2018-12-18 05:48:20 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2020-12-15 09:04:00 +05:30
|
|
|
#include <stdint.h>
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
#include "hal/ccm.h"
|
|
|
|
#include "hal/radio.h"
|
|
|
|
|
2019-11-07 11:39:45 +05:30
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
|
|
|
#define LOG_MODULE_NAME bt_ctlr_lll_chan
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "common/log.h"
|
|
|
|
#include <soc.h>
|
|
|
|
#include "hal/debug.h"
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint8_t chan_sel_remap(uint8_t *chan_map, uint8_t chan_index);
|
2018-12-18 05:48:20 +01:00
|
|
|
#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint16_t chan_prn(uint16_t counter, uint16_t chan_id);
|
2018-12-18 05:48:20 +01:00
|
|
|
#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CONN)
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t lll_chan_sel_1(uint8_t *chan_use, uint8_t hop, uint16_t latency, uint8_t *chan_map,
|
|
|
|
uint8_t chan_count)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t chan_next;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
chan_next = ((*chan_use) + (hop * (1 + latency))) % 37;
|
|
|
|
*chan_use = chan_next;
|
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
if ((chan_map[chan_next >> 3] & (1 << (chan_next % 8))) == 0U) {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t chan_index;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
chan_index = chan_next % chan_count;
|
|
|
|
chan_next = chan_sel_remap(chan_map, chan_index);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* channel can be used, return it */
|
|
|
|
}
|
|
|
|
|
|
|
|
return chan_next;
|
|
|
|
}
|
2020-02-06 16:43:46 +05:30
|
|
|
#endif /* CONFIG_BT_CONN */
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
|
2021-03-08 12:21:01 +05:30
|
|
|
uint16_t lll_chan_id(uint8_t *access_addr)
|
|
|
|
{
|
|
|
|
uint16_t aa_ls = ((uint16_t)access_addr[1] << 8) | access_addr[0];
|
|
|
|
uint16_t aa_ms = ((uint16_t)access_addr[3] << 8) | access_addr[2];
|
|
|
|
|
|
|
|
return aa_ms ^ aa_ls;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t lll_chan_sel_2(uint16_t counter, uint16_t chan_id, uint8_t *chan_map,
|
|
|
|
uint8_t chan_count)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t chan_next;
|
|
|
|
uint16_t prn_e;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
prn_e = chan_prn(counter, chan_id);
|
|
|
|
chan_next = prn_e % 37;
|
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
if ((chan_map[chan_next >> 3] & (1 << (chan_next % 8))) == 0U) {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t chan_index;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
chan_index = ((uint32_t)chan_count * prn_e) >> 16;
|
2018-12-18 05:48:20 +01:00
|
|
|
chan_next = chan_sel_remap(chan_map, chan_index);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* channel can be used, return it */
|
|
|
|
}
|
|
|
|
|
|
|
|
return chan_next;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint8_t chan_sel_remap(uint8_t *chan_map, uint8_t chan_index)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t chan_next;
|
|
|
|
uint8_t byte_count;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
chan_next = 0U;
|
|
|
|
byte_count = 5U;
|
2018-12-18 05:48:20 +01:00
|
|
|
while (byte_count--) {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t bite;
|
|
|
|
uint8_t bit_count;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
bite = *chan_map;
|
2019-03-26 19:57:45 -06:00
|
|
|
bit_count = 8U;
|
2018-12-18 05:48:20 +01:00
|
|
|
while (bit_count--) {
|
|
|
|
if (bite & 0x01) {
|
2019-03-26 19:57:45 -06:00
|
|
|
if (chan_index == 0U) {
|
2018-12-18 05:48:20 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
chan_index--;
|
|
|
|
}
|
|
|
|
chan_next++;
|
|
|
|
bite >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bit_count < 8) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
chan_map++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return chan_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
|
|
|
|
#if defined(RADIO_UNIT_TEST)
|
|
|
|
void lll_chan_sel_2_ut(void)
|
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t chan_map_1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x1F};
|
|
|
|
uint8_t chan_map_2[] = {0x00, 0x06, 0xE0, 0x00, 0x1E};
|
|
|
|
uint8_t m;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
m = chan_sel_2(1, 0x305F, chan_map_1, 37);
|
2019-03-26 19:57:45 -06:00
|
|
|
LL_ASSERT(m == 20U);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
m = chan_sel_2(2, 0x305F, chan_map_1, 37);
|
2019-03-26 19:57:45 -06:00
|
|
|
LL_ASSERT(m == 6U);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
m = chan_sel_2(3, 0x305F, chan_map_1, 37);
|
2019-03-26 19:57:45 -06:00
|
|
|
LL_ASSERT(m == 21U);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
m = chan_sel_2(6, 0x305F, chan_map_2, 9);
|
2019-03-26 19:57:45 -06:00
|
|
|
LL_ASSERT(m == 23U);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
m = chan_sel_2(7, 0x305F, chan_map_2, 9);
|
2019-03-26 19:57:45 -06:00
|
|
|
LL_ASSERT(m == 9U);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
m = chan_sel_2(8, 0x305F, chan_map_2, 9);
|
2019-03-26 19:57:45 -06:00
|
|
|
LL_ASSERT(m == 34U);
|
2018-12-18 05:48:20 +01:00
|
|
|
}
|
|
|
|
#endif /* RADIO_UNIT_TEST */
|
|
|
|
|
|
|
|
/* Attribution:
|
|
|
|
* http://graphics.stanford.edu/%7Eseander/bithacks.html#ReverseByteWith32Bits
|
|
|
|
*/
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint8_t chan_rev_8(uint8_t b)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
b = (((uint32_t)b * 0x0802LU & 0x22110LU) |
|
|
|
|
((uint32_t)b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint16_t chan_perm(uint16_t i)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
|
|
|
return (chan_rev_8((i >> 8) & 0xFF) << 8) | chan_rev_8(i & 0xFF);
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint16_t chan_mam(uint16_t a, uint16_t b)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
return ((uint32_t)a * 17U + b) & 0xFFFF;
|
2018-12-18 05:48:20 +01:00
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint16_t chan_prn(uint16_t counter, uint16_t chan_id)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t iterate;
|
|
|
|
uint16_t prn_e;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
prn_e = counter ^ chan_id;
|
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
for (iterate = 0U; iterate < 3; iterate++) {
|
2018-12-18 05:48:20 +01:00
|
|
|
prn_e = chan_perm(prn_e);
|
|
|
|
prn_e = chan_mam(prn_e, chan_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
prn_e ^= chan_id;
|
|
|
|
|
|
|
|
return prn_e;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
|