Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth: Controller: Separate SDU interval for C_to_P and P_to_C #76453

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion subsys/bluetooth/controller/ll_sw/lll.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
#define SCAN_INT_UNIT_US 625U
#define CONN_INT_UNIT_US 1250U
#define ISO_INT_UNIT_US CONN_INT_UNIT_US
#define PERIODIC_INT_UNIT_US 1250U
#define PERIODIC_INT_UNIT_US CONN_INT_UNIT_US

#define ISO_INTERVAL_TO_US(interval) ((interval) * ISO_INT_UNIT_US)

/* Timeout for Host to accept/reject cis create request */
/* See BTCore5.3, 4.E.6.7 - Default value 0x1f40 * 625us */
Expand Down
71 changes: 52 additions & 19 deletions subsys/bluetooth/controller/ll_sw/ull_central_iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ static void mfy_cis_offset_get(void *param);
static void ticker_op_cb(uint32_t status, void *param);
#endif /* CONFIG_BT_CTLR_CENTRAL_SPACING == 0 */

static void set_bn_max_pdu(bool framed, uint32_t iso_interval,
uint32_t sdu_interval, uint16_t max_sdu, uint8_t *bn,
uint8_t *max_pdu);
static uint32_t iso_interval_adjusted_bn_max_pdu_get(bool framed, uint32_t iso_interval,
uint32_t iso_interval_cig,
uint32_t sdu_interval,
uint16_t max_sdu, uint8_t *bn,
uint8_t *max_pdu);
static uint8_t ll_cig_parameters_validate(void);
static uint8_t ll_cis_parameters_validate(uint8_t cis_idx, uint8_t cis_id,
uint16_t c_sdu, uint16_t p_sdu,
Expand Down Expand Up @@ -154,6 +156,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
uint16_t cis_created_handles[STREAMS_PER_GROUP];
struct ll_conn_iso_stream *cis;
struct ll_conn_iso_group *cig;
uint32_t iso_interval_cig_us;
uint32_t iso_interval_us;
uint32_t cig_sync_delay;
uint32_t max_se_length;
Expand Down Expand Up @@ -228,19 +231,19 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
* handle the throughput. For unframed these must be divisible, if they're not,
* framed mode must be forced.
*/
cig->iso_interval = cig->c_sdu_interval / ISO_INT_UNIT_US;
iso_interval_us = cig->c_sdu_interval;

if (cig->iso_interval < BT_HCI_ISO_INTERVAL_MIN) {
if (iso_interval_us < ISO_INTERVAL_TO_US(BT_HCI_ISO_INTERVAL_MIN)) {
/* ISO_Interval is below minimum (5 ms) */
cig->iso_interval = BT_HCI_ISO_INTERVAL_MIN;
iso_interval_us = ISO_INTERVAL_TO_US(BT_HCI_ISO_INTERVAL_MIN);
}

#if defined(CONFIG_BT_CTLR_CONN_ISO_AVOID_SEGMENTATION)
/* Check if this is a HAP usecase which requires higher link bandwidth to ensure
* segmentation is not invoked in ISO-AL.
Comment on lines 242 to 243
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to this PR, but how can the controller determine which LE Audio profile is being used? :s

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, @wopu-ot ?

*/
if (cig->central.framing && cig->c_sdu_interval == 10000U) {
cig->iso_interval = 6; /* 7500 us */
iso_interval_us = 7500U; /* us */
}
#endif

Expand All @@ -250,10 +253,11 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
*/
force_framed = true;
}
} else {
iso_interval_us = cig->iso_interval * ISO_INT_UNIT_US;
Thalley marked this conversation as resolved.
Show resolved Hide resolved
}

iso_interval_us = cig->iso_interval * ISO_INT_UNIT_US;
cig->lll.iso_interval_us = iso_interval_us;
iso_interval_cig_us = iso_interval_us;

lll_hdr_init(&cig->lll, cig);
max_se_length = 0U;
Expand Down Expand Up @@ -360,29 +364,43 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
* directions
*/
if (tx) {
uint32_t iso_interval_adjust_us;
uint8_t max_pdu;
uint8_t bn;

bn = cis->lll.tx.bn;
max_pdu = cis->lll.tx.max_pdu;
set_bn_max_pdu(cis->framed, iso_interval_us,
cig->c_sdu_interval,
cis->c_max_sdu, &bn, &max_pdu);
iso_interval_adjust_us =
iso_interval_adjusted_bn_max_pdu_get(cis->framed,
iso_interval_us, iso_interval_cig_us,
cig->c_sdu_interval, cis->c_max_sdu, &bn, &max_pdu);
if (iso_interval_adjust_us != iso_interval_us) {
iso_interval_us = iso_interval_adjust_us;

goto ll_cig_parameters_commit_retry;
}
cis->lll.tx.bn = bn;
cis->lll.tx.max_pdu = max_pdu;
} else {
cis->lll.tx.bn = 0U;
}

if (rx) {
uint32_t iso_interval_adjust_us;
Thalley marked this conversation as resolved.
Show resolved Hide resolved
uint8_t max_pdu;
uint8_t bn;

bn = cis->lll.rx.bn;
max_pdu = cis->lll.rx.max_pdu;
set_bn_max_pdu(cis->framed, iso_interval_us,
cig->p_sdu_interval,
cis->p_max_sdu, &bn, &max_pdu);
iso_interval_adjust_us =
iso_interval_adjusted_bn_max_pdu_get(cis->framed,
iso_interval_us, iso_interval_cig_us,
cig->p_sdu_interval, cis->p_max_sdu, &bn, &max_pdu);
if (iso_interval_adjust_us != iso_interval_us) {
iso_interval_us = iso_interval_adjust_us;

goto ll_cig_parameters_commit_retry;
}
cis->lll.rx.bn = bn;
cis->lll.rx.max_pdu = max_pdu;
} else {
Expand All @@ -402,6 +420,9 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
(cis->central.p_rtn + 1) * cis->lll.rx.bn);
}

cig->lll.iso_interval_us = iso_interval_us;
cig->iso_interval = iso_interval_us / ISO_INT_UNIT_US;

handle_iter = UINT16_MAX;
total_time = 0U;

Expand Down Expand Up @@ -1170,9 +1191,11 @@ static void ticker_op_cb(uint32_t status, void *param)
}
#endif /* CONFIG_BT_CTLR_CENTRAL_SPACING == 0 */

static void set_bn_max_pdu(bool framed, uint32_t iso_interval,
uint32_t sdu_interval, uint16_t max_sdu, uint8_t *bn,
uint8_t *max_pdu)
static uint32_t iso_interval_adjusted_bn_max_pdu_get(bool framed, uint32_t iso_interval,
uint32_t iso_interval_cig,
uint32_t sdu_interval,
uint16_t max_sdu, uint8_t *bn,
uint8_t *max_pdu)
{
if (framed) {
uint32_t max_drift_us;
Expand Down Expand Up @@ -1222,13 +1245,23 @@ static void set_bn_max_pdu(bool framed, uint32_t iso_interval,
}
} else {
/* For unframed, ISO_Interval must be N x SDU_Interval */
LL_ASSERT(iso_interval % sdu_interval == 0);
if ((iso_interval % sdu_interval) != 0) {
/* The requested ISO interval is doubled until it is multiple of
* SDU_interval.
* For example, between 7.5 and 10 ms, 7.5 is added in iterations to reach
* 30 ms ISO interval; or between 10 and 7.5 ms, 10 is added in iterations
* to reach the same 30 ms ISO interval.
*/
iso_interval += iso_interval_cig;
}

/* Core 5.3 Vol 6, Part G section 2.1:
* BN >= ceil(Max_SDU/Max_PDU * ISO_Interval/SDU_Interval)
*/
*bn = DIV_ROUND_UP(max_sdu * iso_interval, (*max_pdu) * sdu_interval);
}

return iso_interval;
}

static uint8_t ll_cig_parameters_validate(void)
Expand Down
Loading