Simple beacon for nRF51822
Dependencies: BLE_API mbed nRF51822Copy
Fork of BLE_iBeacon by
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.
Diff: main.cpp
- Revision:
- 44:6a5d976d6e61
- Parent:
- 43:b5dc3241fc91
- Child:
- 45:e64d1e920cd1
--- a/main.cpp Tue Sep 02 16:09:59 2014 +0000 +++ b/main.cpp Sun Sep 21 19:23:27 2014 +0000 @@ -16,8 +16,17 @@ #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. */ @@ -29,10 +38,28 @@ #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); + } + } +} + + + /* - * For this demo application, populate the beacon advertisement payload - * with 2 AD structures: FLAG and MSD (manufacturer specific data). - * * Reference: * Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18 */ @@ -41,41 +68,85 @@ * 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 + * Major/Minor = 0000 / 0000 (We steal this for data) * Tx Power = C8 */ -const uint8_t beaconPayload[] = { - 0x4C, 0x00, - 0x02, - 0x15, - 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, + 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, - 0x00, 0x00, - 0xC8 + 0x00, 0x00, // Major + 0x00, 0x00, // Minor + 0xC8 // TXPower +, 0x99 // one spare byte! }; + +// 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=nrf_temp_read(); // always reads 0? (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) { - DEBUG("Initialising BTLE transport\n\r"); - ble.init(); - - ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); - ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, beaconPayload, sizeof(beaconPayload)); + char *devname="DDJ"; + DEBUG("Init\n\r"); + activity=errLED=0; + nrf_temp_init(); + errTry(ble.init(),1); - ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); - ble.setAdvertisingInterval(1600); /* 1s; in multiples of 0.625ms. */ - ble.startAdvertising(); +// 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(); - for (;;) { - ble.waitForEvent(); + 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 } - // An alternative to the above: - // - // DigitalOut mainloopLED(LED1); - // for (;;) { - // mainloopLED = !mainloopLED; - // ble.waitForEvent(); - // } }