5. Preparing the Peripheral cntd
5.1. Operation Mode Changes
5.1.1. Advertising
For this set of tests, advertising should broadcast the maximum possible payload which is 26 characters plus 1 byte for length. In file ble_peripheral_task.c modify adv_data[] to contain 26 characters and alter the first element of the array to reflect the number of bytes (0x1B in case of 26 characters).
/*
* BLE peripheral advertising data
*/
static const uint8_t adv_data[] = {
0x1B, GAP_DATA_TYPE_LOCAL_NAME,
'T','e','s','t',' ','C','u','s','t','o','m',' ','S','e','r','v','i','c','e',' ','C','h','.',' ','1','A'
};
Additionally, the advertising interval should be modified to reflect the frequency with which the advertising event should be taking place. This can be achieved by calling the following API and providing the proper values for minimum and maximum connection interval.
/*
* Set the connection interval. First argument is the minimum and second the maximum interval in clock ticks.
* Min and Max should have a small variation (+/- 10 milliseconds ) or the interval will be picked randomly between
* 1 and value as the central sees fit. Additionally use macro BLE_ADV_INTERVAL_FROM_MS() in order to turn milliseconds
* to clock ticks.
*/
ble_gap_adv_intv_set(BLE_ADV_INTERVAL_FROM_MS(USER_MIN_ADV_INTV_MS),BLE_ADV_INTERVAL_FROM_MS(USER_MAX_ADV_INTV_MS));
Last but not least, when ble_gap_adv_start() function is called, modify the parameter according to the desired advertising mode as defined in the following enum:
/** GAP connectivity modes */
typedef enum {
GAP_CONN_MODE_NON_CONN, ///< Non-connectable mode
GAP_CONN_MODE_UNDIRECTED, ///< Undirected mode
GAP_CONN_MODE_DIRECTED, ///< Directed mode
GAP_CONN_MODE_DIRECTED_LDC, ///< Directed Low Duty Cycle mode
} gap_conn_mode_t;
5.1.2. Characteristic Value Auto-change and Notify Peers
One of the test cases involves automatically changing the value without a request every two seconds and sending out notifications to all connected peers who have requested to receive them. A timer has to be used which when triggered, will notify the task that the value needs to be changed and notifications need to be sent. Additionally since there is not a request the notifications functions should be altered/replaced accordingly.
5.1.2.1. Setting up the Task Notification Bit
Anywhere after the include directives, add the following code snippet:
#define VALUE_CHANGE_NOTIF (1<<3)
This directive will be used later by the timer callback function to set the desired bit and also by the task itself in order to execute the corresponding code. Do not use the first bit (#0) as it is reserved usually for BLE related task notifications as defined in ble_common.h.
5.1.2.2. Setting up the Timer
First comes the declaration of an OS_TIMER type global variable which has to be retained in RAM. (The variable is also zero initialized as __RETAINED dictates)
__RETAINED OS_TIMER val_change_timer;
Next, create the timer inside ble_peripheral_task() function right before the for(;;) loop in order to change the value of the characteristic every 2000 milliseconds.
val_change_timer= OS_TIMER_CREATE("val_change", OS_MS_2_TICKS(2000),
OS_TIMER_SUCCESS, (void *)OS_GET_CURRENT_TASK(),
val_change_timer_cb);
In handle_evt_gap_connected() add the following lines in order to start the timer if it was not started yet.
if(!OS_TIMER_IS_ACTIVE(val_change_timer)) {
OS_TIMER_START(val_change_timer,OS_TIMER_FOREVER);
}
5.1.2.3. Setting up the Callback function
The callback function should simply notify the task. Declare its prototype at the start…
static void val_change_timer_cb(OS_TIMER xTimer);
…and define it at any point afterwards.
/*
* val_change_timer callback
*/
static void val_change_timer_cb(OS_TIMER xTimer)
{
OS_TASK_NOTIFY(ble_task_handle,VALUE_CHANGE_NOTIF,eSetBits);
}
5.1.2.4. Altering the BLE Notification functions
Functions mcs_notify_char_value_all() and mcs_notify_char_value() need to be modified as follows:
In ble_custom_service.c remove their prototype declaration
Replace the body of the functions with:
/*
* Notify all the connected peers that characteristic's value has been changed.
*/
void mcs_notify_char_value_all(uint16_t size, const uint8_t* value, uint16_t attr_h, uint16_t ccc_h)
{
/*
* Get the number of connected devices
*/
uint8_t num_conn;
uint16_t* conn_idx;
ble_gap_get_connected(&num_conn, &conn_idx);
/*
* For each connected peer device
*/
while(num_conn--)
{
mcs_notify_char_value(conn_idx[num_conn], size, value, attr_h, ccc_h);
}
if(conn_idx){
OS_FREE(conn_idx);
}
}
/*
* Notify peer at the other end of connection of index conn_idx that a change has occurred on the characteristic.
*/
void mcs_notify_char_value(uint16_t conn_idx, uint16_t size, const uint8_t *value, uint16_t attr_h, uint16_t ccc_h)
{
uint16_t ccc = GATT_CCC_NONE;
/*
* Get the Client Configuration Chracteristic (CCC) value stored in flash memory.
*/
ble_storage_get_u16(conn_idx, ccc_h, &ccc);
/*
* Check whether notifications/indications are enabled for this particular peer with conn_idx
* and send the corresponding event.
*/
if(ccc & GATT_CCC_NOTIFICATIONS)
{
/*
* Send a notification to the peer device with the altered value.
*/
ble_gatts_send_event(conn_idx, attr_h, GATT_EVENT_NOTIFICATION, size, (const void*)value);
return;
}
else if(ccc & GATT_CCC_INDICATIONS)
{
/*
* Send a notification to the peer device with the altered value.
*/
ble_gatts_send_event(conn_idx, attr_h, GATT_EVENT_INDICATION, size, (const void*)value);
return;
}
}
Additionally in do_char_value_write(), alter the arguments passed to the mcs_notify_char_value_all() call with…
mcs_notify_char_value_all(evt->length, evt->value, attr->characteristic_h, attr->characteristic_ccc_h);
Add the function prototypes to ble_custom_service.h
/*
* Function prototypes for notifying all peers of changes of specific characteristic.
*/
void mcs_notify_char_value_all(uint16_t size, const uint8_t* value, uint16_t attr_h, uint16_t ccc_h);
void mcs_notify_char_value(uint16_t conn_idx, uint16_t size,
const uint8_t *value, uint16_t attr_h, uint16_t ccc_h);
5.1.2.5. Set the value
In ble_peripheral_task() function of ble_peripheral_task.c at its start, declare and define the value you want to be updating to. For example…
uint8_t notif_msg[]={'A', ' ', 's' ,'t', 'r', 'i', 'n', 'g', ' ', 'o', 'f', ' ', '2', '0', ' ', 'c', 'h', 'a', 'r', '$'};
uint16_t msg_size = sizeof(notif_msg);
5.1.2.6. Capturing the Task Notification
Capture the notification by placing the following snippet right after if (notif & BLE_APP_NOTIFY_MASK) block.
if (notif & VALUE_CHANGE_NOTIF)
{
set_var_value_cb(notif_msg, msg_size);
mcs_auto_notify_all(msg_size, notif_msg , 0x0b, 0x0d);
#if(!USER_SUPPRESS_LOGS_EN)
printf("Value Change Notifications sent. Size:%d Msg Address:0X%lX\r\n\n", msg_size, (uint32_t)notif_msg);
#endif
}
The above code sets the value of the characteristic with handle 0x0b to the message contained in notif_msg array and then after checking which devices have requested notifications, it sends the notification of the value changing to them.