Draft
Bluetooth: Controller: Align PAST sync_offset_us calc with CIS_IND#35
Conversation
Copilot created this pull request from a session on behalf of
cvinayak
July 4, 2026 02:29
View session
The `ull_sync_setup_from_sync_transfer()` function computed the adjustment to `sync_offset_us` from the `Connection Event Counter` carried by LL_PERIODIC_SYNC_IND using a signed difference (`conn_event_count - conn_evt_current`) narrowed to `int16_t`. The narrowing conversion of an unsigned subtraction result is implementation-defined, and the resulting arithmetic mixed signed and unsigned types. Refactor the computation to mirror the CIS_IND LLCP procedure handling of `instant_latency` in `rp_cc_check_instant_by_counter()` and `lp_cc_check_instant()`: compute the difference as an unsigned wrap-safe value `(conn_evt_current - conn_event_count) & 0xFFFF` and dispatch on the `<= 0x7FFF` range test. Also explicitly handle both directions: - Reference connection event in the past (peripheral processes the LL_PERIODIC_SYNC_IND at a connection event later than the one indicated by the PDU): deduct the elapsed time from `sync_offset_us`; when the resulting anchor would fall into the past, advance the periodic advertising event counter by the required whole number of periodic advertising intervals. - Reference connection event in the future: add the remaining time to `sync_offset_us`. The behavior for a valid signed offset in the range supported by the previous implementation is preserved, while the arithmetic is now portable and matches the CIS_IND pattern. Assisted-by: Claude:claude-sonnet-4.6
In ull_sync_setup_from_sync_transfer() the ticker was started using only conn->llcp.prep.ticks_at_expire as the anchor and dropping the paired conn->llcp.prep.remainder. On nRF52 the LFCLK ticker runs at 32.768 kHz, so one tick is ~30.5 us and the fractional-microsecond remainder that positions the ACL prepare within a tick is significant. Ignoring it means the PAST-established periodic sync anchor can be off by up to almost one tick, degrading first-anchor accuracy and initial window widening compensation. Fold the ACL prepare remainder into sync_offset_us using hal_ticker_remove_jitter() (the same pattern CIS uses in cig_offset_calc()), and start the ticker with ticker_start_us() so the sub-tick fractional component of the offset is preserved via HAL_TICKER_REMAINDER(sync_offset_us). Assisted-by: Claude:claude-sonnet-4.6
13b5de2 to
dbe7675
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ull_sync_setup_from_sync_transfer()adjustedsync_offset_usfrom the receivedLL_PERIODIC_SYNC_INDPDU using a signedint16_tnarrowing of an unsigned subtraction, and didn't cleanly cover the case where the PDU'sConnection Event Counterrefers to a connection event already in the past relative to the current CE at processing time on the peripheral.Changes
ull_sync.c—ull_sync_setup_from_sync_transfer(): adopt the CIS_IND LLCPinstant_latencyidiom for the CE delta.int16_t conn_evt_offset→uint16_t conn_evt_latency, computed unsigned/wrap-safe as(current − reference) & 0xFFFF, mirroringrp_cc_check_instant_by_counter()/lp_cc_check_instant()inull_llcp_cc.c.conn_evt_latency <= 0x7FFFU:0..0x7FFF): subtractconn_evt_latency * conn_interval_usfromsync_offset_us; if that drives the anchor into the past, advancelll->event_counterby the required whole number of PA intervals and setsync_offset_usto the remainder.0x8000..0xFFFF): add(0x10000 − conn_evt_latency) * conn_interval_us.ull_sync_transfer_received(): pass(conn_evt_current − conn_event_count) & 0xFFFFUto match.Illustration
Behavior is preserved for every input in the range the previous signed path could represent.