Bluetooth: controller: Implement CSA #2 for SubEvents
Implement the functions required to calculate the SubEvent 1
and SubEvent n mapped channel indices.
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig
index 4d220c2..8fe0335 100644
--- a/subsys/bluetooth/controller/Kconfig
+++ b/subsys/bluetooth/controller/Kconfig
@@ -641,6 +641,11 @@
and will be invoked whenever the controller code encounters
an unrecoverable error.
+config BT_CTLR_TEST
+ bool "Run in-system unit tests"
+ help
+ Run in-system unit tests
+
endif # BT_CTLR
config BT_CTLR_DEBUG_PINS_CPUAPP
diff --git a/subsys/bluetooth/controller/ll_sw/lll_chan.c b/subsys/bluetooth/controller/ll_sw/lll_chan.c
index ffca8d0..fd29837 100644
--- a/subsys/bluetooth/controller/ll_sw/lll_chan.c
+++ b/subsys/bluetooth/controller/ll_sw/lll_chan.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ * Copyright (c) 2018-2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,7 +17,15 @@
static uint8_t chan_sel_remap(uint8_t *chan_map, uint8_t chan_index);
#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
-static uint16_t chan_prn(uint16_t counter, uint16_t chan_id);
+static uint16_t chan_prn_s(uint16_t counter, uint16_t chan_id);
+static uint16_t chan_prn_e(uint16_t counter, uint16_t chan_id);
+
+#if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_SYNC_ISO)
+static uint8_t chan_sel_remap_index(uint8_t *chan_map, uint8_t chan_index);
+static uint16_t chan_prn_subevent_se(uint16_t chan_id,
+ uint16_t *prn_subevent_lu);
+static uint8_t chan_d(uint8_t n);
+#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_SYNC_ISO */
#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
#if defined(CONFIG_BT_CONN)
@@ -58,7 +66,7 @@
uint8_t chan_next;
uint16_t prn_e;
- prn_e = chan_prn(counter, chan_id);
+ prn_e = chan_prn_e(counter, chan_id);
chan_next = prn_e % 37;
if ((chan_map[chan_next >> 3] & (1 << (chan_next % 8))) == 0U) {
@@ -73,6 +81,61 @@
return chan_next;
}
+
+#if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_SYNC_ISO)
+uint8_t lll_chan_iso_event(uint16_t counter, uint16_t chan_id,
+ uint8_t *chan_map, uint8_t chan_count,
+ uint16_t *prn_s, uint16_t *remap_idx)
+{
+ uint8_t chan_idx;
+ uint16_t prn_e;
+
+ *prn_s = chan_prn_s(counter, chan_id);
+ prn_e = *prn_s ^ chan_id;
+ chan_idx = prn_e % 37;
+
+ if ((chan_map[chan_idx >> 3] & (1 << (chan_idx % 8))) == 0U) {
+ *remap_idx = ((uint32_t)chan_count * prn_e) >> 16;
+ chan_idx = chan_sel_remap(chan_map, *remap_idx);
+
+ } else {
+ *remap_idx = chan_sel_remap_index(chan_map, chan_idx);
+ }
+
+ return chan_idx;
+}
+
+uint8_t lll_chan_iso_subevent(uint16_t chan_id, uint8_t *chan_map,
+ uint8_t chan_count, uint16_t *prn_subevent_lu,
+ uint16_t *remap_idx)
+{
+ uint16_t prn_subevent_se;
+ uint8_t chan_idx;
+ uint8_t d;
+ uint8_t x;
+
+ prn_subevent_se = chan_prn_subevent_se(chan_id, prn_subevent_lu);
+
+ d = chan_d(chan_count);
+ if ((chan_count + 1) > (d << 1)) {
+ x = (chan_count + 1) - (d << 1);
+ } else {
+ x = 0;
+ }
+
+ chan_idx = ((((uint32_t)prn_subevent_se * x) >> 16) +
+ d + *remap_idx) % chan_count;
+
+ if ((chan_map[chan_idx >> 3] & (1 << (chan_idx % 8))) == 0U) {
+ *remap_idx = chan_idx;
+ chan_idx = chan_sel_remap(chan_map, *remap_idx);
+ } else {
+ *remap_idx = chan_idx;
+ }
+
+ return chan_idx;
+}
+#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_SYNC_ISO */
#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
static uint8_t chan_sel_remap(uint8_t *chan_map, uint8_t chan_index)
@@ -110,33 +173,6 @@
}
#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
-#if defined(RADIO_UNIT_TEST)
-void lll_chan_sel_2_ut(void)
-{
- uint8_t chan_map_1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x1F};
- uint8_t chan_map_2[] = {0x00, 0x06, 0xE0, 0x00, 0x1E};
- uint8_t m;
-
- m = chan_sel_2(1, 0x305F, chan_map_1, 37);
- LL_ASSERT(m == 20U);
-
- m = chan_sel_2(2, 0x305F, chan_map_1, 37);
- LL_ASSERT(m == 6U);
-
- m = chan_sel_2(3, 0x305F, chan_map_1, 37);
- LL_ASSERT(m == 21U);
-
- m = chan_sel_2(6, 0x305F, chan_map_2, 9);
- LL_ASSERT(m == 23U);
-
- m = chan_sel_2(7, 0x305F, chan_map_2, 9);
- LL_ASSERT(m == 9U);
-
- m = chan_sel_2(8, 0x305F, chan_map_2, 9);
- LL_ASSERT(m == 34U);
-}
-#endif /* RADIO_UNIT_TEST */
-
/* Attribution:
* http://graphics.stanford.edu/%7Eseander/bithacks.html#ReverseByteWith32Bits
*/
@@ -158,20 +194,306 @@
return ((uint32_t)a * 17U + b) & 0xFFFF;
}
-static uint16_t chan_prn(uint16_t counter, uint16_t chan_id)
+static uint16_t chan_prn_s(uint16_t counter, uint16_t chan_id)
{
uint8_t iterate;
- uint16_t prn_e;
+ uint16_t prn_s;
- prn_e = counter ^ chan_id;
+ prn_s = counter ^ chan_id;
for (iterate = 0U; iterate < 3; iterate++) {
- prn_e = chan_perm(prn_e);
- prn_e = chan_mam(prn_e, chan_id);
+ prn_s = chan_perm(prn_s);
+ prn_s = chan_mam(prn_s, chan_id);
}
+ return prn_s;
+}
+
+static uint16_t chan_prn_e(uint16_t counter, uint16_t chan_id)
+{
+ uint16_t prn_e;
+
+ prn_e = chan_prn_s(counter, chan_id);
prn_e ^= chan_id;
return prn_e;
}
+
+#if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_SYNC_ISO)
+static uint8_t chan_sel_remap_index(uint8_t *chan_map, uint8_t chan_index)
+{
+ uint8_t octet_count;
+ uint8_t remap_index;
+
+ remap_index = 0U;
+ octet_count = 5U;
+ while (octet_count--) {
+ uint8_t octet;
+ uint8_t bit_count;
+
+ octet = *chan_map;
+ bit_count = 8U;
+ while (bit_count--) {
+ if (!chan_index) {
+ return remap_index;
+ }
+ chan_index--;
+
+ if (octet & BIT(0)) {
+ remap_index++;
+ }
+ octet >>= 1;
+ }
+
+ chan_map++;
+ }
+
+ return 0;
+}
+
+static uint16_t chan_prn_subevent_se(uint16_t chan_id,
+ uint16_t *prn_subevent_lu)
+{
+ uint16_t prn_subevent_se;
+ uint16_t lu;
+
+ lu = *prn_subevent_lu;
+ lu = chan_perm(lu);
+ lu = chan_mam(lu, chan_id);
+
+ *prn_subevent_lu = lu;
+
+ prn_subevent_se = lu ^ chan_id;
+
+ return prn_subevent_se;
+}
+
+static uint8_t chan_d(uint8_t n)
+{
+ uint8_t x, y;
+
+ if (n > 5) {
+ x = n - 5;
+ } else {
+ x = 0;
+ }
+
+ if (n > 10) {
+ y = (n - 10) >> 1;
+ } else {
+ y = 0;
+ }
+
+ return MAX(1, MAX(MIN(3, x), MIN(11, y)));
+}
+#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_SYNC_ISO */
+
+#if defined(CONFIG_BT_CTLR_TEST)
+void lll_chan_sel_2_ut(void)
+{
+ uint8_t chan_map_1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x1F};
+ uint8_t chan_map_2[] = {0x00, 0x06, 0xE0, 0x00, 0x1E};
+ uint8_t m;
+
+ m = lll_chan_sel_2(0, 0x305F, chan_map_1, 37);
+ LL_ASSERT(m == 25U);
+
+ m = lll_chan_sel_2(1, 0x305F, chan_map_1, 37);
+ LL_ASSERT(m == 20U);
+
+ m = lll_chan_sel_2(2, 0x305F, chan_map_1, 37);
+ LL_ASSERT(m == 6U);
+
+ m = lll_chan_sel_2(3, 0x305F, chan_map_1, 37);
+ LL_ASSERT(m == 21U);
+
+ m = lll_chan_sel_2(6, 0x305F, chan_map_2, 9);
+ LL_ASSERT(m == 23U);
+
+ m = lll_chan_sel_2(7, 0x305F, chan_map_2, 9);
+ LL_ASSERT(m == 9U);
+
+ m = lll_chan_sel_2(8, 0x305F, chan_map_2, 9);
+ LL_ASSERT(m == 34U);
+
+
+
+#if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_SYNC_ISO)
+ uint16_t prn_subevent_lu;
+ uint16_t prn_subevent_se;
+ uint16_t remap_idx;
+ uint16_t prn_s;
+
+ /* BIS subevent 2, event counter 0, test prnSubEvent_se */
+ prn_s = 56857 ^ 0x305F;
+ prn_subevent_lu = prn_s;
+ prn_subevent_se = chan_prn_subevent_se(0x305F, &prn_subevent_lu);
+ LL_ASSERT(prn_subevent_se == 11710);
+
+ /* BIS subevent 3, event counter 0 */
+ prn_subevent_se = chan_prn_subevent_se(0x305F, &prn_subevent_lu);
+ LL_ASSERT(prn_subevent_se == 16649);
+
+ /* BIS subevent 4, event counter 0 */
+ prn_subevent_se = chan_prn_subevent_se(0x305F, &prn_subevent_lu);
+ LL_ASSERT(prn_subevent_se == 38198);
+
+
+
+ /* BIS subevent 1, event counter 0 */
+ m = lll_chan_iso_event(0, 0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT((prn_s ^ 0x305F) == 56857);
+ LL_ASSERT(m == 25U);
+ LL_ASSERT(remap_idx == 25U);
+
+ /* BIS subvent 2 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 1U);
+ LL_ASSERT(m == 1U);
+
+ /* BIS subvent 3 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 16U);
+ LL_ASSERT(m == 16U);
+
+ /* BIS subvent 4 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 36U);
+ LL_ASSERT(m == 36U);
+
+
+ /* BIS subevent 1, event counter 1 */
+ m = lll_chan_iso_event(1, 0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT((prn_s ^ 0x305F) == 1685);
+ LL_ASSERT(m == 20U);
+ LL_ASSERT(remap_idx == 20U);
+
+ /* BIS subvent 2 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 36U);
+ LL_ASSERT(m == 36U);
+
+ /* BIS subvent 3 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 12U);
+ LL_ASSERT(m == 12U);
+
+ /* BIS subvent 4 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 34U);
+ LL_ASSERT(m == 34U);
+
+
+ /* BIS subevent 1, event counter 2 */
+ m = lll_chan_iso_event(2, 0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT((prn_s ^ 0x305F) == 38301);
+ LL_ASSERT(m == 6U);
+ LL_ASSERT(remap_idx == 6U);
+
+ /* BIS subvent 2 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 18U);
+ LL_ASSERT(m == 18U);
+
+ /* BIS subvent 3 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 32U);
+ LL_ASSERT(m == 32U);
+
+ /* BIS subvent 4 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 21U);
+ LL_ASSERT(m == 21U);
+
+
+ /* BIS subevent 1, event counter 3 */
+ m = lll_chan_iso_event(3, 0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT((prn_s ^ 0x305F) == 27475);
+ LL_ASSERT(m == 21U);
+ LL_ASSERT(remap_idx == 21U);
+
+ /* BIS subvent 2 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 4U);
+ LL_ASSERT(m == 4U);
+
+ /* BIS subvent 3 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 22U);
+ LL_ASSERT(m == 22U);
+
+ /* BIS subvent 4 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_1, 37, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 8U);
+ LL_ASSERT(m == 8U);
+
+
+
+ /* BIS subevent 1, event counter 6 */
+ m = lll_chan_iso_event(6, 0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT((prn_s ^ 0x305F) == 10975);
+ LL_ASSERT(remap_idx == 4U);
+ LL_ASSERT(m == 23U);
+
+ /* BIS subvent 2 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 7U);
+ LL_ASSERT(m == 35U);
+
+ /* BIS subvent 3 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 2U);
+ LL_ASSERT(m == 21U);
+
+ /* BIS subvent 4 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 8U);
+ LL_ASSERT(m == 36U);
+
+
+ /* BIS subevent 1, event counter 7 */
+ m = lll_chan_iso_event(7, 0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT((prn_s ^ 0x305F) == 5490);
+ LL_ASSERT(remap_idx == 0U);
+ LL_ASSERT(m == 9U);
+
+ /* BIS subvent 2 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 3U);
+ LL_ASSERT(m == 22U);
+
+ /* BIS subvent 3 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 8U);
+ LL_ASSERT(m == 36U);
+
+ /* BIS subvent 4 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 5U);
+ LL_ASSERT(m == 33U);
+
+
+ /* BIS subevent 1, event counter 8 */
+ m = lll_chan_iso_event(8, 0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT((prn_s ^ 0x305F) == 46970);
+ LL_ASSERT(remap_idx == 6U);
+ LL_ASSERT(m == 34U);
+
+ /* BIS subvent 2 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 0U);
+ LL_ASSERT(m == 9U);
+
+ /* BIS subvent 3 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 5U);
+ LL_ASSERT(m == 33U);
+
+ /* BIS subvent 4 */
+ m = lll_chan_iso_subevent(0x305F, chan_map_2, 9, &prn_s, &remap_idx);
+ LL_ASSERT(remap_idx == 1U);
+ LL_ASSERT(m == 10U);
+#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_SYNC_ISO */
+}
+#endif /* CONFIG_BT_CTLR_TEST */
#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
diff --git a/subsys/bluetooth/controller/ll_sw/lll_chan.h b/subsys/bluetooth/controller/ll_sw/lll_chan.h
index d384650..6105cb6 100644
--- a/subsys/bluetooth/controller/ll_sw/lll_chan.h
+++ b/subsys/bluetooth/controller/ll_sw/lll_chan.h
@@ -1,11 +1,21 @@
/*
- * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ * Copyright (c) 2018-2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
uint8_t lll_chan_sel_1(uint8_t *chan_use, uint8_t hop, uint16_t latency, uint8_t *chan_map,
uint8_t chan_count);
+
uint16_t lll_chan_id(uint8_t *access_addr);
uint8_t lll_chan_sel_2(uint16_t counter, uint16_t chan_id, uint8_t *chan_map,
uint8_t chan_count);
+
+uint8_t lll_chan_iso_event(uint16_t counter, uint16_t chan_id,
+ uint8_t *chan_map, uint8_t chan_count,
+ uint16_t *prn_s, uint16_t *remap_idx);
+uint8_t lll_chan_iso_subevent(uint16_t chan_id, uint8_t *chan_map,
+ uint8_t chan_count, uint16_t *prn_subevent_lu,
+ uint16_t *remap_idx);
+
+void lll_chan_sel_2_ut(void);
diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c
index e93f667..6067399 100644
--- a/subsys/bluetooth/controller/ll_sw/ull.c
+++ b/subsys/bluetooth/controller/ll_sw/ull.c
@@ -34,6 +34,7 @@
#include "lll/lll_adv_types.h"
#include "lll_adv.h"
#include "lll/lll_adv_pdu.h"
+#include "lll_chan.h"
#include "lll_scan.h"
#include "lll/lll_df_types.h"
#include "lll_sync.h"
@@ -619,6 +620,10 @@
ull_filter_reset(true);
}
+#if defined(CONFIG_BT_CTLR_TEST)
+ lll_chan_sel_2_ut();
+#endif /* CONFIG_BT_CTLR_TEST */
+
return 0;
}