diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h index 66bd71d39e9..89be10c9ba8 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h @@ -53,6 +53,8 @@ struct lll_conn_iso_stream { memq_link_t *link_tx_free; }; +#define LLL_CONN_ISO_EVENT_COUNT_MAX BIT64_MASK(39) + struct lll_conn_iso_group { struct lll_hdr hdr; diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index 79abe60bfb9..4fd61e81514 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -351,6 +351,7 @@ ((enc) ? \ (PDU_MIC_SIZE) : 0), \ (phy)) +#define PDU_CIS_OFFSET_MIN_US 500U struct pdu_adv_adv_ind { uint8_t addr[BDADDR_SIZE]; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index beda9f54557..1f7f4418c4f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -563,7 +563,7 @@ void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle) /* Initialize stream states */ cis->established = 0; cis->teardown = 0; - cis->lll.event_count = 0; + cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.sn = 0; cis->lll.nesn = 0; cis->lll.cie = 0; @@ -732,7 +732,6 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ cis->central.instant = instant; - cis->lll.event_count = -1; cis->lll.next_subevent = 0U; cis->lll.sn = 0U; cis->lll.nesn = 0U; @@ -863,10 +862,13 @@ static void cis_offset_get(struct ll_conn_iso_stream *cis) static void mfy_cis_offset_get(void *param) { + uint32_t elapsed_acl_us, elapsed_cig_us; + uint16_t latency_acl, latency_cig; struct ll_conn_iso_stream *cis; struct ll_conn_iso_group *cig; uint32_t cig_remainder_us; uint32_t acl_remainder_us; + uint32_t cig_interval_us; uint32_t ticks_to_expire; uint32_t ticks_current; uint32_t offset_min_us; @@ -953,6 +955,32 @@ static void mfy_cis_offset_get(void *param) cig_remainder_us + cig->sync_delay - acl_remainder_us - cis->sync_delay; + /* Calculate instant latency */ + /* 32-bits are sufficient as maximum connection interval is 4 seconds, + * and latency counts (typically 3) is low enough to avoid 32-bit + * overflow. Refer to ull_central_iso_cis_offset_get(). + */ + latency_acl = cis->central.instant - ull_conn_event_counter(conn); + elapsed_acl_us = latency_acl * conn->lll.interval * CONN_INT_UNIT_US; + + /* Calculate elapsed CIG intervals until the instant */ + cig_interval_us = cig->iso_interval * ISO_INT_UNIT_US; + latency_cig = DIV_ROUND_UP(elapsed_acl_us, cig_interval_us); + elapsed_cig_us = latency_cig * cig_interval_us; + + /* Compensate for the difference between ACL elapsed vs CIG elapsed */ + offset_min_us += elapsed_cig_us - elapsed_acl_us; + while (offset_min_us > (cig_interval_us + PDU_CIS_OFFSET_MIN_US)) { + offset_min_us -= cig_interval_us; + } + + /* Decrement event_count to compensate for offset_min_us greater than + * CIG interval due to offset being atleast PDU_CIS_OFFSET_MIN_US. + */ + if (offset_min_us > cig_interval_us) { + cis->lll.event_count--; + } + ull_cp_cc_offset_calc_reply(conn, offset_min_us, offset_min_us); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index ef59ac520dd..af17dd9347d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -319,7 +319,7 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, cis->sync_delay = sys_get_le24(ind->cis_sync_delay); cis->offset = cis_offset; memcpy(cis->lll.access_addr, ind->aa, sizeof(ind->aa)); - cis->lll.event_count = -1; + cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.next_subevent = 0U; cis->lll.sn = 0U; cis->lll.nesn = 0U;