Periodic Advertising

Introduction

Periodic advertising is a Bluetooth 5.0 feature based on extended advertisements. It allows non-connectable advertisements to be sent at a fixed interval where advertising data can change between those intervals. One or more scanners can then listen for such advertisements. It is a form of multicast. Its huge advantage to other advertising modes is that, due to the fix interval, the scanners can go sleep between two advertisement events instead of being in receive mode all the time.

Some points to know about Periodic Advertising:

  1. Although extended advertiser does not need to be enabled when periodic advertising is enabled. The only way to get the pointer to the Periodic Advertising train is through the SyncInfo field of the extended advertiser. As a result, starting extended advertisement is mandatory.
  2. At least one advertisement packet needs to be sent for periodic advertising to be enabled.
  3. It will use the same PHY as the auxiliary packet. Each periodic advertiser has same parameters as in connection. Additionally, the channel is also determined in the same way as in connection using the Channel Selection Algorithm #2.

  4. Because it is based on extended advertisements, it uses data channels as opposed to advertisements channels.

Concept

The overall process is shown in this figure.

Periodic Advertising

Periodic advertising mode is indicated with the ADV_EXT_IND packets (legacy advertisement) sent on primary (advertising) channels, which point to AUX_ADV_IND packets (extended advertisement), containing the actual information about the periodic advertisement, such as interval, hopping sequence, advertiser address, and so on. The advertiser will also send AUX_SYNC_IND packets (periodic advertisement) at the identified interval containing the actual periodic advertisement data.

Timing of Periodic Advertising

If the data of the periodic advertisement does not fit into one packet, the AUX_SYNC_IND packet can be followed by AUX_CHAIN_IND packets. AUX_SYNC_IND along with AUX_CHAIN_IND make up a sequence of advertisements forming a periodic advertising train.

Periodic Advertising Train

The advertiser will periodically send new AUX_ADV_IND packets, so that new scanners can synchronize to the data stream or existing scanners can resume a lost sync. Silicon Labs' Bluetooth stack sends AUX_ADV_IND packet before every periodic advertisement so that new scanners will be able to synchronize quickly.

Periodic Advertising Modes

Note: Periodic advertising is a new feature; it's not yet implemented in Phones yet. Hence, periodic advertisement packets will not be visible in mobile platforms and in Bluetooth scanning apps.

The following diagram summarizes the procedure involving both the advertiser and scanner side:

Flowchart of Periodic Advertiser and Scanner

Implementation of Advertiser

Configuration

max_advertisers in the Bluetooth configuration structure also configures the maximum number of periodic advertisers. Usually the structure is found in main.c file.

#else
  .sleep.flags = 0,
#endif // LFXO
  .bluetooth.max_connections = MAX_CONNECTIONS,        /* Maximum number of simultaneous connections */
  .bluetooth.max_advertisers = MAX_ADVERTISERS,        /* Maximum number of advertisement sets */
  .bluetooth.heap = bluetooth_stack_heap,              /* Bluetooth stack memory for connection management */

The MAX_ADVERTISERS can be overwritten in app.c using

void appMain(gecko_configuration_t *pconfig)
{
#if DISABLE_SLEEP > 0
  pconfig->sleep.flags = 0;
#endif

  /* Set maximum number of periodic advertisers */
  pconfig->bluetooth.max_advertisers = 1;

Feature Initialization

On the advertiser side, you can initiate the usage of periodic advertising using the following command. Note that this command should be called after gecko_init().

gecko_init_periodic_advertising()

Enable/Disable Periodic Advertising

This command can be used to start periodic advertising on the given advertisement set. The stack will enable the advertisement set automatically if the set has not been enabled and the set can advertise using extended advertising PDUs.

// Enable periodic advertisement
gecko_cmd_le_gap_start_periodic_advertising(uint8 handle,
                                              uint16 interval_min,
                                              uint16 interval_max,
                                              uint32 flags)

// Disable
gecko_cmd_le_gap_stop_periodic_advertising(uint8 handle)

Set Periodic Advertisement Data

This command sets the pointers for data to be sent in periodic advertisement. Execute this command every time you want to change the periodic advertisement data. If periodic advertising is currently disabled for the specified advertising set, data is kept by the Controller and used after periodic advertising is enabled for that set. The data is discarded when the advertising set is removed.

gecko_cmd_le_gap_bt5_set_adv_data(uint8 handle,
                                    uint8 scan_rsp,
                                    uint8 adv_data_len,
                                    const uint8 *adv_data_data)

The value of scan_rsp for Periodic advertisements is 8.

Periodic advertisement has the highest priority in the current implementation (BLE SDK 2.11.1.0). For collisions, Periodic advertisements is always overriding other advertisements. If you see collisions, try increasing the interval of advertisements.

Implementation of Scanner

Configuration

max_periodic_sync in the Bluetooth config configures the maximum number of synchronizations the Bluetooth stack needs to support. Usually the config is mentioned in main.c, however, MAX_PERIODIC_SYNC can be overwritten in app.c using

void appMain(gecko_configuration_t *pconfig)
{
#if DISABLE_SLEEP > 0
  pconfig->sleep.flags = 0;
#endif

  /* Set maximum number of periodic advertisers */
  pconfig->bluetooth.max_periodic_sync = 1;

Feature Initialization

To enable Periodic Advertisement Synchronization in the Bluetooth stack, call the following initialization function after the generic gecko_init function.

gecko_bgapi_class_sync_init()

Enable Extended Scan Response

To get all information from the scan responses needed to establish synchronization, extended scan responses shall be enabled. The following command can be used to enable the extended scan response event:

gecko_cmd_le_gap_set_discovery_extended_scan_response(uint8 enable)

Set it 0 to disable and 1 to enable.

Establish Synchronization

This command can be used to establish a synchronization with periodic advertisement from the specified advertiser and begin receiving periodic advertisement packets. More details here.

gecko_cmd_sync_open(uint8 adv_sid,
                      uint16 skip, uint16 timeout,
                      bd_addr address,
                      uint8 address_type)

The adv_sid parameter specifies the value that must match the Advertising SID subfield in the ADI (Advertise Data Info) field of the received advertisement for it to be used to synchronize. It can be obtained from the event gecko_evt_le_gap_extended_scan_response_id

evt->data.evt_le_gap_extended_scan_response.adv_sid

The skip parameter specifies the maximum number of consecutive periodic advertisement events that the receiver may skip after successfully receiving a periodic advertisement packet. The timeout parameter specifies the maximum permitted time between successful receives. If this time is exceeded, synchronization is lost.

The advertiser address_type, and advertiser address parameters specify the periodic advertising device to listen to. It can be obtained from the event gecko_evt_le_gap_extended_scan_response_id

evt->data.evt_le_gap_extended_scan_response.address,
evt->data.evt_le_gap_extended_scan_response.address_type

Successfully synchronization leads to the generation of this event:

gecko_evt_sync_opened_id

Whenever a periodic advertisement packet is received, this event is generated:

gecko_evt_sync_data_id

Close Synchronization

This command closes a synchronization with periodic advertisement or cancel an ongoing synchronization establishment procedure.

gecko_cmd_sync_close(uint8 sync)

where sync is the periodic advertisement synchronization handle.

When the synchronization is closed, lost or when an ongoing sync process is cancelled this event is generated:

gecko_evt_sync_closed_id

Example

This guide has a related code example, here: Periodic Advertisement Example.