Simple beacon for nRF51822

Dependencies:   BLE_API mbed nRF51822Copy

Fork of BLE_iBeacon by Bluetooth Low Energy

This is the demo beacon for ARM TechCon 2014.

Based on the original library, this demo reads the onboard switches and temperature sensor and beacons them out as a BLE advertisment.

main.cpp

Committer:
wd5gnr
Date:
2014-10-01
Revision:
45:e64d1e920cd1
Parent:
44:6a5d976d6e61

File content as of revision 45:e64d1e920cd1:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "BLEDevice.h"
#include "nrf_temp.h"

#define ADVTIME 1000    // advertise time in ms
#define UPDTIME 2000   // update time in ms

BLEDevice ble;
Timer msclock;
DigitalOut activity(LED1);  // blinks to show activity
DigitalOut errLED(LED2);    // comes on if error occurs
DigitalIn btn1(BUTTON1);
DigitalIn btn2(BUTTON2);

#define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console;
                               * it will have an impact on code-size and power consumption. */

#if NEED_CONSOLE_OUTPUT
Serial  pc(USBTX, USBRX);
#define DEBUG(...) { pc.printf(__VA_ARGS__); }
#else
#define DEBUG(...) /* nothing */
#endif /* #if NEED_CONSOLE_OUTPUT */

// Try a BLE function and if failed, light LED 2 and halt
// but don't catch fire....

void errTry(ble_error_t fn,int n=1)
{
    if (fn)
    {
        while (1)
        {
            for (int i=0;i<n*2;i++)
            {
                wait_ms(250);
                errLED=!errLED;
            }
        wait_ms(2000);
        }
    }
} 



/*
 * Reference:
 *  Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18
 */

/*
 * The Beacon payload (encapsulated within the MSD advertising data structure)
 * has the following composition:
 * 128-Bit UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
 * Major/Minor  = 0000 / 0000 (We steal this for data)
 * Tx Power     = C8
 */
   uint8_t beaconPayload[] = {
    0x4C, 0x00,   // vendor ID
    0x02,         // packet type (2)
    0x15,         // length
    0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,  // UUID
    0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61,
    0x00, 0x00,  // Major
    0x00, 0x00,  // Minor
    0xC8         // TXPower
,   0x99         // one spare byte!
};


// Read temperature
int temp_read()
{
    int t;
    NRF_TEMP->TASKS_START=1;
    while (NRF_TEMP->EVENTS_DATARDY==0);
    NRF_TEMP->EVENTS_DATARDY=0;
    t=nrf_temp_read();
    NRF_TEMP->TASKS_STOP=1;
    return t;
}


// Grab the sensors and put 55AA in major
// Put minor data for temperature reading 
// (which returns 0 on this board)
// as well as switches
void readSensors()
{
    int temp;
    beaconPayload[20]=0x55;
    beaconPayload[21]=0xAA;
    temp=temp_read();  //  (should read 0-1023)
    if (!btn1) temp|=0x8000;   // switches are inverted sense (0=pressed)
    if (!btn2) temp|=0x4000;
        
    beaconPayload[22]=temp>>8;
    beaconPayload[23]=temp&0xFF;

}

// Build up advertising packet including sensors
void setupBLE()
{
    ble.clearAdvertisingPayload();
    readSensors();
    errTry(ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE),5);
    errTry(ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, beaconPayload, sizeof(beaconPayload)),6);    

}





int main(void)
{
    char *devname="DDJ";
    DEBUG("Init\n\r");
    activity=errLED=0;
    nrf_temp_init();
    errTry(ble.init(),1);
    NRF_TEMP->TASKS_START=1;

// Build advert
    setupBLE();
    
    // Set up general parameters
    errTry(ble.setDeviceName((uint8_t *)devname),2);
  #if 0
    errTry(ble.setAdvertisingType(GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED));  // this will give you one "ping" and no repeats
  #else
    ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);  // This will give you a ping every interval
  #endif
   
    ble.setAdvertisingInterval((16*ADVTIME)/10); /* 1s; in multiples of 0.625ms. is 1600 */
   
// start timer for sensor reading 
    msclock.start();

    while (true) {
        msclock.reset();    
        errTry(ble.startAdvertising(),3);   // start advert
         wait_ms(UPDTIME);                // wait awhile
        activity=!activity;               // blink led
        errTry(ble.stopAdvertising(),4);    // stop advert
        setupBLE();                       // set up with new data
    }

}