From 6e5ff59d433e27af07b66065fa0d67935e300f30 Mon Sep 17 00:00:00 2001 From: Florian Grandel Date: Fri, 10 May 2024 16:32:47 +0200 Subject: [PATCH] samples: bluetooth: central_iso: fix rounding error This change introduces a timing approach that does not accrue rounding errors over time, thereby further improving deterministic behavior of the sample relative to the BLE host's sleep clock. Signed-off-by: Florian Grandel --- samples/bluetooth/central_iso/src/main.c | 26 +++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/samples/bluetooth/central_iso/src/main.c b/samples/bluetooth/central_iso/src/main.c index df3e45041544309..ba6c44d8f2ec046 100644 --- a/samples/bluetooth/central_iso/src/main.c +++ b/samples/bluetooth/central_iso/src/main.c @@ -66,7 +66,7 @@ static void iso_send_sdu(struct k_work *work) net_buf_add_mem(buf, buf_data, len_to_send); - ret = bt_iso_chan_send(&iso_chan, buf, seq_num++); + ret = bt_iso_chan_send(&iso_chan, buf, seq_num); if (ret < 0) { printk("Failed to send ISO data (%d)\n", ret); @@ -83,9 +83,29 @@ static K_WORK_DEFINE(iso_send_sdu_work, iso_send_sdu); static void iso_timer_timeout(struct k_timer *timer) { - ARG_UNUSED(timer); + int64_t cur_tick = sys_clock_tick_get(), next_tick; + static int64_t first_tick = 0; + if (unlikely(first_tick == 0)) { + first_tick = cur_tick; + } + + seq_num++; + + /* iso_send_sdu_work will access seq_num, so be sure to update it + * before submitting the work. + */ k_work_submit(&iso_send_sdu_work); + + /* Calculate the next tick such that that the next measurement will be + * delivered with minimal latency and w/o accruing rounding errors. + */ + next_tick = first_tick + + (((int64_t)seq_num * INTERVAL_US) * + CONFIG_SYS_CLOCK_TICKS_PER_SEC) / + USEC_PER_SEC - + cur_tick; + k_timer_start(timer, K_TICKS(next_tick), K_FOREVER); } static K_TIMER_DEFINE(iso_timer, iso_timer_timeout, NULL); @@ -148,7 +168,7 @@ static void iso_connected(struct bt_iso_chan *chan) seq_num = 0U; /* Start send timer */ - k_timer_start(&iso_timer, K_NO_WAIT, K_USEC(INTERVAL_US)); + k_timer_start(&iso_timer, K_NO_WAIT, K_FOREVER); } static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)