This is an automated email from the ASF dual-hosted git repository. andk pushed a commit to branch ll-big-event-drift in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit 2e283db0d21afc2a2d481e6b06851a4db14314b5 Author: Andrzej Kaczmarek <andrzej.kaczma...@codecoup.pl> AuthorDate: Wed Jul 31 11:32:54 2024 +0200 nimble/ll: Fix event drift in event start time calculations Updating BIG event start time by adding interval on every event introduces additional clock drift due to rouding errors on conversion from usecs to ticks. This fixes the problem by using some event time as constant base and timing for subsqeuent events is calculated relative to that event. This eliminates drift due to calculations. To prevent overflows in calculations, base event is changed every 30mins. --- nimble/controller/src/ble_ll_iso_big.c | 50 ++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/nimble/controller/src/ble_ll_iso_big.c b/nimble/controller/src/ble_ll_iso_big.c index e41f3f94..e2a7790c 100644 --- a/nimble/controller/src/ble_ll_iso_big.c +++ b/nimble/controller/src/ble_ll_iso_big.c @@ -134,6 +134,9 @@ struct ble_ll_iso_big { uint32_t sync_delay; uint32_t event_start; uint8_t event_start_us; + uint32_t anchor_base_ticks; + uint8_t anchor_base_rem_us; + uint16_t anchor_offset; struct ble_ll_sched_item sch; struct ble_npl_event event_done; @@ -168,6 +171,34 @@ static uint8_t bis_pool_free = BIS_POOL_SIZE; static struct ble_ll_iso_big *big_pending; static struct ble_ll_iso_big *big_active; +static void big_sched_set(struct ble_ll_iso_big *big) +{ + uint32_t offset_us; + + big->sch.start_time = big->anchor_base_ticks; + big->sch.remainder = big->anchor_base_rem_us; + + offset_us = big->anchor_offset * big->iso_interval * 1250; + + ble_ll_tmr_add(&big->sch.start_time, &big->sch.remainder, offset_us); + + /* Reset anchor base every 30mins to avoid overflows in calculations later. */ + if (offset_us >= 30 * 60 * 1000000) { + big->anchor_base_ticks = big->sch.start_time; + big->anchor_base_rem_us = big->sch.remainder; + big->anchor_offset = 0; + } + + big->sch.end_time = big->sch.start_time + + ble_ll_tmr_u2t_up(big->sync_delay) + 1; + big->sch.start_time -= g_ble_ll_sched_offset_ticks; + + if (big->control_active) { + /* XXX calculate proper time */ + big->sch.end_time += 10; + } +} + struct ble_ll_iso_bis * ble_ll_iso_big_find_bis_by_handle(uint16_t conn_handle) { @@ -536,19 +567,13 @@ ble_ll_iso_big_event_done(struct ble_ll_iso_big *big) } } - /* XXX precalculate some data here? */ + big->anchor_offset++; + big_sched_set(big); - ble_ll_tmr_add(&big->sch.start_time, &big->sch.remainder, - big->iso_interval * 1250); big->sch.end_time = big->sch.start_time + ble_ll_tmr_u2t_up(big->sync_delay) + 1; big->sch.start_time -= g_ble_ll_sched_offset_ticks; - if (big->control_active) { - /* XXX fixme */ - big->sch.end_time += 10; - } - /* XXX this should always succeed since we preempt anything for now */ rc = ble_ll_sched_iso_big(&big->sch, 0, 0); assert(rc == 0); @@ -1107,10 +1132,11 @@ ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, big_event_fixed = 1; } - big->sch.start_time = big_time; - big->sch.remainder = 0; - big->sch.end_time = big->sch.start_time + sync_delay_ticks + 1; - big->sch.start_time -= g_ble_ll_sched_offset_ticks; + big->anchor_base_ticks = big_time; + big->anchor_base_rem_us = 0; + big->anchor_offset = 0; + + big_sched_set(big); rc = ble_ll_sched_iso_big(&big->sch, 1, big_event_fixed); if (rc < 0) {