Skip to content

Commit e5e7395

Browse files
committed
samples: Bluetooth: ISO: Update conn and adv intervals
Update the connection and advertising intervals of the broadcast and connected ISO samples (including benchmark samples) to work better with the selected SDU intervals and the resulting ISO intervals. For the ISO connected benchmark the order of CIG and ACl has changed, so that we create the CIG before connecting the ACL for the purpose of providing as much information as possible to the controller. Signed-off-by: Emil Gydesen <[email protected]>
1 parent 054d60f commit e5e7395

File tree

4 files changed

+116
-14
lines changed

4 files changed

+116
-14
lines changed

samples/bluetooth/iso_broadcast/src/main.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
/*
2-
* Copyright (c) 2021 Nordic Semiconductor ASA
2+
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
6+
#include <stddef.h>
7+
#include <stdint.h>
68

79
#include <zephyr/bluetooth/bluetooth.h>
10+
#include <zephyr/bluetooth/gap.h>
811
#include <zephyr/bluetooth/iso.h>
912
#include <zephyr/sys/byteorder.h>
1013

@@ -88,6 +91,20 @@ static const struct bt_data ad[] = {
8891

8992
int main(void)
9093
{
94+
/* Some controllers work best while Extended Advertising interval to be a multiple
95+
* of the ISO Interval minus 10 ms (max. advertising random delay). This is
96+
* required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the
97+
* Broadcast ISO radio events.
98+
* For 10ms SDU interval a extended advertising interval of 60 - 10 = 50 is suitable
99+
*/
100+
const uint16_t adv_interval_ms = 60U;
101+
const uint16_t ext_adv_interval_ms = adv_interval_ms - 10U;
102+
const struct bt_le_adv_param *ext_adv_param = BT_LE_ADV_PARAM(
103+
BT_LE_ADV_OPT_EXT_ADV, BT_GAP_MS_TO_ADV_INTERVAL(ext_adv_interval_ms),
104+
BT_GAP_MS_TO_ADV_INTERVAL(ext_adv_interval_ms), NULL);
105+
const struct bt_le_per_adv_param *per_adv_param = BT_LE_PER_ADV_PARAM(
106+
BT_GAP_MS_TO_PER_ADV_INTERVAL(adv_interval_ms),
107+
BT_GAP_MS_TO_PER_ADV_INTERVAL(adv_interval_ms), BT_LE_PER_ADV_OPT_NONE);
91108
uint32_t timeout_counter = INITIAL_TIMEOUT_COUNTER;
92109
struct bt_le_ext_adv *adv;
93110
struct bt_iso_big *big;
@@ -106,7 +123,7 @@ int main(void)
106123
}
107124

108125
/* Create a non-connectable advertising set */
109-
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, &adv);
126+
err = bt_le_ext_adv_create(ext_adv_param, NULL, &adv);
110127
if (err) {
111128
printk("Failed to create advertising set (err %d)\n", err);
112129
return 0;
@@ -120,7 +137,7 @@ int main(void)
120137
}
121138

122139
/* Set periodic advertising parameters */
123-
err = bt_le_per_adv_set_param(adv, BT_LE_PER_ADV_DEFAULT);
140+
err = bt_le_per_adv_set_param(adv, per_adv_param);
124141
if (err) {
125142
printk("Failed to set periodic advertising parameters"
126143
" (err %d)\n", err);

samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
/*
2-
* Copyright (c) 2021 Nordic Semiconductor ASA
2+
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

77
#include <ctype.h>
88
#include <stdlib.h>
9+
#include <stdint.h>
10+
11+
#include <zephyr/bluetooth/gap.h>
912
#include <zephyr/console/console.h>
1013
#include <zephyr/bluetooth/bluetooth.h>
1114
#include <zephyr/bluetooth/iso.h>
1215
#include <zephyr/sys/byteorder.h>
1316

1417
#include <zephyr/logging/log.h>
18+
#include <zephyr/sys/util.h>
19+
#include <zephyr/sys_clock.h>
1520
LOG_MODULE_REGISTER(iso_broadcast_broadcaster, LOG_LEVEL_DBG);
1621

1722
#define DEFAULT_BIS_RTN 2
@@ -613,13 +618,60 @@ static void iso_timer_timeout(struct k_work *work)
613618
seq_num++;
614619
}
615620

621+
static uint16_t calc_adv_interval(uint32_t sdu_interval_us)
622+
{
623+
/* Default to 6 times the SDU interval and then reduce until we reach a reasonable maximum
624+
* advertising interval (BT_GAP_PER_ADV_SLOW_INT_MAX)
625+
* sdu_interval_us can never be larger than 1048ms (BT_ISO_SDU_INTERVAL_MAX)
626+
* so a multiple of it will always be possible to keep under BT_GAP_PER_ADV_SLOW_INT_MAX
627+
* (1200ms)
628+
*/
629+
630+
/* Convert from microseconds to advertising interval units (0.625ms)*/
631+
const uint32_t interval = BT_GAP_US_TO_ADV_INTERVAL(sdu_interval_us);
632+
uint32_t adv_interval = interval * 6U;
633+
634+
/* Ensure that the adv interval is between BT_GAP_PER_ADV_FAST_INT_MIN_1 and
635+
* BT_GAP_PER_ADV_SLOW_INT_MAX for the sake of interopability
636+
*/
637+
while (adv_interval < BT_GAP_PER_ADV_FAST_INT_MIN_1) {
638+
adv_interval += interval;
639+
}
640+
641+
while (adv_interval > BT_GAP_PER_ADV_SLOW_INT_MAX) {
642+
adv_interval -= interval;
643+
}
644+
645+
/* If we cannot convert back then it's not a lossless conversion */
646+
if (big_create_param.framing == BT_ISO_FRAMING_UNFRAMED &&
647+
BT_GAP_ADV_INTERVAL_TO_US(interval) != sdu_interval_us) {
648+
LOG_INF("Advertising interval of 0x04%x is not a multiple of the advertising "
649+
"interval unit (0.625 ms) and may be subpar. Suggest to adjust SDU "
650+
"interval %u to be a multiple of 0.625 ms",
651+
adv_interval, sdu_interval_us);
652+
}
653+
654+
return adv_interval;
655+
}
656+
616657
static int create_big(struct bt_le_ext_adv **adv, struct bt_iso_big **big)
617658
{
659+
/* Some controllers work best when Extended Advertising interval is a multiple
660+
* of the ISO Interval minus 10 ms (max. advertising random delay). This is
661+
* required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the
662+
* Broadcast ISO radio events.
663+
*/
664+
const uint16_t adv_interval = calc_adv_interval(big_create_param.interval);
665+
const uint16_t ext_adv_interval = adv_interval - BT_GAP_MS_TO_ADV_INTERVAL(10U);
666+
const struct bt_le_adv_param *ext_adv_param =
667+
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, ext_adv_interval, ext_adv_interval, NULL);
668+
const struct bt_le_per_adv_param *per_adv_param =
669+
BT_LE_PER_ADV_PARAM(adv_interval, adv_interval, BT_LE_PER_ADV_OPT_NONE);
618670
int err;
619671

620672
/* Create a non-connectable advertising set */
621673
LOG_INF("Creating Extended Advertising set");
622-
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
674+
err = bt_le_ext_adv_create(ext_adv_param, NULL, adv);
623675
if (err != 0) {
624676
LOG_ERR("Failed to create advertising set (err %d)", err);
625677
return err;
@@ -634,7 +686,7 @@ static int create_big(struct bt_le_ext_adv **adv, struct bt_iso_big **big)
634686

635687
LOG_INF("Setting Periodic Advertising parameters");
636688
/* Set periodic advertising parameters */
637-
err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
689+
err = bt_le_per_adv_set_param(*adv, per_adv_param);
638690
if (err != 0) {
639691
LOG_ERR("Failed to set periodic advertising parameters (err %d)",
640692
err);

samples/bluetooth/iso_central/src/main.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
* Copyright (c) 2021 2021 Nordic Semiconductor ASA
2+
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#include <zephyr/bluetooth/gap.h>
78
#include <zephyr/types.h>
89
#include <stddef.h>
910
#include <errno.h>
@@ -90,6 +91,9 @@ static void iso_timer_timeout(struct k_work *work)
9091
static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
9192
struct net_buf_simple *ad)
9293
{
94+
const struct bt_le_conn_param *conn_param =
95+
BT_LE_CONN_PARAM(BT_GAP_MS_TO_CONN_INTERVAL(60), BT_GAP_MS_TO_CONN_INTERVAL(60), 0,
96+
BT_GAP_MS_TO_CONN_TIMEOUT(4000));
9397
char addr_str[BT_ADDR_LE_STR_LEN];
9498
int err;
9599

@@ -115,8 +119,7 @@ static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
115119
return;
116120
}
117121

118-
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
119-
&default_conn);
122+
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, conn_param, &default_conn);
120123
if (err) {
121124
printk("Create conn to %s failed (%u)\n", addr_str, err);
122125
start_scan();

samples/bluetooth/iso_connected_benchmark/src/main.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@
55
*/
66

77
#include <ctype.h>
8+
#include <zephyr/bluetooth/conn.h>
9+
#include <zephyr/bluetooth/gap.h>
810
#include <zephyr/kernel.h>
911
#include <string.h>
12+
#include <stdint.h>
1013
#include <stdlib.h>
14+
#include <zephyr/sys/util.h>
15+
#include <zephyr/sys_clock.h>
1116
#include <zephyr/types.h>
1217

1318

@@ -1046,6 +1051,12 @@ static int change_central_settings(void)
10461051

10471052
static int central_create_connection(void)
10481053
{
1054+
/* Give the controller a large range of intervals to pick from. In this benchmark sample we
1055+
* want to prioritize ISO over ACL, but will leave the actual choice up to the controller.
1056+
*/
1057+
const struct bt_le_conn_param *conn_param =
1058+
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_MS_TO_CONN_INTERVAL(500U), 0,
1059+
BT_GAP_MS_TO_CONN_TIMEOUT(4000));
10491060
int err;
10501061

10511062
advertiser_found = false;
@@ -1071,8 +1082,7 @@ static int central_create_connection(void)
10711082
}
10721083

10731084
LOG_INF("Connecting");
1074-
err = bt_conn_le_create(&adv_addr, BT_CONN_LE_CREATE_CONN,
1075-
BT_LE_CONN_PARAM_DEFAULT, &default_conn);
1085+
err = bt_conn_le_create(&adv_addr, BT_CONN_LE_CREATE_CONN, conn_param, &default_conn);
10761086
if (err != 0) {
10771087
LOG_ERR("Create connection failed: %d", err);
10781088
return err;
@@ -1089,7 +1099,6 @@ static int central_create_connection(void)
10891099

10901100
static int central_create_cig(void)
10911101
{
1092-
struct bt_iso_connect_param connect_param[CONFIG_BT_ISO_MAX_CHAN];
10931102
int err;
10941103

10951104
iso_conn_start_time = 0;
@@ -1102,6 +1111,16 @@ static int central_create_cig(void)
11021111
return err;
11031112
}
11041113

1114+
return 0;
1115+
}
1116+
1117+
static int central_connect_cis(void)
1118+
{
1119+
struct bt_iso_connect_param connect_param[CONFIG_BT_ISO_MAX_CHAN];
1120+
int err;
1121+
1122+
iso_conn_start_time = 0;
1123+
11051124
LOG_INF("Connecting ISO channels");
11061125

11071126
for (int i = 0; i < cig_create_param.num_cis; i++) {
@@ -1205,15 +1224,26 @@ static int run_central(void)
12051224
}
12061225
}
12071226

1227+
/* Creating the CIG before connecting verified that it's possible before establishing a
1228+
* connection, while also providing the controller information about our use case before
1229+
* creating the connection, which should provide additional information to the controller
1230+
* about which connection interval to use
1231+
*/
1232+
err = central_create_cig();
1233+
if (err != 0) {
1234+
LOG_ERR("Failed to create CIG: %d", err);
1235+
return err;
1236+
}
1237+
12081238
err = central_create_connection();
12091239
if (err != 0) {
12101240
LOG_ERR("Failed to create connection: %d", err);
12111241
return err;
12121242
}
12131243

1214-
err = central_create_cig();
1244+
err = central_connect_cis();
12151245
if (err != 0) {
1216-
LOG_ERR("Failed to create CIG or connect CISes: %d", err);
1246+
LOG_ERR("Failed to connect CISes: %d", err);
12171247
return err;
12181248
}
12191249

0 commit comments

Comments
 (0)