Jan 01

iBeacons on the TI CC2541

 Adding Logic

There are a few things you can do with an iBeacon:

  1. Turn it on/off
  2. Vary the output power, if your hardware supports it
  3. Vary how often it advertises
  4. Vary the advertisement

That’s about it.  Now we just need to figure out how to implement it.

Some general hints when working with the BLE Examples

Here’s a few pointers to save you time when trying to find your way through the stack.  This is not meant to scare you off, but to help guide you as you go through the code.

  • There are lots of global variables that are typed static and limited to the file they are declared in.  Often it is easier to remove the static typing so that you can declare them as external variables in the other files and access them than trying to figure out how to pass the information through the application structure.
  • The same goes with #define.  Some are not in header files and you will have to copy them from elsewhere.
  • Lots goes on by passing pointers to variables.  You will spend time tracking down the variable that a pointer points to.
  • You will spend time learning the application structure.  It’s basically its own RTOS.  There is a lot of documentation about how it works, but there is a steep learning curve.  It would be really nice if TI had the libraries setup so that you initialized them and then went about things as you normally would and just called a function to send an advertisement (anyone from TI listening?).  It does not work that way.
  • The ways I got things working for the first proof-of-concept are ugly and I am pretty sure not how it is intended to work, but that’s how I did it.  I didn’t get a week long training course on the BLE stack and associated RTOS.

Trigger on Keypress

With the demo kit the easiest way to test changing the different things is using the buttons on the dev board.  We can insert logic to do our bidding where the keypresses are handled in the code.  By default the project does not have the compiler define CC2540_MINIDK defined.  Without this set the logic for switch 1 and 2 will not be compiled in.  We need to set this under Project -> Options -> C/C++ Compiler and then in the Preprocessor tab add CC2540_MINIDK to the Defined Symbols.  Note, doing this will cause the devboard to not transmit until one of the switches is pressed.  From there you can hook into

void OnBoard_KeyCallback ( uint8 keys, uint8 state )


uint8 OnBoard_SendKeys( uint8 keys, uint8 state )

and put in our logic.

Changing the Advertisement

The tutorial linked to earlier explains how to setup your advertisement so that it is recognized as an iBeacon.  In the iBeacon we have two unsigned shorts (16-bit) to play with the Major and Minor.  Changing the UUID in the Advertisement will cause your data to get sent to another program, or to nothing on an iDevice, depending on how your app is configured.  The Major value is located at index 22 & 23 of advertData[].  The Minor value is located at index 24 & 25 of advertData[].  Both are big endian (high byte first).

Changing the memory there is not enough.  The BLE stack needs to have the data copied into it.  To do that we need to call 

GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );

.  Here’s the catch, we will be calling it from outside the file advertData is defined in, so sizeof(advertData) will throw an error.  We can change it to

GAPRole_SetParameter( GAPROLE_ADVERT_DATA, advertData[0]+1, advertData );

and that will work.  We need to remove the static keyword from the declaration of advertData so that it is accessible from other files and declare extern uint8 advertData[]; in the file we are updating the advertising data from as well.

The function GAPRole_SetParameter() also needs slight modification.  Inside the function in the GAPROLE_ADVERT_DATA case we need to add 

GAP_UpdateAdvertisingData( gapRole_TaskID,TRUE, len, gapRole_AdvertData );


gapRole_AdvertDataLen = len;

so that it is loaded for the next advertisement.  Much of this came from discussions on e2e.ti.com.

Adding this all together, this is how it looked in the iBeacon Locate app:

iBeacon Screenshot

A screen shot of successfully changing the minor value for our iBeacon example.

Next we are going to look at how to set a timeout timer to turn off the iBeacon.

Permanent link to this article: http://blog.curioussystem.com/2014/01/ibeacons-on-the-ti-cc2541/


1 ping

  1. Gokhan

    Can you put batter level data from battery service in advertisement data?

    etc: battery level:%88 So is it possible to put that data in advertisement also?

  2. Dan

    Could you upload the firmware source somewhere? The tutorial page originally linked to has disappeared. If you also have a backup copy of the tutorial page, that would be great also.

  3. Glenn

    Hi Chad, do you have a copy of the radius networks CC2541 iBeacon project for the CC2541DK-MINI dev kit? Your links doesn’t work any more (they’ve moved the project/taken it down).

    Many thanks

  1. Updates on iBeacons with the CC2540 » Things Learned Along the Way

    […] good news is that I was able to leverage the code I wrote for the CC2541 previously.  This project was a little more complicated.  It has to take commands over the asynchronous […]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>