Skip to content

Bluetooth: Controller: Align PAST sync_offset_us calc with CIS_IND#35

Draft
cvinayak with Copilot wants to merge 2 commits into
mainfrom
copilot/check-instant-latency-calculation
Draft

Bluetooth: Controller: Align PAST sync_offset_us calc with CIS_IND#35
cvinayak with Copilot wants to merge 2 commits into
mainfrom
copilot/check-instant-latency-calculation

Conversation

Copilot AI commented Jul 4, 2026

Copy link
Copy Markdown

ull_sync_setup_from_sync_transfer() adjusted sync_offset_us from the received LL_PERIODIC_SYNC_IND PDU using a signed int16_t narrowing of an unsigned subtraction, and didn't cleanly cover the case where the PDU's Connection Event Counter refers to a connection event already in the past relative to the current CE at processing time on the peripheral.

Changes

  • ull_sync.cull_sync_setup_from_sync_transfer(): adopt the CIS_IND LLCP instant_latency idiom for the CE delta.
    • Parameter: int16_t conn_evt_offsetuint16_t conn_evt_latency, computed unsigned/wrap-safe as (current − reference) & 0xFFFF, mirroring rp_cc_check_instant_by_counter() / lp_cc_check_instant() in ull_llcp_cc.c.
    • Dispatch on conn_evt_latency <= 0x7FFFU:
      • Past reference CE (0..0x7FFF): subtract conn_evt_latency * conn_interval_us from sync_offset_us; if that drives the anchor into the past, advance lll->event_counter by the required whole number of PA intervals and set sync_offset_us to the remainder.
      • Future reference CE (0x8000..0xFFFF): add (0x10000 − conn_evt_latency) * conn_interval_us.
  • ull_sync_transfer_received(): pass (conn_evt_current − conn_event_count) & 0xFFFFU to match.

Illustration

/* Was: signed, implementation-defined narrowing, mixed int64/uint32 arithmetic */
int16_t conn_evt_offset = conn_event_count - conn_evt_current;
if ((int64_t)sync_offset_us + (int64_t)conn_evt_offset * conn_interval_us < 0) { ... }

/* Now: unsigned wrap-safe, CIS_IND-style */
uint16_t conn_evt_latency = (conn_evt_current - conn_event_count) & 0xFFFFU;
if (conn_evt_latency <= 0x7FFFU) {
    /* reference CE reached/passed - deduct elapsed time from sync_offset_us */
} else {
    /* reference CE still in the future - add remaining time */
}

Behavior is preserved for every input in the range the previous signed path could represent.

Copilot AI added 2 commits July 4, 2026 06:39
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
@cvinayak cvinayak force-pushed the copilot/check-instant-latency-calculation branch from 13b5de2 to dbe7675 Compare July 4, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants