Bluetooth 5 Lab Manual
Introduction
This document demonstrates how to use the Bluetooth 5 features supported in the BLE SDK 2.13 using the GCC compiler and Simplicity Studio IDE.
The focus of this training session will be on BT5 features supported in BLE SDK 2.13.
Topics covered
- LE Coded and LE 2M PHY
- Multiple Advertisement sets
- Extended advertisements
- Anonymous advertising
Getting Started
Review the following material before starting the Bluetooth 5 labs. Ensure that you have the correct hardware and software to successfully complete the labs.
Hardware Requirements
- 2 Wireless Starter Kits (EFR32BG13/MG13 Radio Boards installed)
- 2 USB mini B cables
- iOS or Android Mobile device
Software Requirements
- Simplicity Studio v4
- Gecko Platform – v2.7
- Bluetooth SDK – v2.13
- Blue Gecko v1.5.1 Mobile App
- Project source files (app-client.c, app-server.c).
Software Installation
Install Simplicity Studio v4 (https://www.silabs.com/products/development-tools/software/simplicity-studio)
Install Device Support by clicking on tab “Select by Product Group”.
Click on Wireless Products. Click Next.
Install Protocol SDKs by clicking menu bar Help -> Update Software. Click on tab for “SDKs” in Package Manager window
Select and Install Gecko Platform – v2.7
Select and Install Bluetooth SDK – v2.13
Install Silicon Labs EFR Connect app from a mobile app store: Google Play or Apple App Store
Add 2M PHY Connections to an Application
Create a Project Using Simplicity Studio IDE
Start by creating an soc-empty sample application.
Click on the Simplicity IDE button in the upper right corner to return to the IDE perspective.
Select File -> New -> Project in the menu bar.
In the Create Project window, Click on Silicon Labs AppBuilder project and click next.
Click Bluetooth SDK and click next.
Click Bluetooth SDK 2.13 and click next.
Click
SOC - Empty
and click next.Enter
soc-bt5-server
for the project name and click next.Select your target board from the list and turn off all configurations except GNU ARM v7.2.1 and click finish.
Creating a new project using Simplicity Studio IDE
Drag and drop
app-server.c
into the project folder and deleteapp.c
.Open
app.h
and enableDEBUG_LEVEL
by changing the value from 0 to 1.
Add 2M PHY Service to GATT
Open the visual GATT editor by double clicking project’s
.isc
file and click on theCustom BLE GATT
.Create a new service by clicking on the Create new item icon in upper right of configurator. Select New Service (now named as Service).
Under General settings, set the Name of the service to
2mphy_test
.Give it the following UUID: a4aabbb3-4de2-41c6-8a3f-3fae9214cd49
This is an important step because the client will look for a server advertising a service with this custom UUID.
Check the Advertise service box.
Create a characteristic for this service by clicking on the Create new item icon and selecting New Characteristic. Note that the
2mphy_test
has to be selected before Characteristic can be created.Under General settings, set the Name of the characteristic to
sample_data
.Under Properties, set the information to only include Read with Requirement = Optional and State = True.
Save
.isc
GATT configurator and Click Generate to update changes to the GATT files.
Add Event Handler Code for 2M PHY Connections
Add an event handler in app-server.c
for the le_connection_phy_status
event. Copy the following code and put it below the comment /* LAB TASK 2M PHY connection: phy status handler */
.
case gecko_evt_le_connection_phy_status_id:
printLog("now using the %s PHY\r\n", getPhyName(evt->data.evt_le_connection_phy_status.phy).string);
break;
Add Event Handler for Scan Request Reporting
Another feature of Bluetooth 5 is the added ability to report scan requests. To add this event handler, paste in the following code after the comment, which reads /*LAB TASK 2M PHY connection: scan request reporting */
.
case gecko_evt_le_gap_scan_request_id:
printLog("received scan request from: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
evt->data.evt_le_gap_scan_request.address.addr[5],
evt->data.evt_le_gap_scan_request.address.addr[4],
evt->data.evt_le_gap_scan_request.address.addr[3],
evt->data.evt_le_gap_scan_request.address.addr[2],
evt->data.evt_le_gap_scan_request.address.addr[1],
evt->data.evt_le_gap_scan_request.address.addr[0]);
break;
This is a purely informative event and no action is required here. This event handler simply prints out the address of the device requesting the scan response. To enable this reporting, also add a call to the following:
gecko_cmd_le_gap_set_advertise_report_scan_request(HANDLE_DEMO,true);
add this call after the comment /*LAB TASK 2M PHY connection: enable scan request */
.
Program Starter Kit with 2M PHY Server Application
- Click Build icon in the tool bar at the top of the Simplicity IDE. The project will compile based on its build configuration. (NOTE: You need to select the project in the Project explorer view on left)
Press the Debug icon in the tool bar. This will flash the project onto the board if it was successfully built. This only updates the program memory.
Once the project is flashed, the Debug perspective is shown and by default the application execution is stopped at
main()
-function. Press the Resume icon in the tool bar to have the application start.
Program Client with 2M Capable Client Application
Now that a Server (aka peripheral) application is set up, build a client which can connect to this server.
As with the server application, the source code for the client is provided (app-client.c
).
Create a new project, as you did in section above and name it
soc-bt5-client
.Replace
app.c
withapp-client.c
. A few helper functions have been added to this template, which are not related to Bluetooth 5 features.Copy
src
directories fromC:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.7\platform\emdrv\gpiointerrupt
and put it inplatform\emdrv\gpiointerrupt\
folder in your project.System Boot event handler is started by adding a startup message to find out when the device has started and the setup for scanning. Paste in the following code for the system boot event, right after the comment
/* LAB TASK 2M PHY CONNECTION: start scanning */
inapp-client.c
.bootMessage(&(evt->data.evt_system_boot)); printLog("BT5 test client started\r\n"); /*set the discovery type for both PHYs to passive */ gecko_cmd_le_gap_set_discovery_type(le_gap_phy_1m|le_gap_phy_coded,0); /* 200 ms scan window min/max*/ gecko_cmd_le_gap_set_discovery_timing(le_gap_phy_1m|le_gap_phy_coded,320,320); /* start listening for devices to connect to */ gecko_cmd_le_gap_start_discovery(scanning_phy,le_gap_discover_generic); gecko_cmd_le_gap_set_discovery_extended_scan_response(true);
The client looks for the server by the service it advertises. Add the following code just after the comment
/* LAB TASK 2MPHY CONNECTION: service UUID */
.static const uint8 silabs_2mphy_uuid[16] = {0xa4,0xaa,0xbb,0xb3,0x4d,0xe2,0x41,0xc6,0x8a,0x3f,0x3f,0xae,0x92,0x14,0xcd,0x49};
A scan response event handler is next. The event used here is a new event available starting in SDK v2.10. This event is enabled by calling
gecko_cmd_le_gap_set_discovery_extended_scan_response(true);
as done above in step 4. Add the following code just after the comment/* LAB TASK: 2M PHY CONNECTION: scan response event handler */
.case gecko_evt_le_gap_extended_scan_response_id: { for(int index = 0; index < evt->data.evt_le_gap_extended_scan_response.data.len;){ if(evt->data.evt_le_gap_extended_scan_response.data.data[index+1] == 0x07){ if(check_uuid(&evt->data.evt_le_gap_extended_scan_response.data.data[index+2], 16) == true){ /*stop scanning for now*/ gecko_cmd_le_gap_end_procedure(); /* and connect to the advertising device using whatever PHY we're scanning on*/ gecko_cmd_le_gap_connect(evt->data.evt_le_gap_extended_scan_response.address, evt->data.evt_le_gap_extended_scan_response.address_type,scanning_phy); break; } } index += evt->data.evt_le_gap_extended_scan_response.data.data[index]+1; } } break;
The two buttons on the WSTK are used these to control the following parameters PB0 to control the PHY used for scanning, and PB1 to control the desired PHY once a connection has been established. To accomplish, use the Bluetooth stack’s external sign mechanism which requires an event handler. Paste in the following immediately after the comment
/* LAB TASK: 2M PHY CONNECTION: external signal handling event */
.case gecko_evt_system_external_signal_id: /* */ if (evt->data.evt_system_external_signal.extsignals==1){ printLog("Switching scanning PHY\r\n"); gecko_cmd_le_gap_end_procedure(); if(scanning_phy == le_gap_phy_1m){ scanning_phy = le_gap_phy_coded; phy_index = 2; } else if (scanning_phy == le_gap_phy_coded){ scanning_phy = le_gap_phy_1m; } printLog(" Starting scanning on %s PHY \r\n", getPhyName(scanning_phy).string); gecko_cmd_le_gap_start_discovery(scanning_phy, le_gap_discover_generic); } else if (evt->data.evt_system_external_signal.extsignals==2){ //use PB1 to increment the desired PHY phy_index = (phy_index+1)%4; desired_phy = supported_phys[phy_index]; gecko_cmd_le_connection_set_preferred_phy(connection, desired_phy, le_gap_phy_1m|le_gap_phy_2m|le_gap_phy_coded ); } break;
Open
app.h
and enableDEBUG_LEVEL
by changing the value from 0 to 1. Include also#include "gpiointerrupt.h"
in the same file.Build the project and flash the resulting hex file to the second WSTK.
Open Consoles to Display 2M Status
The two Bluetooth 5 devices will establish a 1M PHY connection. After a connection is established, the PHY can be changed by pressing PB1 on the client WSTK. If the selected PHY is not supported by the remote server, the connection will fall back to the 1M PHY.
The status of the connections is printed to debug terminals.
Open 2 consoles to show these status messages. Right click the WSTK in the debug adapters perspective as shown, then select the serial1 tab, place the cursor in the text entry field at the bottom, and press enter.
Press reset on both boards to see the startup messages and confirm that both applications are running.
After a connection is formed, press PB1 on the Client board to switch to the 2 Mbps PHY.
The client will now display a message indicating that the 2Mbps PHY is in use.
Compare Server PHY Connection of Mobile Device vs. 2M PHY Client
To establish a 4.2 connection with the server, switch off the client WSTK then restart the server and connect to it using the EFR Connect app in the mobile. Click on the Bluetooth Browser and select the “Empty Ex” server. A 1M PHY connection is established as it loads the GATT information.
Add Multiple Advertisement Sets to an Application
Bluetooth 5 supports multiple advertisements each with its own data and transmitting power and timing parameters. This section explains how an application can simultaneously send out a non-connectable iBeacon advertisement as well as a connectable Eddystone advertisement.
The project loaded in section Add 2M PHY connections to an application, bt5-server, will be modified to demonstrate the new features for Advertisement sets.
Increase Number of Advertisers
max_advertisers
field in the Bluetooth configuration structure, which is found in main.c
file, configures the maximum number of advertisers. Its value can be overwritten in app-server.c
. Put the following code next to /* LAB TASK MULTIPLE ADVT: max_advertisers */
pconfig->bluetooth.max_advertisers = 3;
This will initialize the Bluetooth stack to support the specific amount of advertisements.
Configure Beacons and Enable after Boot Event
In
app-server.c
go to the location marked by the comment/* LAB TASK MULTIPLE ADVT: iBeacons */
and uncomment the following linebcnSetupAdvBeaconing();
If you examine the contents of this function, you’ll see a new APIgecko_cmd_le_gap_set_advertise_tx_power()
. This API allows you to set the TX power used in just this advertiser without affecting other advertisers nor the TX power used in connections. Do this first because it sets the power.Include
#include "infrastructure.h"
intoapp.h
. Enable iBeacon also by setting#define IBEACON
to 1 inapp-server.c
.In
app-server.c
, go to the code section below the comment/* LAB TASK MULTIPLE ADVT: modify your custom URL */
and modify the characters for a custom URL you would like for the physical Web advertisement.Determine the new value with the new URL and modify the length and the characters for the URL.
static uint8_t eddystone_data[] = { 0x03, //Length of service list 0x03, //service list 0xAA, 0xFE, //Eddystone ID 0x10, //length of service data = 6 plus length of URL (silabs.com) that is 10 = 16 = 0x10 0x16, //service data 0xAA, 0xFE, //Eddystone ID 0x10, //frame type Eddystone-URL 0x00, // tx power 0x00, //http://www. 's','i','l','a','b','s','.','c','o','m' };
Navigate to the Event Handler section of code in the
main()
routine.Modify the case statement for
gecko_evt_system_boot_id
after the existing iBeacon instructions. Insert the following code at the location marked by comment:/* LAB TASK MULTIPLE ADVT: EddyStone */
/* EddyStone*/ gecko_cmd_le_gap_bt5_set_adv_data(HANDLE_EDDYSTONE, ADV_PKT, 30, eddystone_data); gecko_cmd_le_gap_set_advertise_configuration(HANDLE_EDDYSTONE,0x01); gecko_cmd_le_gap_set_advertise_timing(HANDLE_EDDYSTONE,160,160,0,0); gecko_cmd_le_gap_set_advertise_channel_map(HANDLE_EDDYSTONE,0x07); gecko_cmd_le_gap_start_advertising(HANDLE_EDDYSTONE,le_gap_user_data, le_gap_non_connectable);
Build and Flash the Application
Click the Build icon in the tool bar at the top of the Simplicity IDE. The project will compile based on its build configuration. (NOTE: You need to select the project in the Project explorer view on left).
Press the Debug icon in the tool bar. This will flash the project onto the board if it was successfully built. This only updates the program memory.
After the project is flashed, the Debug perspective will be shown. Press the Resume icon in the tool bar to start the application.
Use Mobile App to View Multiple Advertisements
Open the BlueGecko app on a smartphone and tap the Bluetooth Beaconing tab.
Multiple beacons broadcast from one device. An iBeacon and Eddystone beacon are displayed.
Install the mobile App Beacon Scanner by Nicolas Bridoux from the Google Playstore if you have an Android phone or eBeacon by Lifestyle from the Apple Appstore. These apps scan for Physical Web advertisements i.e., Eddystone.
Open the Beacon app or enable notifications. The Eddystone URL is shown. You can tap the ‘visit website’ link to visit www.silabs.com.
Extended Advertisements
Getting Started with Extended Advertisements
This section explains extended advertisements. This type of advertisement is used by both the LE Coded PHY for any length of advertising packet and by the 1M PHY for packets longer than 31 bytes. LE coded PHY is discussed first.
Paste in the following code after the comment marked
/* LAB TASK EXTENDED ADVT: 4th advertisement */
.gecko_cmd_le_gap_set_advertise_timing(HANDLE_EXTENDED,160,160,0,0); gecko_cmd_le_gap_set_advertise_phy(HANDLE_EXTENDED,le_gap_phy_coded,le_gap_phy_coded); gecko_cmd_le_gap_start_advertising(HANDLE_EXTENDED,le_gap_general_discoverable, le_gap_undirected_connectable);
Change the maximum number of advertisers setting to 4, as you did in section Increase number of advertisers.
Build the project and download it to the target board as you have in previous sections. Now the server application should be broadcasting 4 beacons: a connectable 1M advertisement, an iBeacon, an Eddystone beacon, and a connectable 125k coded PHY advertisement.
However, this section of code has an intentional error built into it. The task here is to find out what’s wrong and fix it. Each of the BGAPI functions returns an error code, which you can output using
printLog
. See the BGAPI reference manual for error code definitions and for information about acceptable advertising configurations. You may want to turn off scan request reporting here to limit the number of messages being sent to the console and comment out the code added in the section Add Event Handler for Scan Request Reporting.After you’ve fixed the bug, you can move on to the client. Here, you can add code to test the packet type to check if the advertisement was of the extended type and print the PHY used for the primary and secondary advertisements. This information is used to determine which PHYs are actually being used by the advertiser. Paste in the following at the very beginning of the extended scan response event handler.
if(0x80 & evt->data.evt_le_gap_extended_scan_response.packet_type){ printLog("extended advertising packet primary advertisement on %s PHY and secondary advertisment on %s PHY\r\n", getPhyName(evt->data.evt_le_gap_extended_scan_response.primary_phy).string, getPhyName(evt->data.evt_le_gap_extended_scan_response.secondary_phy).string); /* LAB TASK ANONYMOUS ADVERTISEMENT: check and verify reception of anonymous advertising */ /*LAB TASK EXTENDED ADVT: Long Advertising Packet and the 2Mbps PHY */ }
As a bonus exercise, you can also add code here to print out information about the address type and the bond handle. Do the following:
After the code in step 5 (and optionally step 6) has been added, build the project and flash it to client board.
Temporarily power down the server WSTK to prevent the client from connecting to it automatically.
Build the application and download to the target as before.
Press PB0. You’ll see a message on the console indicating that scanning is done on the LE Coded PHY (125k).
Power up the server WSTK.
The client’s console will now connect when it finds the desired service UUID being advertised.
Press PB1 to switch the PHY. Any of the supported PHYs can be selected by pressing PB1 to cycle through the list. The server and client consoles each display the PHY currently in use. Note that the 500k PHY is not supported in this example.
Long Advertising Packet and the 2Mbps PHY
Another feature of extended advertising is the ability to set the PHY for the primary and secondary advertisements independently. This gives the user the ability to use the 2Mbps PHY to save energy.
Go to the Visual GATT Editor of your server application and change the device name to
Extended Advertising Test Device
and change the length parameter to 40.In
app-server.c
, find the comment/* LAB TASK EXTENDED ADVT: 4th advertisement */
and make the following change to the callgecko_cmd_le_gap_set_advertise_phy()
. Add also configurations to set the transmission power and include it in the advertising packets just before start advertising command.gecko_cmd_le_gap_set_advertise_phy(HANDLE_EXTENDED,le_gap_phy_coded, le_gap_phy_2m); gecko_cmd_le_gap_clear_advertise_configuration(HANDLE_EXTENDED,0x01); gecko_cmd_le_gap_set_advertise_configuration(HANDLE_EXTENDED,0x08); gecko_cmd_le_gap_set_advertise_tx_power(HANDLE_EXTENDED,100);
Note that, it is not permitted to be scannable and connectable at the same time. Therefore, the connectability mode is changed from
le_gap_undirected_connectable
tole_gap_connectable_non_scannable
.To see the effect of extended advertising only, comment out the commands that are used to start the legacy advertisements:
bcnSetupAdvBeaconing();
,gecko_cmd_le_gap_start_advertising(HANDLE_DEMO, le_gap_general_discoverable, le_gap_undirected_connectable)
, andgecko_cmd_le_gap_start_advertising(HANDLE_EDDYSTONE,le_gap_user_data, le_gap_non_connectable);
. Build and flash it to the target device.Now, let's modify the client to look for this advertisement and print out the name. Add the following code to the end of the
if
block you added in Section Getting Started with Extended Advertisements, just below the comment/*LAB TASK EXTENDED ADVT: Long Advertising Packet and the 2Mbps PHY */
.for(int index=0;index<evt->data.evt_le_gap_extended_scan_response.data.len;) { /* find start of device name */ if(evt->data.evt_le_gap_extended_scan_response.data.data[index+1] == 8|| evt->data.evt_le_gap_extended_scan_response.data.data[index+1] == 9){ uint8 adv_name[35]; printLog("adv packet size %d\r\n", evt->data.evt_le_gap_extended_scan_response.data.len); printLog("device name: "); snprintf(adv_name, evt->data.evt_le_gap_extended_scan_response.data.data[index], "%s", &evt->data.evt_le_gap_extended_scan_response.data.data[index+2]); printLog("%s\r\n",adv_name); if(127 == evt->data.evt_le_gap_extended_scan_response.tx_power){ printLog("advertised tx power is : unavailable\r\n"); } else { printLog("advertised tx power is : %d and RSSI is %d\r\n", evt->data.evt_le_gap_extended_scan_response.tx_power, evt->data.evt_le_gap_extended_scan_response.rssi); } break; } else{ index += evt->data.evt_le_gap_extended_scan_response.data.data[index]+1; } }
Build the client application and flash to the target as before.
Observe in the client’s console that the client now reports the server’s TX power as well as the RSSI of the advertisement.
To see the effects of the advertising PHY being used switch to the Energy Profiler perspective.
In the Energy Profiler, click the Quick Access menu -> Start capture then select your server device as shown below and click OK.
Let the energy capture run for a few seconds then use the slider in the bottom right corner of the screen to adjust the timebase to 20 ms so that you can see only 2 advertisements. Note the average current. (Hint: set
DEBUG_LEVEL
of the server to 0 inapp.h
, it may also be necessary to power cycle the WSTK to get the results shown below)Stop the energy capture using the Quickstart menu and Switch back to the SimplicityIDE perspective. Change the PHY used for the secondary advertisement to the 125k coded PHY as follows:
gecko_cmd_le_gap_set_advertise_phy(HANDLE_EXTENDED,le_gap_phy_coded, le_gap_phy_coded);
Rebuild and flash to the target board again and switch to the energy profiler and start capture as before. Adjust the timebase as in the previous step and note the new average current. You should see the average current go up significantly in the second measurement.
Anonymous Advertising
This section explains anonymous advertising, which is a new feature in Bluetooth 5 that allows an advertisement to omit the device address. Anonymous advertising is only available in extended advertisements. To make the extended advertisement anonymous, open the server application and follow the following steps.
Set configuration
gecko_cmd_le_gap_set_advertise_configuration(HANDLE_EXTENDED,0x02)
before the call togecko_cmd_le_gap_start_advertising()
. This sets the anonymous advertising flag.Build the project and download to the target as before.
On the client side:
Open
app-client.c
and add the following below the comment/* LAB TASK ANONYMOUS ADVERTISEMENT: check and verify reception of anonymous advertising */
.if (evt->data.evt_le_gap_extended_scan_response.address_type & 0xFF) { int i = 0; printLog("Received scan request from: "); for (i = 0; i < 5; i++) { printLog("%02x:", evt->data.evt_le_gap_extended_scan_response.address.addr[5 - i]); } printLog("%02x\r\n", evt->data.evt_le_gap_extended_scan_response.address.addr[0]); }
Build the project and flash it to the target client device.
Open the console and you’ll see that the client reports the address as 00:00:00:00:00:00. Note: If you set the primary advertising channels as
le_gap_phy_coded
on the server side, remember to press PB0 to start scanning in Coded PHY (125K) on the client side.
This is a simple feature and it completes the lab portion of the training exercise.
Periodic Advertising
Periodic advertising is one of the features of Bluetooth 5's extended advertising which allows the advertiser and one or multiple scanners to sync with each other and wake up at the same time.
In this section a simple periodic advertising application that syncs a counter value is implemented. The counter value is incremented every second, which is triggered by a soft-timer.
On the server side:
Open the visual GATT editor by double clicking project’s
.isc
file.Create a new service by clicking on the Create new item icon in upper right of configurator. Select New Service.
Under General settings, set the Name of the service to
periodicSync
.Give it the following UUID: 2e7f05cd-df04-4e03-892b-9a4612c79bbe.
This is an important step because the client will look for a server advertising a service with this custom UUID.
Check the Advertise service box.
Create a characteristic for the new service by clicking on the Create new item icon and selecting New Characteristic.
Under General settings, set the Name of the characteristic to
testCounter
.Under General settings, check the User description box and add the text "this is just a placeholder" in the space.
Under Properties, set the information to only include Read with Requirement = Optional and State = True.
Save the GATT configurator and click Generate to update changes to the GATT files.
Open
app-server.c
and initialize periodic advertising feature. Add the following line of code below the comment/* LAB TASK PERIODIC ADVT: initialize periodic advertisement */
.gecko_init_periodic_advertising();
Define an array for periodic advertisement data, below the comment
/* LAB TASK PERIODIC ADVT: initialize periodic advertisement data */
.static uint16 counter = 0; static periodicData myCounter = { .length = (uint8)5, .type = (uint8)0xFF, .manuf_HI = (uint8)0xFF, .manuf_LO = (uint8)0xFF, .counter_LO = (uint8)0, .counter_HI = (uint8)0 }; periodicData *pData = &myCounter;
Make the following changes to the demo advertising set (i.e.,
HANDLE_DEMO
). Note that the stack will automatically select extended advertising PDUs if periodic advertising is enabled.case gecko_evt_system_boot_id: gecko_cmd_system_set_tx_power(100); gecko_cmd_le_gap_set_advertise_tx_power(HANDLE_DEMO,30); gecko_cmd_le_gap_set_advertise_timing(HANDLE_DEMO, 160, 160, 0, 0); gecko_cmd_le_gap_clear_advertise_configuration(HANDLE_DEMO,1); gecko_cmd_le_gap_start_advertising(HANDLE_DEMO,le_gap_general_discoverable, le_gap_non_connectable); gecko_cmd_le_gap_start_periodic_advertising(HANDLE_DEMO,160,160,1); /* LAB TASK PERIODIC ADVT: set advertising data and soft timer */ break;
Set advertising data and soft timer that will fire every second. Add the following code below the comment
/* LAB TASK PERIODIC ADVT: set advertising data and soft timer */
.gecko_cmd_le_gap_bt5_set_adv_data(HANDLE_DEMO, 8, sizeof(periodicData), (const uint8 *)pData); printLog("\r\n Counter: %d \r\n", counter); gecko_cmd_hardware_set_soft_timer(32768, 0, 0);
Create an event handler for the expired timer, increment the counter, and reset the periodic advertising data.
case gecko_evt_hardware_soft_timer_id: counter++; pData->counter_HI = (uint8) (counter >> 8); pData->counter_LO = (uint8) (counter & 0xFF); //Reset the advertising data pointers to reflect the change in data gecko_cmd_le_gap_bt5_set_adv_data(0, 8, sizeof(periodicData), (const uint8 *)pData); printLog("\r\n Counter: %d \r\n", counter); break;
Build your project and flash it to the target device.
Open app-client.c
and make the following changes.
Declare the UUID of the periodic advertisement service just below the
/* LAB TASK PERIODIC ADVT: periodic advertising service UUID*/
comment.static const uint8 periodic_sync_uuid[16] = {0xbe,0x9b,0xc7,0x12,0x46,0x9a,0x2b,0x89,0x03,0x4e,0x04,0xdf,0xcd,0x05,0x7f,0x2e};
Configure the maximum number of synchronizations the Bluetooth stack needs to support. Add the following code just before the gecko initialization, below the comment
/* LAB TASK PERIODIC ADVT: Set the maximum number of periodic sync allowed */
pconfig->bluetooth.max_periodic_sync = 1;
Enable periodic advertisement synchronization in the Bluetooth stack by calling the following function next to
gecko_init()
, just after the comment/* LAB TASK PERIODIC ADVT: initialize periodic sync feature */
.gecko_bgapi_class_sync_init();
Replace the the system boot event handler with the following code to start scanning.
case gecko_evt_system_boot_id: printLog("BT5 CLIENT STARTED\r\n"); printLog("Start scanning on %s PHY\r\n", getPhyName(scanning_phy).string); gecko_cmd_le_gap_set_discovery_timing(le_gap_phy_1m|le_gap_phy_coded,200,200); gecko_cmd_le_gap_set_discovery_type(le_gap_phy_1m|le_gap_phy_coded,0); gecko_cmd_le_gap_start_discovery(scanning_phy,le_gap_discover_observation); gecko_cmd_le_gap_set_discovery_extended_scan_response(true); break;
Replace the event handler for extended scan responses with the following code.
case gecko_evt_le_gap_extended_scan_response_id: { /* Only look at extended advertisements */ if ((evt->data.evt_le_gap_extended_scan_response.packet_type & 0x80)!= 0x80) break; // Exit if sync is already opened for our service if (syncOpened) break; // If it is extended advertisement and sync is not opened, check if the service match if (serviceMatch(evt->data.evt_le_gap_extended_scan_response.data.data, evt->data.evt_le_gap_extended_scan_response.data.len)) { printLog("Found the periodic service. Attempting to open sync ...\r\n"); uint16 skip = 1, timeout = 20; // Open sync syncOpenResponse = gecko_cmd_sync_open(evt->data.evt_le_gap_extended_scan_response.adv_sid, skip, timeout, evt->data.evt_le_gap_extended_scan_response.address, evt->data.evt_le_gap_extended_scan_response.address_type); if (!syncOpenResponse->result) { sync_handle = syncOpenResponse->sync; printLog("\r\n SYNC HANDLE: %d\r\n", sync_handle); } } } break;
Create an event handler for sync open event.
case gecko_evt_sync_opened_id: printLog("evt_sync_opened\r\n"); /* LAB TASK PERIODIC ADVT: stop scanning */ break;
Stop scanning to save energy by ending the gap procedure. Add the following code below the comment
/* LAB TASK PERIODIC ADVT: stop scanning */
.if(evt->data.evt_sync_opened.sync == sync_handle) { syncOpened = true; gecko_cmd_le_gap_end_procedure(); }
Create an event handler for sync data read from the server.
case gecko_evt_sync_data_id: if(evt->data.evt_sync_data.sync == sync_handle){ printLog("\r\n Sync handle: %d\r\n", evt->data.evt_sync_data.sync); counter = (evt->data.evt_sync_data.data.data[5] << 8) + evt->data.evt_sync_data.data.data[4]; printLog("\r Counter value: %d\r\n", counter); printLog("periodic sync RSSI %d and Tx power %d\r\n", evt->data.evt_sync_data.rssi, evt->data.evt_sync_data.tx_power); printLog("periodic data status %d\r\n", evt->data.evt_sync_data.data_status); } break;
Create an event handler for a closed sync event.
case gecko_evt_sync_closed_id: // Check if the sync handle is our service ID if (evt->data.evt_sync_closed.sync == sync_handle) { printLog(" Periodic sync closed. reason 0x%2X, sync handle %d", evt->data.evt_sync_closed.reason, evt->data.evt_sync_closed.sync); syncOpened = false; } /* restart discovery */ gecko_cmd_le_gap_start_discovery(scanning_phy, le_gap_discover_observation); break;
Build the project and flash it to the targeted client device. Open the console on both devices and verify the counter value on the server being reflected on the client.
Disable the debug messages for the client in app.h
by setting DEBUG_LEVEL
to 0. Build the project and flash it to the device. Open the Energy Profile perspective in Simplicity Studio. Go to Quick access and Start Energy Capture for the client device. Zoom-in on the time axis to 20 ms. After a few seconds, pause the energy capture and verify the average current reading. The value should be close to the reading shown in the figure below.