Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

CC2640 Eddystone Beacon Implementation

From Texas Instruments Wiki
Jump to: navigation, search


As described in the “Bluetooth® low energy Beacons” Application Note, generally a Bluetooth low energy (BLE) ‘beacon’ is a device broadcasting a non-connectable advertising packet carrying small pieces of information to nearby devices. Depending on the timing and the information conveyed within the packet, beacons can enable a variety of use cases including but not limited to proximity awareness, synchronization, identification, or just informing.

Some vendors have defined a protocol or format for how the beacon is implemented in a larger ecosystem. For example, Apple has defined the iBeacon protocol, available under an MFi license, for use with iOS devices.

Eddystone is an open beacon protocol specification from Google aimed at improving “proximity-based experiences” with support for both Android and iOS smart device platforms. These experiences are implemented by specifying various beacon payload formats, defined as “frames-types”, as well as a corresponding set of APIs used to access these payloads from the smart device (e.g., and Android smart phone).

This wiki page will describe how to implement an example Eddystone beacon device using the TI BLE-Stack V2.1 SDK on the SimpleLink™ CC2640 Bluetooth Smart wireless MCU. The lower power consumption and wide operating voltage capability make the CC2640 an ideal platform for implementing battery-powered Eddystone beacons.

Although beacons are, by definition, broadcast-only devices, the concept of a “connectable beacon” will be described. Having the beacon enter a connectable state (technically, switching from the GAP broadcaster to the peripheral role) is desirable for the purposes of provisioning and updating the beacon’s metadata. The Eddystone protocol defines such a mode that allows the beacon’s data to be updated by an authorized client.

The project files and the source code files that were created or modified for Eddystone Beacon device implementation is available at


Through this wiki page, we will know what need to be implemented on top of the existing SimpleBLEPeripheral sample application to make a complete working Eddystone beacon example project named SimpleEddystoneBeacon.

Projects Overview and Prerequisites

Prior to following the examples described in this wiki page, the designer should have a detailed understanding of the TI BLE-Stack SDK as described in the SW Developer’s Guide, the Bluetooth low energy Beacons application note, and the Google Eddystone protocol specification.

The sample application SimpleEddystoneBeacon requires TI BLE-Stack V2.1. Either IAR Workbench for ARM 7.40.2 or CCS 6.1 IDEs can be used to build the project. The SimpleEddystoneBeacon project will run on the CC2650DK (SmartRF06EB + CC2650EM) and CC2650 SensorTag reference platforms. An optional smartphone and test application can be used to validate the Eddystone beacon implementation.

The GitHub repository CC2640_simpleeddystonebeacon includes minimum number of files necessary to build the project when they are put on top of the existing BLE-Stack V2.1 installation. It consists of project/workspace files for IAR/CCS as well as simpleEddystoneBeacon.c and simpleEddystoneBeacon.h which are for the application and eddystoneURLCfg.c and eddystoneURLCfg.h which provide URF Configuration service. The slightly modified peripheral.c is also included. To install SimpleEddystoneBeacon project, copy the repository on the <INSTALL_DIR>\Projects\ble. Where, <INSTALL_DIR> is the location where TI BLE-Stack 2.1 is installed. By default it is C:\ti\simplelink\ble_cc26xx_2_01_00_44423.

The SimpleEddystoneBeacon application projects have the configurations for CC2650DK and CC2650 SensorTag. Since SensorTag configurations are combined with OAD option as well, Chapter 9 of CC2640 BLE OAD User's Guide needs to be read carefully before building those configurations. CC2640 BLE OAD User's Guide is available at <INSTALL_DIR>\Documents.

Design and Implementation

Operation Modes Overview

The Eddystone protocol defines three frame-type formats (referred to as “frames”) which are transmitted by the beacon device are described in the table below.

Frame Type Description
UID Unique identifier that can identify a particular beacon. Useful for location aware applications.
URL Compressed web URL, e.g.,, that can be launched by the smart device application.
TLM Telemetry information, such as battery voltage & temperature of the beacon.

These frames are described in more detail in the Eddystone protocol specification. Each frame represents an Advertising packet, up to the maximum 31 byte payload defined by the Bluetooth 4.0 core specification.

The Eddystone Beacon defines two modes of operation, Regular Advertising Mode and an optional URL Configuration Mode. These operating modes are related by five individual operational states. In Regular Advertising Mode, the beacon is operates as a traditional broadcaster sending non-connectable advertisements consisting of UID, URL or TLM frames. In URL Configuration Mode, the beacon transmits connectable advertisements to allow a client to connect, and if authorized, update the URL content and the system parameters via the URL Configuration Service.

The operating state transitions for these modes of operation are depicted in the diagram below, along with the corresponding actions used to transition states in the SimpleEddystoneBeacon example project. States shown with a grey circle represent URL Configuration Mode while the other states represent Regular Advertising Mode.

SimpleEddystoneBeacon Operation Mode Transitions

It is important to note that the Eddystone protocol does not specify the type, when or how often a particular frame is transmitted, or the actions that trigger a particular state transition. These details are implementation-specific. An Eddystone Beacon may, for example, transmit only URL frames, or a combination of all three frames at different intervals.

In this design, the beacon device sends either UID frames or URL frames regularly and TLM frames intermittently while in Regular Advertising mode. The state transitions between UID and URL are toggled by RIGHT button press. For practical reasons, TLM frames are expected to be observed less frequently than UID or URL frames, so in this design, they are sent only every 10th advertise of UID or URL.

URL Configuration mode can be entered by entering the Config Mode advertising state in this design. It is triggered by LEFT button press. Exiting Configuration mode can be caused by LEFT button press or any type of termination of the connection. Generally the central terminates the connection when it’s done updating the beacon to let the beacon resume Regular Advertising Mode.

In order to use button press to trigger some of the transitions, key event handler needs to be implemented. Button press handling is implemented slightly differently by hardware platform. In this implementation, functions in board_key.c are used for the SmartRF06EB while the equivalent code for the SensorTag has been added to the application source file. In any case, SimpleEddystoneBeacon_keyChangeHandler() is registered as the callback and eventually the key event SEB_KEY_CHANGE_EVT is handled by SimpleEddystoneBeacon_handleKeys().

Regular Advertising Mode

We use advertising for four different purposes in total regardless the operation mode. Properties of each type of ADV’s used in this implementation are summarized in the table below.

UID/URL/TLM Frame URL Configuration Mode ADV
ADV Interval From URL Cfg for UID/URL, 10x longer for TLM Default Interval
TX Power From URL Cfg Medium Power Mode
Connectable No Yes

As switching from one advertising packet to another at run time is required, we need to take a look at how to set the parameters to change the properties for Regular Advertising mode in this section. Also, how to get the information to populate the payload of each packet is also covered.

Setting Regular Advertising Mode Advertising Parameters

As shown in the table above, there are five properties to be changed when toggling between Regular Advertising mode & URL Configuration mode.

ADV Event Type can configured using GAPRole_SetParameter() with GAPROLE_ADV_EVENT_TYPE as the parameter ID and GAP_ADTYPE_ADV_NONCONN_IND as the value since Regular Advertising mode is non-connectable.

ADV Type Flags is an item included in an advertising packet. The GAP_ADTYPE_FLAGS field of the struct variable eddystoneAdv for Regular Advertising mode is initialized with GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED since Regular Advertising Mode is non-discoverable.

ADV Interval is set by specifying minimum and maximum intervals for limited and general discoverable ADVs. Typically the all four parameter are set to the same value to get the desired interval as follows:

  GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
  GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
  GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
  GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);

Note that particular design should select advertising parameters that balance power usage with beacon power use. Using faster advertising intervals allow for quicker discovery by the smart device, while longer intervals allow for longer beacon battery life.

The value from the parameter corresponding with URLCFGSVC_BEACON_PERIOD of URL Configuration service is reflected on advInt. Unit conversion is necessary in this case since the value from URL Configuration service is in millisec while GAP_SetParamValue() expects the number of 625-microsec ticks. See section 5.3.2 for more details about URL Configuration service. Basically the beacon period from URL Configuration service is supposed to be applied to URL frame advertising. However, it is used for UID as well in this implementation since no external means to setup the interval for UID is defined in the Eddystone specification. Interval for TLM is depending on the interval for UID/URL because it based on number of UID/URL frames that have sent since the last TLM frame in this implementation.

We use the value from the parameters corresponding with URLCFGSVC_ADV_TX_PWR_LVLS and URLCFGSVC_TX_POWER_MODE of URL Configuration service to get the designated TX Power in dBm.

Together with all the above properties set up, when the ADV data is updated, advertising is ready to start. The next section describes more about updating ADV data.

Lastly, non-connectable advertising mode is enabled to actually start sending out the packets at the given rate and power. GAPRole_SetParameter() with the parameter ID GAPROLE_ADV_NONCONN_ENABLED is used to start or stop advertising in Regular Advertising mode.

All the procedures described above in this section are done in SimpleEddystoneBeacon_applyConfiguration() and SimpleEddystoneBeacon_startRegularAdv().

Populating the Eddystone Frame Payload

Data in UID and URL frames generally don’t need to be changed unless the beacon device has had some update during the last Configuration mode operation. Ranging Data subfield of UID frame and all subfields of URL frame except Frame Type need to be updated upon exit of Configuration Mode. It is implemented in SimpleEddystoneBeacon_applyConfiguration().

A couple of algorithms are recommended to generate 10-byte ID Namespace subfield and 6-byte ID Instance subfield of UID by the Bluetooth core specification for better uniqueness. We used some meaningless numbers for them in this implementation. For actual product, the number assignments in function SimpleEddystoneBeacon_initUID() will need to be replaced with proper algorithms.

For URL frame, SimpleEddystoneBeacon_encodeURL() facilitates conversion of regular null-terminated string URL into encoded numbers.

TLM frames require special handling compared to UID and URL frames because the frame data needs to be updated with most recent information every time a TLM frame is broadcasted. Updating of the TLM payload is done in SimpleEddystoneBeacon_updateTLM(). Let’s look into that function to know where all the information required for TLM come from.

The battery voltage VBATT subfield can be obtained from AONBatMonBatteryVoltageGet(). To use the battery monitor function, aon_batmon.h of driverlib should be included.

A constant value is currently used for the temperature TEMP subfield since the SmartRF06EB doesn’t have a temperature sensor on it. On the SensorTag, the integrated temperature sensor can be utilized for this.

For ADV_CNT subfield, we need an event from the stack, notifying the application of completion of each advertising operation. HCI_EXT_AdvEventNoticeCmd() is the API to register an event that will be sent upon completion of an ADV send out. We register SEB_ADV_COMPLETE_EVT and check it in the processing loop of stack events that come with the signature of 0xFFFF. The event SEB_ADV_COMPLETE_EVT is eventually processed in SimpleEddystoneBeacon_processAdvCompleteEvt(). Indeed, this event processing function is not only for counting the number of ADV’s. Which type of Eddystone frame should be sent is also determined in it.

A 1-sec resolution clock tick counter is used, as an example, for SEC_CNT subfield though the Eddystone spec requires 100-ms resolution. UTC_clock.c which is originally used by TimeApp example project was added for this. Typically TLM frame is supposed to be sent intermittently and we send it every 10 seconds by default in this example, so 1-sec resolution is allowable for now.

When a local Eddystone frame is populated with all necessary information, it needs to be handed over to the BLE stack. GAPRole_SetParameter() with the parameter ID GAPROLE_ADVERT_DATA is used for that purpose.

All the procedures described above in this section are handled by SimpleEddystoneBeacon_selectFrame().

Note that dynamic change of ADV payload in non-connectable advertising mode is not considered in peripheral.c by design because it is originally intended to take care of GAP role of peripheral device which normally uses connectable advertising. To enable dynamic ADV payload change in non-connectable advertising mode, we need to make a small modification in gapRole_processGAPMsg() in peripheral.c as follows:

        gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;
        if (pPkt->hdr.status == SUCCESS)
          if (pPkt->adType)
            // Setup the Response Data
            pPkt->hdr.status = GAP_UpdateAdvertisingData(selfEntity,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData);
          else if ((gapRole_state != GAPROLE_ADVERTISING)   &&
                   (gapRole_state != GAPROLE_CONNECTED_ADV) &&
                   (gapRole_state != GAPROLE_CONNECTED || 
                    gapRole_AdvNonConnEnabled == TRUE)      &&
                   (gapRole_state != GAPROLE_ADVERTISING_NONCONN) && 
                   (Util_isActive(&startAdvClock) == FALSE))
            // Start advertising

This change is incorporated into the accompanying patch included in the repository.

URL Configuration Mode

The URL Configuration Mode is an optional method to update the beacon’s URL content. A designer may wish to omit this mode or modify the accompanying service based on implementation-specific requirements.

Setting URL Configuration Mode Advertising Parameters

With the same method described in 'Setting Regular Advertising Mode Advertising Parameters' but different properties shown in the above table, we can make the right set up for Configuration Mode advertising. In this section, only the differences will be noted.

For ADV Event Type, GAP_ADTYPE_ADV_IND as the value is used since Configuration Mode is connectable.

For ADV Type Flags, the GAP_ADTYPE_FLAGS field of the struct variable eddystoneCfgAdv for Configuration mode is initialized with GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED together with GAP_ADTYPE_FLAGS_GENERAL since Configuration mode is discoverable.

advInt for ADV Interval is set to GAP_ADTYPE_ADV_IND. Typically the interval for Configuration mode is shorter than that for Regular Advertising mode.

TX Power should be set to the value corresponding to TX_POWER_MODE_MEDIUM.

Together with all the above properties set up, when the ADV data is updated using GAPRole_SetParameter() with the parameter ID GAPROLE_ADVERT_DATA, advertising is ready to start.

Lastly, connectable advertising mode is enabled by calling GAPRole_SetParameter() with the parameter ID GAPROLE_ADVERT_ENABLED.

All the procedures described above in this section are handled in SimpleEddystoneBeacon_startConfigAdv().

URL Configuration Service

URL Configuration service is implemented in eddystoneURLCfg.c. The application can access the nine characteristics of the service using URLCfgSvc_GetParameter() and URLCfgSvc_SetParameter(). The application registers a callback that is called when changes happen in the characteristics by the central. In this implementation, only Reset characteristic change gets the application notified.

Once the beacon device is connected with a central (e.g., smart phone) in URL Configuration Mode, some of the system properties on the beacon device can be modified by the central through writing to characteristics if the Lock State is FALSE. Only Unlock characteristic can be written to if Lock State is TRUE.

Updated characteristics get reflected on the corresponding properties in SimpleEddystoneBeacon_applyConfiguration() when the beacon device exits URL Configuration Mode to enter Regular Advertising Mode by being disconnected for any reason such as termination or time out. However, actions should be immediately taken when Reset characteristic changes.


In order to verify all the features and functions described in the application note, devices implementing the observer and/or central GAP roles are necessary. A GitHub Eddystone repository comes with validation tools for that purpose. Using Eddystone Validator and Eddystone-URL Config Validator, we can verify URI/URL/TLM frames and URL Configuration Mode respectively. Below are the screenshots of Eddystone Validator and Eddystone-URL Config Validator that have been used to verify SimpleEddystoneBeacon sample application.

The validators used to validate SimpleEddystoneBeacon project are based on the commit SHA b5f23b3f895007c761e2303db4c10df7af2f997f of the GitHub Eddystone master branch.

Besides the validators, there are several Android/iOS applications that can be used to test Regular Advertising Mode functionalities of Eddystone-compatible beacons. For example, using Estimote Android App, we can see how Eddystone-compatible advertising packets are parsed and used by applications as shown in the screenshots below. These smart phone applications are not developed or supported by Texas Instruments.


In this wiki page, the basic concept of Eddystone Beacon, how connectable beacon application can be implemented on top of the existing sample application SimpleBLEPeripheral and how the compatibility to Eddystone specification cab be tested are described. Also, events, callbacks and usages of hardware drivers are introduced mainly for obtaining information to populate TLM frame.

We see, with a simple feature addition and modification on the sample application, connectable beacon devices such as Eddystone-compatible beacon device can be easily developed.