mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-25 10:17:22 +00:00
Merge pull request #328 from sjanc/adv_csa
Use CSA#2 for secodnary channels selection in extended advertising
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t ble_ll_utils_calc_access_addr(void);
|
||||
uint8_t ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap);
|
||||
uint8_t ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id,
|
||||
uint8_t num_used_chans, const uint8_t *chanmap);
|
||||
uint8_t ble_ll_utils_calc_num_used_chans(const uint8_t *chanmap);
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "controller/ble_ll_whitelist.h"
|
||||
#include "controller/ble_ll_resolv.h"
|
||||
#include "controller/ble_ll_trace.h"
|
||||
#include "controller/ble_ll_utils.h"
|
||||
#include "ble_ll_conn_priv.h"
|
||||
|
||||
/* XXX: TODO
|
||||
@@ -111,6 +112,10 @@ struct ble_ll_adv_sm
|
||||
uint8_t *conn_comp_ev;
|
||||
struct ble_npl_event adv_txdone_ev;
|
||||
struct ble_ll_sched_item adv_sch;
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
|
||||
uint16_t channel_id;
|
||||
uint16_t event_cntr;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
uint8_t aux_active : 1;
|
||||
uint8_t aux_index : 1;
|
||||
@@ -1131,10 +1136,15 @@ ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm,
|
||||
aux->payload_len = 0;
|
||||
aux->ext_hdr = 0;
|
||||
|
||||
/* TODO we could use CSA2 for this
|
||||
* (will be needed for periodic advertising anyway)
|
||||
*/
|
||||
aux->chan = rand() % BLE_PHY_NUM_DATA_CHANS;
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
|
||||
aux->chan = ble_ll_utils_calc_dci_csa2(advsm->event_cntr++,
|
||||
advsm->channel_id,
|
||||
g_ble_ll_conn_params.num_used_chans,
|
||||
g_ble_ll_conn_params.master_chan_map);
|
||||
#else
|
||||
aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS,
|
||||
g_ble_ll_conn_params.master_chan_map);
|
||||
#endif
|
||||
|
||||
rem_aux_data_len = AUX_DATA_LEN(advsm) - aux_data_offset;
|
||||
chainable = !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE);
|
||||
@@ -1776,6 +1786,9 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
|
||||
uint8_t adv_chan;
|
||||
uint8_t *addr;
|
||||
uint8_t *evbuf;
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
|
||||
uint32_t access_addr;
|
||||
#endif
|
||||
|
||||
/* only clear flags that are not set from HCI */
|
||||
advsm->flags &= ~BLE_LL_ADV_SM_FLAG_TX_ADD;
|
||||
@@ -1839,6 +1852,13 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
|
||||
/* Set flag telling us that advertising is enabled */
|
||||
advsm->adv_enabled = 1;
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
|
||||
advsm->event_cntr = 0;
|
||||
access_addr = ble_ll_utils_calc_access_addr();
|
||||
advsm->channel_id = ((access_addr & 0xffff0000) >> 16) ^
|
||||
(access_addr & 0x0000ffff);
|
||||
#endif
|
||||
|
||||
/* Determine the advertising interval we will use */
|
||||
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
|
||||
/* Set it to max. allowed for high duty cycle advertising */
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "controller/ble_ll_trace.h"
|
||||
#include "controller/ble_phy.h"
|
||||
#include "controller/ble_hw.h"
|
||||
#include "controller/ble_ll_utils.h"
|
||||
#include "ble_ll_conn_priv.h"
|
||||
|
||||
#if (BLETEST_THROUGHPUT_TEST == 1)
|
||||
@@ -462,257 +463,6 @@ ble_ll_conn_calc_window_widening(struct ble_ll_conn_sm *connsm)
|
||||
return window_widening;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of used channels in the channel map
|
||||
*
|
||||
* @param chmap
|
||||
*
|
||||
* @return uint8_t Number of used channels
|
||||
*/
|
||||
uint8_t
|
||||
ble_ll_conn_calc_used_chans(uint8_t *chmap)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
uint8_t mask;
|
||||
uint8_t chanbyte;
|
||||
uint8_t used_channels;
|
||||
|
||||
used_channels = 0;
|
||||
for (i = 0; i < BLE_LL_CONN_CHMAP_LEN; ++i) {
|
||||
chanbyte = chmap[i];
|
||||
if (chanbyte) {
|
||||
if (chanbyte == 0xff) {
|
||||
used_channels += 8;
|
||||
} else {
|
||||
mask = 0x01;
|
||||
for (j = 0; j < 8; ++j) {
|
||||
if (chanbyte & mask) {
|
||||
++used_channels;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return used_channels;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ble_ll_conn_calc_access_addr(void)
|
||||
{
|
||||
uint32_t aa;
|
||||
uint16_t aa_low;
|
||||
uint16_t aa_high;
|
||||
uint32_t temp;
|
||||
uint32_t mask;
|
||||
uint32_t prev_bit;
|
||||
uint8_t bits_diff;
|
||||
uint8_t consecutive;
|
||||
uint8_t transitions;
|
||||
uint8_t ones;
|
||||
int tmp;
|
||||
|
||||
/* Calculate a random access address */
|
||||
aa = 0;
|
||||
while (1) {
|
||||
/* Get two, 16-bit random numbers */
|
||||
aa_low = rand() & 0xFFFF;
|
||||
aa_high = rand() & 0xFFFF;
|
||||
|
||||
/* All four bytes cannot be equal */
|
||||
if (aa_low == aa_high) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Upper 6 bits must have 2 transitions */
|
||||
tmp = (int16_t)aa_high >> 10;
|
||||
if (__builtin_popcount(tmp ^ (tmp >> 1)) < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot be access address or be 1 bit different */
|
||||
aa = aa_high;
|
||||
aa = (aa << 16) | aa_low;
|
||||
bits_diff = 0;
|
||||
temp = aa ^ BLE_ACCESS_ADDR_ADV;
|
||||
for (mask = 0x00000001; mask != 0; mask <<= 1) {
|
||||
if (mask & temp) {
|
||||
++bits_diff;
|
||||
if (bits_diff > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bits_diff <= 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot have more than 24 transitions */
|
||||
transitions = 0;
|
||||
consecutive = 1;
|
||||
ones = 0;
|
||||
mask = 0x00000001;
|
||||
while (mask < 0x80000000) {
|
||||
prev_bit = aa & mask;
|
||||
mask <<= 1;
|
||||
if (mask & aa) {
|
||||
if (prev_bit == 0) {
|
||||
++transitions;
|
||||
consecutive = 1;
|
||||
} else {
|
||||
++consecutive;
|
||||
}
|
||||
} else {
|
||||
if (prev_bit == 0) {
|
||||
++consecutive;
|
||||
} else {
|
||||
++transitions;
|
||||
consecutive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_bit) {
|
||||
ones++;
|
||||
}
|
||||
|
||||
/* 8 lsb should have at least three 1 */
|
||||
if (mask == 0x00000100 && ones < 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 16 lsb should have no more than 11 transitions */
|
||||
if (mask == 0x00010000 && transitions > 11) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is invalid! */
|
||||
if (consecutive > 6) {
|
||||
/* Make sure we always detect invalid sequence below */
|
||||
mask = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid sequence found */
|
||||
if (mask != 0x80000000) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot be more than 24 transitions */
|
||||
if (transitions > 24) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have a valid access address */
|
||||
break;
|
||||
}
|
||||
return aa;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_ll_conn_remapped_channel(uint8_t remap_index, const uint8_t *chanmap)
|
||||
{
|
||||
uint8_t cntr;
|
||||
uint8_t mask;
|
||||
uint8_t usable_chans;
|
||||
uint8_t chan;
|
||||
int i, j;
|
||||
|
||||
/* NOTE: possible to build a map but this would use memory. For now,
|
||||
we just calculate */
|
||||
/* Iterate through channel map to find this channel */
|
||||
chan = 0;
|
||||
cntr = 0;
|
||||
for (i = 0; i < BLE_LL_CONN_CHMAP_LEN; i++) {
|
||||
usable_chans = chanmap[i];
|
||||
if (usable_chans != 0) {
|
||||
mask = 0x01;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (usable_chans & mask) {
|
||||
if (cntr == remap_index) {
|
||||
return (chan + j);
|
||||
}
|
||||
++cntr;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
chan += 8;
|
||||
}
|
||||
|
||||
/* we should never reach here */
|
||||
BLE_LL_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
|
||||
static uint16_t
|
||||
ble_ll_conn_csa2_perm(uint16_t in)
|
||||
{
|
||||
uint16_t out = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
out |= ((in >> i) & 0x00000001) << (7 - i);
|
||||
}
|
||||
|
||||
for (i = 8; i < 16; i++) {
|
||||
out |= ((in >> i) & 0x00000001) << (15 + 8 - i);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
ble_ll_conn_csa2_prng(uint16_t counter, uint16_t ch_id)
|
||||
{
|
||||
uint16_t prn_e;
|
||||
|
||||
prn_e = counter ^ ch_id;
|
||||
|
||||
prn_e = ble_ll_conn_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = ble_ll_conn_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = ble_ll_conn_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = prn_e ^ ch_id;
|
||||
|
||||
return prn_e;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_ll_conn_calc_dci_csa2(struct ble_ll_conn_sm *conn)
|
||||
{
|
||||
uint16_t channel_unmapped;
|
||||
uint8_t remap_index;
|
||||
|
||||
uint16_t prn_e;
|
||||
uint8_t bitpos;
|
||||
|
||||
prn_e = ble_ll_conn_csa2_prng(conn->event_cntr, conn->channel_id);
|
||||
|
||||
channel_unmapped = prn_e % 37;
|
||||
|
||||
/*
|
||||
* If unmapped channel is the channel index of a used channel it is used
|
||||
* as channel index.
|
||||
*/
|
||||
bitpos = 1 << (channel_unmapped & 0x07);
|
||||
if (conn->chanmap[channel_unmapped >> 3] & bitpos) {
|
||||
return channel_unmapped;
|
||||
}
|
||||
|
||||
remap_index = (conn->num_used_chans * prn_e) / 0x10000;
|
||||
|
||||
return ble_ll_conn_remapped_channel(remap_index, conn->chanmap);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t
|
||||
ble_ll_conn_calc_dci_csa1(struct ble_ll_conn_sm *conn)
|
||||
{
|
||||
@@ -738,7 +488,7 @@ ble_ll_conn_calc_dci_csa1(struct ble_ll_conn_sm *conn)
|
||||
/* Calculate remap index */
|
||||
remap_index = curchan % conn->num_used_chans;
|
||||
|
||||
return ble_ll_conn_remapped_channel(remap_index, conn->chanmap);
|
||||
return ble_ll_utils_remapped_channel(remap_index, conn->chanmap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -757,7 +507,8 @@ ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency)
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
|
||||
if (CONN_F_CSA2_SUPP(conn)) {
|
||||
return ble_ll_conn_calc_dci_csa2(conn);
|
||||
return ble_ll_utils_calc_dci_csa2(conn->event_cntr, conn->channel_id,
|
||||
conn->num_used_chans, conn->chanmap);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1722,7 +1473,7 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
|
||||
BLE_LL_CONN_CHMAP_LEN);
|
||||
|
||||
/* Calculate random access address and crc initialization value */
|
||||
connsm->access_addr = ble_ll_conn_calc_access_addr();
|
||||
connsm->access_addr = ble_ll_utils_calc_access_addr();
|
||||
connsm->crcinit = rand() & 0xffffff;
|
||||
|
||||
/* Set initial schedule callback */
|
||||
@@ -2322,7 +2073,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
|
||||
* transmitted update request. Would end up killing connection
|
||||
on slave side. Could ignore it or see if still enqueued. */
|
||||
connsm->num_used_chans =
|
||||
ble_ll_conn_calc_used_chans(connsm->req_chanmap);
|
||||
ble_ll_utils_calc_num_used_chans(connsm->req_chanmap);
|
||||
memcpy(connsm->chanmap, connsm->req_chanmap, BLE_LL_CONN_CHMAP_LEN);
|
||||
|
||||
connsm->csmflags.cfbit.chanmap_update_scheduled = 0;
|
||||
@@ -4281,7 +4032,7 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr,
|
||||
connsm->peer_addr_type = pat;
|
||||
|
||||
/* Calculate number of used channels; make sure it meets min requirement */
|
||||
connsm->num_used_chans = ble_ll_conn_calc_used_chans(connsm->chanmap);
|
||||
connsm->num_used_chans = ble_ll_utils_calc_num_used_chans(connsm->chanmap);
|
||||
if (connsm->num_used_chans < 2) {
|
||||
goto err_slave_start;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "nimble/hci_common.h"
|
||||
#include "nimble/ble_hci_trans.h"
|
||||
#include "controller/ble_ll.h"
|
||||
#include "controller/ble_ll_utils.h"
|
||||
#include "controller/ble_ll_hci.h"
|
||||
#include "controller/ble_ll_conn.h"
|
||||
#include "controller/ble_ll_ctrl.h"
|
||||
@@ -1234,7 +1235,7 @@ ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf)
|
||||
* I will not allow this command if there are less than 2 channels masked.
|
||||
*/
|
||||
rc = BLE_ERR_SUCCESS;
|
||||
num_used_chans = ble_ll_conn_calc_used_chans(cmdbuf);
|
||||
num_used_chans = ble_ll_utils_calc_num_used_chans(cmdbuf);
|
||||
if ((num_used_chans < 2) || ((cmdbuf[4] & 0xe0) != 0)) {
|
||||
rc = BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,6 @@ void ble_ll_conn_init_wfr_timer_exp(void);
|
||||
int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2);
|
||||
uint32_t ble_ll_conn_get_ce_end_time(void);
|
||||
void ble_ll_conn_event_halt(void);
|
||||
uint8_t ble_ll_conn_calc_used_chans(uint8_t *chmap);
|
||||
void ble_ll_conn_reset_pending_aux_conn_rsp(void);
|
||||
bool ble_ll_conn_init_pending_aux_conn_rsp(void);
|
||||
/* HCI */
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "nimble/ble.h"
|
||||
#include "controller/ble_ll.h"
|
||||
#include "controller/ble_ll_utils.h"
|
||||
|
||||
/* 37 bits require 5 bytes */
|
||||
#define BLE_LL_CHMAP_LEN (5)
|
||||
|
||||
uint32_t
|
||||
ble_ll_utils_calc_access_addr(void)
|
||||
{
|
||||
uint32_t aa;
|
||||
uint16_t aa_low;
|
||||
uint16_t aa_high;
|
||||
uint32_t temp;
|
||||
uint32_t mask;
|
||||
uint32_t prev_bit;
|
||||
uint8_t bits_diff;
|
||||
uint8_t consecutive;
|
||||
uint8_t transitions;
|
||||
uint8_t ones;
|
||||
int tmp;
|
||||
|
||||
/* Calculate a random access address */
|
||||
aa = 0;
|
||||
while (1) {
|
||||
/* Get two, 16-bit random numbers */
|
||||
aa_low = rand() & 0xFFFF;
|
||||
aa_high = rand() & 0xFFFF;
|
||||
|
||||
/* All four bytes cannot be equal */
|
||||
if (aa_low == aa_high) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Upper 6 bits must have 2 transitions */
|
||||
tmp = (int16_t)aa_high >> 10;
|
||||
if (__builtin_popcount(tmp ^ (tmp >> 1)) < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot be access address or be 1 bit different */
|
||||
aa = aa_high;
|
||||
aa = (aa << 16) | aa_low;
|
||||
bits_diff = 0;
|
||||
temp = aa ^ BLE_ACCESS_ADDR_ADV;
|
||||
for (mask = 0x00000001; mask != 0; mask <<= 1) {
|
||||
if (mask & temp) {
|
||||
++bits_diff;
|
||||
if (bits_diff > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bits_diff <= 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot have more than 24 transitions */
|
||||
transitions = 0;
|
||||
consecutive = 1;
|
||||
ones = 0;
|
||||
mask = 0x00000001;
|
||||
while (mask < 0x80000000) {
|
||||
prev_bit = aa & mask;
|
||||
mask <<= 1;
|
||||
if (mask & aa) {
|
||||
if (prev_bit == 0) {
|
||||
++transitions;
|
||||
consecutive = 1;
|
||||
} else {
|
||||
++consecutive;
|
||||
}
|
||||
} else {
|
||||
if (prev_bit == 0) {
|
||||
++consecutive;
|
||||
} else {
|
||||
++transitions;
|
||||
consecutive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_bit) {
|
||||
ones++;
|
||||
}
|
||||
|
||||
/* 8 lsb should have at least three 1 */
|
||||
if (mask == 0x00000100 && ones < 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 16 lsb should have no more than 11 transitions */
|
||||
if (mask == 0x00010000 && transitions > 11) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is invalid! */
|
||||
if (consecutive > 6) {
|
||||
/* Make sure we always detect invalid sequence below */
|
||||
mask = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid sequence found */
|
||||
if (mask != 0x80000000) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot be more than 24 transitions */
|
||||
if (transitions > 24) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have a valid access address */
|
||||
break;
|
||||
}
|
||||
return aa;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap)
|
||||
{
|
||||
uint8_t cntr;
|
||||
uint8_t mask;
|
||||
uint8_t usable_chans;
|
||||
uint8_t chan;
|
||||
int i, j;
|
||||
|
||||
/* NOTE: possible to build a map but this would use memory. For now,
|
||||
* we just calculate
|
||||
* Iterate through channel map to find this channel
|
||||
*/
|
||||
chan = 0;
|
||||
cntr = 0;
|
||||
for (i = 0; i < BLE_LL_CHMAP_LEN; i++) {
|
||||
usable_chans = chanmap[i];
|
||||
if (usable_chans != 0) {
|
||||
mask = 0x01;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (usable_chans & mask) {
|
||||
if (cntr == remap_index) {
|
||||
return (chan + j);
|
||||
}
|
||||
++cntr;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
chan += 8;
|
||||
}
|
||||
|
||||
/* we should never reach here */
|
||||
BLE_LL_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_ll_utils_calc_num_used_chans(const uint8_t *chmap)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
uint8_t mask;
|
||||
uint8_t chanbyte;
|
||||
uint8_t used_channels;
|
||||
|
||||
used_channels = 0;
|
||||
for (i = 0; i < BLE_LL_CHMAP_LEN; ++i) {
|
||||
chanbyte = chmap[i];
|
||||
if (chanbyte) {
|
||||
if (chanbyte == 0xff) {
|
||||
used_channels += 8;
|
||||
} else {
|
||||
mask = 0x01;
|
||||
for (j = 0; j < 8; ++j) {
|
||||
if (chanbyte & mask) {
|
||||
++used_channels;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return used_channels;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
|
||||
static uint16_t
|
||||
ble_ll_utils_csa2_perm(uint16_t in)
|
||||
{
|
||||
uint16_t out = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
out |= ((in >> i) & 0x00000001) << (7 - i);
|
||||
}
|
||||
|
||||
for (i = 8; i < 16; i++) {
|
||||
out |= ((in >> i) & 0x00000001) << (15 + 8 - i);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
ble_ll_utils_csa2_prng(uint16_t counter, uint16_t ch_id)
|
||||
{
|
||||
uint16_t prn_e;
|
||||
|
||||
prn_e = counter ^ ch_id;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = prn_e ^ ch_id;
|
||||
|
||||
return prn_e;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id,
|
||||
uint8_t num_used_chans, const uint8_t *chanmap)
|
||||
{
|
||||
uint16_t channel_unmapped;
|
||||
uint8_t remap_index;
|
||||
|
||||
uint16_t prn_e;
|
||||
uint8_t bitpos;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_prng(event_cntr, channel_id);
|
||||
|
||||
channel_unmapped = prn_e % 37;
|
||||
|
||||
/*
|
||||
* If unmapped channel is the channel index of a used channel it is used
|
||||
* as channel index.
|
||||
*/
|
||||
bitpos = 1 << (channel_unmapped & 0x07);
|
||||
if (chanmap[channel_unmapped >> 3] & bitpos) {
|
||||
return channel_unmapped;
|
||||
}
|
||||
|
||||
remap_index = (num_used_chans * prn_e) / 0x10000;
|
||||
|
||||
return ble_ll_utils_remapped_channel(remap_index, chanmap);
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user