3. Changing Advertising Parameters
This section describes how to change the advertising parameters on a DA14585/86 or DA1453x device. It covers all the key elements related to advertising, specifically dealing with advertising data and advertising intervals, as well as the advertising channel Map and advertising mode.
3.1. Changing the Advertising Data
To see or change the advertising data from default mode you need to open user_config.h
:
In
user_config.h
, change the contents of the existingUSER_ADVERTISE_DATA
macro to the desired Advertising Data.In the following code block we shows how to change the Advertising Data. Since the advertising string should have a specific format, you could use the
ADV_TYPE_MANUFACTURER_SPECIFIC_DATA
macro to add any custom data you wish into the advertising packets, as further explained in step 2.
- ADV_TYPE_COMPLETE_LIST_16BIT_SERVICE_IDS
+ ADV_TYPE_MANUFACTURER_SPECIFIC_DATA
The following sample code demonstrates setting some custom Advertising Data. It sets the full device name to THIS-IS-RENESAS
.
/// Advertising data
#define USER_ADVERTISE_DATA "\x11"\
ADV_TYPE_MANUFACTURER_SPECIFIC_DATA\
ADV_DIALOG_MANUFACTURER_CODE\
"THIS-IS-RENESAS"
2. Commonly, the Advertising Data includes some manufacturer specific data. These data are fully customizable in the header file user_barebone.h
,
as illustrated below:
/* Manufacturer specific data constants */
#define APP_AD_MSD_COMPANY_ID (0xFEDE)
#define APP_AD_MSD_COMPANY_ID_LEN (2)
#define APP_AD_MSD_DATA_LEN (sizeof(uint16_t))
We can change the company data to FEDE
as shown in Figure 8 (screenshot from a BLE Scanner).
/* Manufacturer specific data constants */
#define APP_AD_MSD_COMPANY_ID (0xFEDE)
When the device is ready to start advertising, it calls mnf_data_init()
in user_app_init()
. This function sets some standard parameters so that the device will publicly broadcast its Advertising
Data. The data to be advertised are copied from the struct mnf_specific_data_ad_structure
.
Finally, the device is asked to start advertising based on this configuration.
void user_app_init(void)
{
app_param_update_request_timer_used = EASY_TIMER_INVALID_TIMER;
// Initialize Manufacturer Specific Data
mnf_data_init();
// Initialize Advertising and Scan Response Data
memcpy(stored_adv_data, USER_ADVERTISE_DATA, USER_ADVERTISE_DATA_LEN);
stored_adv_data_len = USER_ADVERTISE_DATA_LEN;
memcpy(stored_scan_rsp_data, USER_ADVERTISE_SCAN_RESPONSE_DATA, USER_ADVERTISE_SCAN_RESPONSE_DATA_LEN);
stored_scan_rsp_data_len = USER_ADVERTISE_SCAN_RESPONSE_DATA_LEN;
default_app_on_init();
}
/**
****************************************************************************************
* @brief Initialize Manufacturer Specific Data
* @return void
****************************************************************************************
*/
static void mnf_data_init()
{
mnf_data.ad_structure_size = sizeof(struct mnf_specific_data_ad_structure ) - sizeof(uint8_t);
// minus the size of the ad_structure_size field
mnf_data.ad_structure_type = GAP_AD_TYPE_MANU_SPECIFIC_DATA;
mnf_data.company_id[0] = APP_AD_MSD_COMPANY_ID & 0xFF; // LSB
mnf_data.company_id[1] = (APP_AD_MSD_COMPANY_ID >> 8 )& 0xFF; // MSB
mnf_data.proprietary_data[0] = 0;
mnf_data.proprietary_data[1] = 0;
}
Note
When the device is ready for advertising, we may want it to call a custom function to handle the Advertising Data. The barebone example periodically updates the Advertising Data
and it demonstrates how the advertising contents can be handled using a user-defined function. In this case, we have to modify the appropriate callback function in user_callback_config.h
,
as in the code example below which uses the function user_app_adv_start
.
user_app_adv_start()
is a user defined function in the user application layer and does the following:
Starts an application timer with timeout
APP_ADV_DATA_UPDATE_TO
.Updates the Manufacturer Data included in the Advertising Data, see Changing the Advertising Data.
Starts the Advertising.
// Default Handler Operations
static const struct default_app_operations user_default_app_operations = {
.default_operation_adv = user_app_adv_start,
};
See also
The DA1458x and DA1453x devices may receive Scan Requests from the Central device in order to transmit additional user data by means of a Scan Response. The Scan Response usually has more data than the advertising packets and can vary in length from 8 to 39 bytes, because the Advertising Data is typically chosen to be very short to minimize power consumption. For more information, we recommend reading about Scan Response packets in the SIG core specification.
3.2. Changing the Advertising Interval
The Advertising Interval is the period between two consecutive advertisements of a Bluetooth Low Energy peripheral.
This interval can be customized in the file user_config.h
. The default value is set to 687.5ms
.
static const struct advertise_configuration user_adv_conf = {
.addr_src = APP_CFG_ADDR_SRC(USER_CFG_ADDRESS_MODE),
/// Minimum interval for advertising
.intv_min = MS_TO_BLESLOTS(687.5), // 687.5 ms
/// Maximum interval for advertising
.intv_max = MS_TO_BLESLOTS(687.5), // 687.5 ms
....
The following example changes the update timer to 1500ms.
/// Minimum interval for advertising
.intv_min = MS_TO_BLESLOTS(1500), // 1500 ms
/// Maximum interval for advertising
.intv_max = MS_TO_BLESLOTS(1500), // 1500 ms
Note
From the Bluetooth Specification (Vol 6, Part B, section 4.4.2.2.1 Advertising Interval) The advInterval
shall be an integer multiple of 0.625ms in the range of 20ms to 10.24s.
3.3. Changing the Advertising Channel Map
The band defined in the Bluetooth Core Specification consists of 37 data communication channels and three advertising channels for Device Discovery. The latter are allocated in non-consecutive parts of the spectrum to prevent interference from concurrent activities in the ISM Band. Specifically, a Bluetooth Low Energy device can advertise on channels 37, 38, and 39 which correspond to frequencies of 2.402 MHz, 2.2426 MHz, and 2.480 MHz respectively. SmartBond™ devices advertise successively on all enabled channels.
By default, all channels are enabled with the assigement .channel_map = ADV_ALL_CHNLS_EN
. To force the
Bluetooth Low Energy device to use only one channel, for example channel 37, use the assignment .channel_map = ADV_CHNL_37_EN
.
static const struct advertise_configuration user_adv_conf = {
.....
/**
* Advertising channels map:
* - ADV_CHNL_37_EN: Advertising channel map for channel 37.
* - ADV_CHNL_38_EN: Advertising channel map for channel 38.
* - ADV_CHNL_39_EN: Advertising channel map for channel 39.
* - ADV_ALL_CHNLS_EN: Advertising channel map for channel 37, 38, and 39.
*/
.channel_map = ADV_CHNL_37_EN,
Enumeration Name |
Value |
Description |
---|---|---|
|
0x01 |
Select channel 37 for advertising |
|
0x02 |
Select channel 38 for advertising |
|
0x04 |
Select channel 39 for advertising |
|
0x07 |
Select all channels (37, 38, and 39) for advertising |
3.4. Changing the Advertising Mode
The Advertising Mode is customizable by calling one of these API functions in sdk/app_modules/src/app_common/app.c
:
void app_easy_gap_undirected_advertise_start()
void app_easy_gap_directed_advertise_start(uint8_t ldc_enable)
void app_easy_gap_non_connectable_advertise_start(void)
To start advertising, use the GAPM_START_ADVERTISE_CMD
definition and
send it to the GAP manager layer (GAPM). A message is allocated using the KE_MSG_ALLOC
macro.
/**
****************************************************************************************
* @brief Create a start advertise message.
* @return The pointer to the created message.
****************************************************************************************
*/
__INLINE struct gapm_start_advertise_cmd* app_advertise_start_msg_create(void)
{
struct gapm_start_advertise_cmd* cmd = KE_MSG_ALLOC(GAPM_START_ADVERTISE_CMD,
TASK_GAPM,
TASK_APP,
gapm_start_advertise_cmd);
return cmd;
}
To start an undirected GAPM_ADV_UNDIRECT
advertising operation, fill the message with the necessary data: cmd = app_easy_gap_undirected_advertise_start_create_msg();
void app_easy_gap_undirected_advertise_start(void)
{
struct gapm_start_advertise_cmd* cmd;
cmd = app_easy_gap_undirected_advertise_start_create_msg();
// Send the message
app_advertise_start_msg_send(cmd);
adv_cmd = NULL ;
// We are now connectable
ke_state_set(TASK_APP, APP_CONNECTABLE);
}
/**
****************************************************************************************
* @brief Create advertising message for connectable undirected event (ADV_IND).
* @return gapm_start_advertise_cmd Pointer to the advertising message
****************************************************************************************
*/
static struct gapm_start_advertise_cmd* app_easy_gap_undirected_advertise_start_create_msg(void)
{
.....
struct gapm_start_advertise_cmd *cmd;
cmd = app_advertise_start_msg_create();
adv_cmd = cmd;
cmd->op.code = GAPM_ADV_UNDIRECT;
cmd->op.addr_src = user_adv_conf.addr_src;
cmd->intv_min = user_adv_conf.intv_min;
cmd->intv_max = user_adv_conf.intv_max;
.....
}
Then send it to the GAPM task, from the user_barebone.c
. The application layer is informed by calling the app_easy_gap_undirected_advertise_start()
in user_app_adv_start
. The other advertising modes are described in Table 5.
Enumeration Name |
Description |
---|---|
|
The Bluetooth Low Energy device advertises without permitting a connection to another central device. |
|
The Bluetooth Low Energy device advertises towards all devices regardless of their BD address |
|
The Bluetooth Low Energy device advertises towards a device with a specific BD address. |
|
The Bluetooth Low Energy device advertises towards a device with a specific BD address using Low Duty Cycle. |
3.5. Changing the Advertising Data On the Fly
The barebone example updates the Advertising Data, and more specifically the Manufacturer Specific Data, while the device is operating. The function that updates the Manufacturer Specific Data can be seen below:
/**
****************************************************************************************
* @brief Update Manufacturer Specific Data
* @return void
****************************************************************************************
*/
static void mnf_data_update()
{
uint16_t data;
data = mnf_data.proprietary_data[0] | (mnf_data.proprietary_data[1] << 8);
data += 1;
mnf_data.proprietary_data[0] = data & 0xFF;
mnf_data.proprietary_data[1] = (data >> 8) & 0xFF;
if (data == 0xFFFF) {
mnf_data.proprietary_data[0] = 0;
mnf_data.proprietary_data[1] = 0;
}
}
This function is called each time a periodic timer fires. This function reads and increments the value of counter, wrapping when the counter reaches the value 0xFFFF.
The update takes place in the adv_data_update_timer_cb()
callback function.
/**
****************************************************************************************
* @brief Advertisement data update timer callback function.
* @return void
****************************************************************************************
*/
static void adv_data_update_timer_cb()
{
// If mnd_data_index has MSB set, manufacturer data is stored in scan response
uint8_t *mnf_data_storage = (mnf_data_index & 0x80) ? stored_scan_rsp_data : stored_adv_data;
// Update manufacturer data
mnf_data_update();
// Update the selected fields of the advertising data (manufacturer data)
memcpy(mnf_data_storage + (mnf_data_index & 0x7F), &mnf_data, sizeof(struct mnf_specific_data_ad_structure));
// Update advertising data on the fly
app_easy_gap_update_adv_data(stored_adv_data, stored_adv_data_len, stored_scan_rsp_data, stored_scan_rsp_data_len);
// Restart timer for the next advertising update
app_adv_data_update_timer_used = app_easy_timer(APP_ADV_DATA_UPDATE_TO, adv_data_update_timer_cb);
}
When we have updated the data, we have to call the app_easy_gap_update_adv_data()
function. This code informs the BLE layer that there are updated advertising
data and queues the update at the next available opportunity.