Introduction
In Bluetooth® Low Energy (BLE), periodic advertising (without responses) refers to a feature in which an advertiser can broadcast data at regular intervals without expecting or allowing a response from receiving devices. This advertising method relies on the use of extended advertising PDUs, and is particularly useful for applications requiring consistent data transmission over time, such as broadcasting sensor data, location beacons, or public information in a power-efficient manner. By not waiting for acknowledgments or replies, periodic advertising minimizes power consumption and reduces the complexity of maintaining a connection.
Periodic Advertising with Responses (PAwR) was introduced in Bluetooth Core Specification 5.4 to enable bi-directional communication between an advertiser and multiple scanners within a structured time frame. Unlike standard periodic advertising, PAwR allows devices to send responses within pre-defined response slots, enabling efficient communication while maintaining low power consumption.
A key feature of PAwR is that AUX_CONNECT_REQ PDUs are allowed, meaning that advertisers can act as initiators and trigger a transition from periodic advertising to an active connection with a particular scanner when needed. This enables both connectionless and connection-oriented communication models.
| PDU Type | PDU Name | Physical Channel | LE 1M | LE 2M | LE Coded | Currently Supported | Used in |
| 0b0101 | AUX_CONNECT_REQ | Secondary | * | * | * | * | PAwR |
| 0b0111 | ADV_EXT_IND | Primary | * | | * | * | PA |
| 0b0111 | AUX_ADV_IND | Secondary | * | * | * | * | PA |
| 0b0111 | AUX_SYNC_IND | Periodic | * | * | * | * | PA |
| 0b0111 | AUX_CHAIN_IND | Secondary and Periodic | * | * | * | * | PA |
| 0b0111 | AUX_SYNC_SUBEVENT_IND | Periodic | * | * | * | * | PAwR |
| 0b0111 | AUX_SYNC_SUBEVENT_RSP | Periodic | * | * | * | * | PAwR |
| 0b1000 | AUX_CONNECT_RSP | Secondary | * | * | * | * | PAwR |
Usage
The periodic scanner command handler is tailored for both periodic advertising with responses and periodic advertising without responses. It can receive indication PDUs as detailed in the table of supported PDU types above. Unlike the general scanner command handler, it does not send scan requests (SCAN_REQ or AUX_SCAN_REQ) or receive scan responses (SCAN_RSP or AUX_SCAN_RSP).
Periodic Advertising Establishment
To receive periodic advertisements, a scanner device must perform a procedure known as periodic advertising establishment. During this procedure, the advertiser device sends an ADV_EXT_IND PDU pointing to an AUX_ADV_IND that contains the SyncInfo needed by the scanner to synchronize with the periodic advertising train.
The AUX_ADV_IND may include an ACAD field with an AD Structure corresponding to the Periodic Advertising Response Timing Information. The scanner can use this information to determine whether it is periodic advertising with responses.
To perform periodic advertising establishment, follow these basic steps:
- Initialize the RCL (See RCL_init) and provide a handle (See RCL_open).
- Initialize and configure a RCL_CMD_BLE5_SCANNER_t command for periodic advertising establishment.
- Provide the necessary Multibuffer(s) such that they have been initialized and configured to receive the necessary syncInfo needed for the periodic advertising.
- Submit the command with RCL_Command_submit, and either use RCL_Command_pend or a callback to wait for the command's conclusion and proceed with any additional tasks such as post-processing or the submitting of new commands.
Periodic Advertising without Responses
When configured to do Periodic Advertising (without responses), the periodic scanner command handler can only receive AUX_SYNC_IND and AUX_CHAIN_IND PDUs and if needed follow the AuxPtrs in them.
Example of periodic advertising events from the same advertising set
If the execution of the RCL_CMD_BLE5_SCANNER_t is successful, it can be assumed that the periodic advertisement establishment is done, and the user can proceed with the reception of the periodic advertising events.
- Initialize and configure a RCL_CMD_BLE5_PER_SCANNER_t command considering the received SyncInfo.
- Use the reception time of the AUX_ADV_IND to calculate the syncPacketWindowOffset and set up the start time of the RCL_CMD_BLE5_PER_SCANNER_t command.
- Provide the necessary Multibuffer(s) such that they have been initialized and configured to receive the advertising data.
- Submit the command RCL_Command_submit, and either use RCL_Command_pend or a callback to wait for the command's conclusion and proceed with any additional tasks such as post-processing or the submitting of new commands.
- Rely on the start time of the previous RCL_CMD_BLE5_PER_SCANNER_t command and the received periodic advertising interval to schedule new periodic advertising commands.
The following code snippet shows how to establish a periodic advertising as a scanner:
void runPeriodicScanner(void)
{
RCL_Handle h =
RCL_open(&rclClient, &LRF_configBle);
RCL_Buffer_DataEntry *rxAdvExtPkt;
RCL_Buffer_DataEntry *rxAuxAdvPkt;
RCL_Buffer_DataEntry *rxAuxSyncPkt;
RCL_Buffer_DataEntry *rxAuxChainPkt;
SyncInfo rxAuxAdvSyncInfo;
scanCmd.channel = 37;
scanCmd.common.phyFeatures = PHY_FEATURES;
scanCmd.ctx = &scanCtx;
scanCmd.stats = &scanStats;
scanCmd.common.runtime.callback = scanCallback;
scanCmd.common.runtime.lrfCallbackMask.value = 0;
scanStats = (RCL_StatsAdvScanInit) { 0 };
scanStats.config.accumulate = true;
scanCmd.common.timing.absStartTime = startTimeScanCmd;
RCL_MultiBuffer *multiBuffer = (RCL_MultiBuffer *)rxBuffer;
List_List finishedBuffers;
List_clearList(&finishedBuffers);
if (rxAdvExtPkt != NULL)
{
}
if (rxAuxAdvPkt != NULL)
{
getSyncInfoData(rxAuxAdvPkt, &rxAuxAdvSyncInfo);
perScanCmd.ctx = &perScanCtx;
perScanCmd.stats = &perScanStats;
perScanCmd.common.runtime.callback = scanCallback;
perScanCmd.common.runtime.lrfCallbackMask.value = 0;
perScanStats = (RCL_StatsAdvScanInit) { 0 };
perScanStats.config.accumulate = true;
perScanCmd.channel = 18;
perScanCtx.accessAddress = rxAuxAdvSyncInfo.accessAddress;
perScanCtx.crcInit = rxAuxAdvSyncInfo.crcInit;
perScanCmd.common.phyFeatures = receivedPhy;
RCL_MultiBuffer *multiBuffer2 = (RCL_MultiBuffer *)rxBuffer2;
if (rxAuxSyncPkt != NULL)
{
}
if (rxAuxChainPkt != NULL)
{
}
}
}
For demonstration purposes, a helper function that inspects the extended header flags of the received packet and stores it in a C struct is used to extract the information contained in the SyncInfo field.
static void getSyncInfoData(RCL_Buffer_DataEntry *rxEntry, SyncInfo *rxSyncInfo)
{
uint8_t extHdrFlags = rxEntry->data[rxEntry->numPad - 1 + BLE_HDR_LEN + 1];
uint8_t syncInfoIndex = rxEntry->numPad - 1 + BLE_HDR_LEN + 1 + 1;
if (extHdrFlags & BLE5_EXT_HDR_FLAG_SYNC_INFO_BM)
{
if (extHdrFlags & BLE5_EXT_HDR_FLAG_ADVA_BM)
{
syncInfoIndex += BLE_EXT_HDR_ADVA_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_TARGETA_BM)
{
syncInfoIndex += BLE_EXT_HDR_TARGETA_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_CTE_INFO_BM)
{
syncInfoIndex += BLE_EXT_HDR_CTEINFO_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_ADI_BM)
{
syncInfoIndex += BLE_EXT_HDR_ADI_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_AUX_PTR_BM)
{
syncInfoIndex += BLE_EXT_HDR_AUXPTR_LEN;
}
}
rxSyncInfo->offsetInfo.base = (uint16_t)(rxEntry->data[syncInfoIndex + 1] & 0x1F) << 8 |
(uint16_t)(rxEntry->data[syncInfoIndex]);
rxSyncInfo->offsetInfo.units = (rxEntry->data[syncInfoIndex + 1] >> 5) & 0x01;
rxSyncInfo->offsetInfo.adjust = (rxEntry->data[syncInfoIndex + 1] >> 6) & 0x01;
rxSyncInfo->interval = (uint16_t)(rxEntry->data[syncInfoIndex + 3]) << 8 |
(uint16_t)(rxEntry->data[syncInfoIndex + 2]);
rxSyncInfo->chMap.chMap0To7 = rxEntry->data[syncInfoIndex + 4];
rxSyncInfo->chMap.chMap8To15 = rxEntry->data[syncInfoIndex + 5];
rxSyncInfo->chMap.chMap16To23 = rxEntry->data[syncInfoIndex + 6];
rxSyncInfo->chMap.chMap24To31 = rxEntry->data[syncInfoIndex + 7];
rxSyncInfo->chMap.chMap32To36 = rxEntry->data[syncInfoIndex + 8] & 0x1F;
rxSyncInfo->sleepClockAccuracy = rxEntry->data[syncInfoIndex + 8] >> 5;
rxSyncInfo->accessAddress = (uint32_t)(rxEntry->data[syncInfoIndex + 12]) << 24 |
(uint32_t)(rxEntry->data[syncInfoIndex + 11]) << 16 |
(uint32_t)(rxEntry->data[syncInfoIndex + 10]) << 8 |
(uint32_t)(rxEntry->data[syncInfoIndex + 9]);
rxSyncInfo->crcInit = (uint32_t)(rxEntry->data[syncInfoIndex + 15]) << 16 |
(uint32_t)(rxEntry->data[syncInfoIndex + 14]) << 8 |
(uint32_t)(rxEntry->data[syncInfoIndex + 13]);
rxSyncInfo->periodicEventCounter = (uint16_t)(rxEntry->data[syncInfoIndex + 17]) << 8 |
(uint16_t)(rxEntry->data[syncInfoIndex + 16]);
}
The scanning device can then use this information and the timestamp of the received AUX_ADV_IND (using the RCL_BLE5_getRxTimestamp API) to calculate the syncPacketWindowOffset and setup the start time of the periodic scanner command.
It's worth mentioning that the PHY to be used for the periodic advertising event corresponds to the PHY that the advertiser used when it sent the AUX_ADV_IND. For this reason, the example also relies on the use of the RCL_BLE5_getRxStatus API to return the status byte of the received packet.
Periodic Advertising With Responses
When configured to do periodic advertising with responses, the periodic scanner command handler can only receive AUX_SYNC_SUBEVENT_IND and AUX_CONNECT_REQ PDUs.
If an AUX_SYNC_SUBEVENT_IND is received, the caller of the command must process the received PDU and if needed use the RCL_CMD_BLE5_GENERIC_TX_t command to send the appropriate AUX_SYNC_SUBEVENT_RSP.
If an AUX_CONNECT_REQ is received, the command handler will automatically determine if it is the target of the connect request, and respond with an AUX_CONNECT_RSP if needed. In such case, the command handler will return a specific command status to indicate that a connection has been established.
Example of periodic advertising with responses events from the same advertising set
If the execution of the RCL_CMD_BLE5_SCANNER_t is successful, it can be assumed that the periodic advertisement establishment is done, and the user can proceed with the reception of the periodic advertising events.
- Initialize and configure a RCL_CMD_BLE5_PER_SCANNER_t command considering the received SyncInfo and ACAD.
- Use the reception time of the AUX_ADV_IND to calculate the syncPacketWindowOffset and set up the start time of the RCL_CMD_BLE5_PER_SCANNER_t command.
- Ensure the TX buffer is properly configured to contain an AUX_CONNECT_RSP PDU in case an AUX_CONNECT_REQ is received.
- Provide the necessary Multibuffer(s) such that they have been initialized and configured to receive the advertising data.
- Submit the command RCL_Command_submit, and either use RCL_Command_pend or a callback to wait for the command's conclusion and proceed with any additional tasks such as post-processing or the submitting of new commands.
- If the RCL_CMD_BLE5_PER_SCANNER_t command concludes with RCL_CommandStatus_Connect, schedule the connection events with the advertiser.
- If the RCL_CMD_BLE5_PER_SCANNER_t command concludes with RCL_CommandStatus_Finished and the received packet is an AUX_SYNC_SUBEVENT_IND, use the reception time of the AUX_SYNC_SUBEVENT_IND and the designated subevent and response slot to initialize and configure a RCL_CMD_BLE5_GENERIC_TX_t command to send the appropriate AUX_SYNC_SUBEVENT_RSP.
- Use the reception time of the AUX_SYNC_SUBEVENT_IND, the periodic advertising subevent interval and the periodic advertising interval to schedule the listening for the next subevents.
The following code snippet shows how to establish a connection by using the PAwR scanner:
void runPAwRScannerConn(void)
{
RCL_Handle h =
RCL_open(&rclClient, &LRF_configBle);
RCL_Buffer_DataEntry *rxAdvExtPkt;
RCL_Buffer_DataEntry *rxAuxAdvPkt;
RCL_Buffer_TxBuffer *auxConnRspTxBuffer = (RCL_Buffer_TxBuffer *)txBuffer;
SyncInfo rxAuxAdvSyncInfo;
DeviceAddr advA;
DeviceAddr targetA;
scanCmd.channel = 37;
scanCmd.common.phyFeatures = PHY_FEATURES;
scanCmd.ctx = &scanCtx;
scanCmd.stats = &scanStats;
scanCmd.common.runtime.callback = scanCallback;
scanCmd.common.runtime.lrfCallbackMask.value = 0;
scanStats = (RCL_StatsAdvScanInit) { 0 };
scanStats.config.accumulate = true;
scanCmd.common.timing.absStartTime = startTimeScanCmd;
RCL_MultiBuffer *multiBuffer = (RCL_MultiBuffer *)rxBuffer;
List_List finishedBuffers;
List_clearList(&finishedBuffers);
if (rxAdvExtPkt != NULL)
{
}
if (rxAuxAdvPkt != NULL)
{
getSyncInfoData(rxAuxAdvPkt, &rxAuxAdvSyncInfo);
perScanCmd.perAdvType = 1;
perScanCmd.ctx = &perScanCtx;
perScanCmd.stats = &perScanStats;
perScanCmd.common.runtime.callback = scanCallback;
perScanCmd.common.runtime.lrfCallbackMask.value = 0;
perScanStats = (RCL_StatsAdvScanInit) { 0 };
perScanStats.config.accumulate = true;
perScanCmd.channel = 18;
perScanCtx.accessAddress = rxAuxAdvSyncInfo.accessAddress;
perScanCtx.crcInit = rxAuxAdvSyncInfo.crcInit;
perScanCmd.common.phyFeatures = receivedPhy;
RCL_MultiBuffer *multiBuffer2 = (RCL_MultiBuffer *)rxBuffer2;
advA = (DeviceAddr) { .addrType = 0, .addrByte = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06} };
targetA = (DeviceAddr) { .addrType = 0, .addrByte = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01} };
setAuxConnRspBuffer(auxConnRspTxBuffer, &advA, &targetA);
{
}
}
}
To enable PAwR, ensure the perAdvType field is set as demonstrated in the code snippet. The PAwR scanner requires a Tx buffer for the AUX_CONNECT_RSP (in case an AUX_CONNECT_REQ is received) and a Multibuffer for receiving AUX_SYNC_SUBEVENT_IND or AUX_CONNECT_REQ PDUs. Note that the AdvA in AUX_CONNECT_RSP corresponds to the scanner's device address, while the TargetA corresponds to the advertiser's device address.
The code snippet includes a helper function that configures the Tx buffer for AUX_CONNECT_RSP.
static void setAuxConnRspBuffer(RCL_Buffer_TxBuffer *buffer, DeviceAddr *advA, DeviceAddr *targetA)
{
uint8_t payloadLength = 1 + AUX_CONN_RSP_HDR_LEN;
txData[0] = BLE_HDR_AUX_CONN_RSP_IND | (advA->addrType << 6) | (targetA->addrType << 7);
txData[1] = payloadLength;
txData[3] = BLE5_EXT_HDR_FLAG_ADVA_BM | BLE5_EXT_HDR_FLAG_TARGETA_BM;
for (uint8_t i = 0; i < BLE_ADDR_LEN_BYTES; ++i)
{
txData[4 + i] = advA->addrByte[i];
}
for (uint8_t i = 0; i < BLE_ADDR_LEN_BYTES; ++i)
{
txData[10 + i] = targetA->addrByte[i];
}
}
The following code snippet demonstrates how to use the periodic scanner command handler to receive AUX_SYNC_SUBEVENT_IND PDUs:
void runPAwRScanner(void)
{
RCL_Handle h =
RCL_open(&rclClient, &LRF_configBle);
RCL_Buffer_DataEntry *rxAdvExtPkt;
RCL_Buffer_DataEntry *rxAuxAdvPkt;
RCL_Buffer_DataEntry *rxSubEventIndOrConnReqPkt;
RCL_Buffer_TxBuffer *auxConnRspTxBuffer = (RCL_Buffer_TxBuffer *)txBuffer;
RCL_Buffer_TxBuffer *auxSyncSubEventRspTxBuffer = (RCL_Buffer_TxBuffer *)txBuffer2;
SyncInfo rxAuxAdvSyncInfo;
SubEventInfo rxAuxAdvSubEventInfo;
DeviceAddr advA;
DeviceAddr targetA;
scanCmd.channel = 37;
scanCmd.common.phyFeatures = PHY_FEATURES;
scanCmd.ctx = &scanCtx;
scanCmd.stats = &scanStats;
scanCmd.common.runtime.callback = scanCallback;
scanCmd.common.runtime.lrfCallbackMask.value = 0;
scanStats = (RCL_StatsAdvScanInit) { 0 };
scanStats.config.accumulate = true;
scanCmd.common.timing.absStartTime = startTimeScanCmd;
RCL_MultiBuffer *multiBuffer = (RCL_MultiBuffer *)rxBuffer;
List_List finishedBuffers;
List_clearList(&finishedBuffers);
if (rxAdvExtPkt != NULL)
{
}
if (rxAuxAdvPkt != NULL)
{
getSyncInfoData(rxAuxAdvPkt, &rxAuxAdvSyncInfo);
getSubEventInfoData(rxAuxAdvPkt, &rxAuxAdvSubEventInfo);
perScanCmd.perAdvType = 1;
perScanCmd.ctx = &perScanCtx;
perScanCmd.stats = &perScanStats;
perScanCmd.common.runtime.callback = scanCallback;
perScanCmd.common.runtime.lrfCallbackMask.value = 0;
perScanStats = (RCL_StatsAdvScanInit) { 0 };
perScanStats.config.accumulate = true;
perScanCmd.channel = 18;
perScanCtx.accessAddress = rxAuxAdvSyncInfo.accessAddress;
perScanCtx.crcInit = rxAuxAdvSyncInfo.crcInit;
perScanCmd.common.phyFeatures = receivedPhy;
advA = (DeviceAddr) { .addrType = 0, .addrByte = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06} };
targetA = (DeviceAddr) { .addrType = 0, .addrByte = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01} };
setAuxConnRspBuffer(auxConnRspTxBuffer, &advA, &targetA);
RCL_MultiBuffer *multiBuffer2 = (RCL_MultiBuffer *)rxBuffer2;
if (rxSubEventIndOrConnReqPkt != NULL)
{
if (RCL_BLE5_getPduType(rxSubEventIndOrConnReqPkt) == BLE_HDR_AUX_SYNC_SUBEVENT_IND)
{
genTxCtx.accessAddress = rxAuxAdvSubEventInfo.rspAA;
genTxCtx.crcInit = PAwR_TRAIN_CRC_INIT;
genTxCmd.channel = 20;
genTxCmd.ctx = &genTxCtx;
genTxCmd.common.phyFeatures = receivedPhy;
genTxCmd.common.runtime.callback = NULL;
genTxCmd.common.runtime.lrfCallbackMask.value = 0;
setAuxSyncSubEventRspBuffer(auxSyncSubEventRspTxBuffer, AUX_SYNC_SUBEVENT_RSP_ADV_DATA_LEN);
uint32_t rspSlotTimeUs = rxAuxAdvSubEventInfo.subeventInterval * (PAwR_SUBEVENT_INTERVAL_UNIT_US) * (PAwR_SUBEVENT_NUMBER_ZERO) +
rxAuxAdvSubEventInfo.responseSlotDelay * (PAwR_SUBEVENT_RESPONSE_SLOT_DELAY_US) +
rxAuxAdvSubEventInfo.responseSlotSpacing * (PAwR_SUBEVENT_RESPONSE_SLOT_SPACING_US) * (PAwR_RESPONSE_SLOT_NUMBER_ONE);
}
}
}
}
When the PAwR scanner receives an AUX_SYNC_SUBEVENT_IND, the application can schedule an RCL_CMD_BLE5_GENERIC_TX_t command to send an AUX_SYNC_SUBEVENT_RSP at the approprite response slot. The start time for this transmission command is calculated based on the reception time of the AUX_SYNC_SUBEVENT_IND and the Periodic Advertising Response Timing Information extracted from the ACAD field in the received AUX_ADV_IND. It is important to note that the access address for the AUX_SYNC_SUBEVENT_RSP must match the one contained in the ACAD. Additionally, the PHY used for transmitting the AUX_SYNC_SUBEVENT_RSP must be the same as the one used to receive the AUX_ADV_IND.
A helper function is provided to demonstrate how to configure the Tx buffer for AUX_SYNC_SUBEVENT_RSP.
static void setAuxSyncSubEventRspBuffer(RCL_Buffer_TxBuffer *buffer, uint8_t advDataLen)
{
uint8_t payloadLength = 1 + 1 + advDataLen;
txData[0] = BLE_HDR_AUX_SYNC_SUBEVENT_RSP;
txData[1] = payloadLength;
txData[3] = 0;
if (advDataLen > 0)
{
for(uint32_t i = 0; i < advDataLen; i++)
{
txData[4 + i] = i & 0xFF;
}
}
}
For demonstration purposes, a helper function is provided to inspect the extended header flags of the received packet and store the response timing information from the ACAD field into a C struct.
typedef struct
{
uint32_t rspAA;
uint8_t numSubevents;
uint8_t subeventInterval;
uint8_t responseSlotDelay;
uint8_t responseSlotSpacing;
} SubEventInfo;
static void getSubEventInfoData(RCL_Buffer_DataEntry *rxEntry, SubEventInfo *subEventInfo)
{
uint8_t extHdrFlags = rxEntry->data[rxEntry->numPad - 1 + BLE_HDR_LEN + 1];
uint8_t acadIndex = rxEntry->numPad - 1 + BLE_HDR_LEN + 1 + 1;
if (extHdrFlags & BLE5_EXT_HDR_FLAG_ADVA_BM)
{
acadIndex += BLE_EXT_HDR_ADVA_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_TARGETA_BM)
{
acadIndex += BLE_EXT_HDR_TARGETA_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_CTE_INFO_BM)
{
acadIndex += BLE_EXT_HDR_CTEINFO_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_ADI_BM)
{
acadIndex += BLE_EXT_HDR_ADI_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_AUX_PTR_BM)
{
acadIndex += BLE_EXT_HDR_AUXPTR_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_SYNC_INFO_BM)
{
acadIndex += BLE_EXT_HDR_SYNCINFO_LEN;
}
if (extHdrFlags & BLE5_EXT_HDR_FLAG_TX_POWER_BM)
{
acadIndex += BLE_EXT_HDR_TXPOWER_LEN;
}
subEventInfo->rspAA = (rxEntry->data[acadIndex + 2]) |
(rxEntry->data[acadIndex + 3] << 8) |
(rxEntry->data[acadIndex + 4] << 16) |
(rxEntry->data[acadIndex + 5] << 24);
subEventInfo->numSubevents = rxEntry->data[acadIndex + 6];
subEventInfo->subeventInterval = rxEntry->data[acadIndex + 7];
subEventInfo->responseSlotDelay = rxEntry->data[acadIndex + 8];
subEventInfo->responseSlotSpacing = rxEntry->data[acadIndex + 9];
}
Architecture
The life cycle of the periodic scanner command handler is influenced by the type of periodic advertising event, whether it involves responses or not.
For periodic advertising without responses, the command handler requires a Multibuffer capable of receiving the entire chain of packets that constitute the periodic advertising event. Upon receiving a packet, the command handler checks for the presence of an AuxPtr and schedules a new listening window to receive subsequent packets if necessary.
For periodic advertising with responses, the command handler needs a TxBuffer for a AUX_CONNECT_RSP (in case an AUX_CONNECT_REQ is received) and a Multibuffer for receiving either AUX_SYNC_SUBEVENT_IND or AUX_CONNECT_REQ PDUs. Depending on the received PDU, the scanner command handler can transition the scanner from the periodic advertising state to a connection state.
It's worth mentioning that only non-connectable/non-scannable extended PDUs can be received with the periodic scanner command, and other PDUs will be rejected and the command will end indicating an Rx buffer corruption.