Skip to content
Permalink
Browse files

bluetooth: controller: Update slot reservation time calculation for ADV

Correct slot reservation time calc for legacy advertise
Add dependency on data lengths for advertise and scan response

Signed-off-by: Erik Brockhoff <erbr@oticon.com>
  • Loading branch information...
erbr-ot authored and aescolar committed Mar 20, 2019
1 parent b69ed03 commit 1090b4522563b4e48d5c80bc92fe61e957042a91
Showing with 86 additions and 20 deletions.
  1. +21 −0 subsys/bluetooth/controller/ll_sw/pdu.h
  2. +65 −20 subsys/bluetooth/controller/ll_sw/ull_adv.c
@@ -17,6 +17,18 @@
/* Advertisement channel maximum PDU size */
#define PDU_AC_SIZE_MAX (PDU_AC_LL_HEADER_SIZE + PDU_AC_PAYLOAD_SIZE_MAX)

#define ACCESS_ADDR_SIZE 4
#define ADVA_SIZE 6
#define SCANA_SIZE 6
#define INITA_SIZE 6
#define TARGETA_SIZE 6
#define LLDATA_SIZE 22
#define CRC_SIZE 3
#define PREAMBLE_SIZE(phy) (phy&0x3)
#define LL_HEADER_SIZE(phy) (PREAMBLE_SIZE(phy) + PDU_AC_LL_HEADER_SIZE \
+ ACCESS_ADDR_SIZE + CRC_SIZE)
#define BYTES2US(bytes, phy) (((bytes)<<3)/BIT((phy&0x3)>>1))

/* Data channel minimum payload */
#define PDU_DC_PAYLOAD_SIZE_MIN 27
/* Link Layer header size of Data PDU. Assumes pdu_data is packed */
@@ -25,6 +37,15 @@
/* Max size of an empty PDU. TODO: Remove; only used in Nordic LLL */
#define PDU_EM_SIZE_MAX (PDU_DC_LL_HEADER_SIZE)

/* Event interframe timings */
#define EVENT_IFS_US 150
/* Standard allows 2 us timing uncertainty inside the event */
#define EVENT_IFS_MAX_US (EVENT_IFS_US + 2)
/* Controller will layout extended adv with minimum separation */
#define EVENT_MAFS_US 300
/* Standard allows 2 us timing uncertainty inside the event */
#define EVENT_MAFS_MAX_US (EVENT_MAFS_US + 2)

/* Extra bytes for enqueued node_rx metadata: rssi (always), resolving
* index, directed adv report, and mesh channel and instant.
*/
@@ -429,10 +429,6 @@ u8_t ll_adv_enable(u8_t enable)
u32_t ticks_slot_offset;
struct ll_adv_set *adv;
struct lll_adv *lll;
u16_t interval;
u32_t slot_us;
u8_t chan_map;
u8_t chan_cnt;
u32_t ret;

if (!enable) {
@@ -678,25 +674,74 @@ u8_t ll_adv_enable(u8_t enable)
ARG_UNUSED(rl_idx);
#endif /* CONFIG_BT_CTLR_PRIVACY */

interval = adv->interval;
chan_map = lll->chan_map;
chan_cnt = util_ones_count_get(&chan_map, sizeof(chan_map));
#if defined(CONFIG_BT_CTLR_ADV_EXT)
const u8_t phy = lll->phy_p;
#else
/* Legacy ADV only supports LE_1M PHY */
const u8_t phy = 1;
#endif

/* TODO: use adv data len in slot duration calculation, instead of
* hardcoded max. numbers used below.
*/
if (pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND) {
/* Max. chain is DIRECT_IND * channels + CONNECT_IND */
slot_us = ((EVENT_OVERHEAD_START_US + 176 + 152 + 40) *
chan_cnt) - 40 + 352;
} else if (pdu_adv->type == PDU_ADV_TYPE_NONCONN_IND) {
slot_us = (EVENT_OVERHEAD_START_US + 376) * chan_cnt;
} else {
/* Max. chain is ADV/SCAN_IND + SCAN_REQ + SCAN_RESP */
slot_us = (EVENT_OVERHEAD_START_US + 376 + 152 + 176 +
152 + 376) * chan_cnt;
/* For now we adv on all channels enabled in channel map */
u8_t ch_map = lll->chan_map;
const u8_t adv_chn_cnt = util_ones_count_get(&ch_map, sizeof(ch_map));
u32_t slot_us = EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;

if (adv_chn_cnt == 0) {
/* ADV needs at least one channel */
goto failure_cleanup;
}

#if defined(CONFIG_BT_CTLR_ADV_EXT)
if (pdu_adv->type == PDU_ADV_TYPE_EXT_IND) {
/* TBD */
} else
#endif
{
const u8_t adv_data_len = pdu_adv->len;
const u8_t rsp_data_len = pdu_scan->len;
const u8_t ll_hdr_size = LL_HEADER_SIZE(phy);
u32_t adv_size = ll_hdr_size + ADVA_SIZE;
const u8_t ll_hdr_us = BYTES2US(ll_hdr_size, phy);
const u8_t rx_to_us = EVENT_RX_TO_US(phy);
const u8_t rxtx_turn_us = EVENT_RX_TX_TURNARROUND(phy);
const u8_t conn_ind_us = ll_hdr_us +
BYTES2US(INITA_SIZE + ADVA_SIZE + LLDATA_SIZE, phy);
const u8_t scan_req_us = ll_hdr_us +
BYTES2US(SCANA_SIZE + ADVA_SIZE, phy);
/* ll_header plus AdvA and scan response data */
const u8_t scan_rsp_us = ll_hdr_us +
BYTES2US(ADVA_SIZE + rsp_data_len, phy);

if (phy != 0x01) {
/* Legacy ADV only supports LE_1M PHY */
goto failure_cleanup;
}

if (pdu_adv->type == PDU_ADV_TYPE_NONCONN_IND) {
adv_size += adv_data_len;
slot_us += BYTES2US(adv_size, phy) * adv_chn_cnt +
EVENT_IFS_MAX_US * (adv_chn_cnt - 1);
} else {
if (pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND) {
adv_size += TARGETA_SIZE;
slot_us += conn_ind_us;
} else if (pdu_adv->type == PDU_ADV_TYPE_ADV_IND) {
adv_size += adv_data_len;
slot_us += MAX(scan_req_us + EVENT_IFS_MAX_US +
scan_rsp_us, conn_ind_us);
} else if (pdu_adv->type == PDU_ADV_TYPE_SCAN_IND) {
adv_size += adv_data_len;
slot_us += scan_req_us + EVENT_IFS_MAX_US +
scan_rsp_us;
}

slot_us += (BYTES2US(adv_size, phy) + EVENT_IFS_MAX_US
+ rx_to_us + rxtx_turn_us) * (adv_chn_cnt-1)
+ BYTES2US(adv_size, phy) + EVENT_IFS_MAX_US;
}
}

u16_t interval = adv->interval;
#if defined(CONFIG_BT_HCI_MESH_EXT)
if (lll->is_mesh) {
u16_t interval_min_us;

0 comments on commit 1090b45

Please sign in to comment.
You can’t perform that action at this time.