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.
main.cpp@45:e64d1e920cd1, 2014-10-01 (annotated)
- Committer:
- wd5gnr
- Date:
- Wed Oct 01 22:06:43 2014 +0000
- Revision:
- 45:e64d1e920cd1
- Parent:
- 44:6a5d976d6e61
Replace the mbed-src library with mbed
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ktownsend | 0:7613d21e5974 | 1 | /* mbed Microcontroller Library |
ktownsend | 0:7613d21e5974 | 2 | * Copyright (c) 2006-2013 ARM Limited |
ktownsend | 0:7613d21e5974 | 3 | * |
ktownsend | 0:7613d21e5974 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
ktownsend | 0:7613d21e5974 | 5 | * you may not use this file except in compliance with the License. |
ktownsend | 0:7613d21e5974 | 6 | * You may obtain a copy of the License at |
ktownsend | 0:7613d21e5974 | 7 | * |
ktownsend | 0:7613d21e5974 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
ktownsend | 0:7613d21e5974 | 9 | * |
ktownsend | 0:7613d21e5974 | 10 | * Unless required by applicable law or agreed to in writing, software |
ktownsend | 0:7613d21e5974 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
ktownsend | 0:7613d21e5974 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
ktownsend | 0:7613d21e5974 | 13 | * See the License for the specific language governing permissions and |
ktownsend | 0:7613d21e5974 | 14 | * limitations under the License. |
ktownsend | 0:7613d21e5974 | 15 | */ |
ktownsend | 0:7613d21e5974 | 16 | |
ktownsend | 0:7613d21e5974 | 17 | #include "mbed.h" |
Rohit Grover |
32:7b7093b653a8 | 18 | #include "BLEDevice.h" |
wd5gnr | 44:6a5d976d6e61 | 19 | #include "nrf_temp.h" |
wd5gnr | 44:6a5d976d6e61 | 20 | |
wd5gnr | 44:6a5d976d6e61 | 21 | #define ADVTIME 1000 // advertise time in ms |
wd5gnr | 44:6a5d976d6e61 | 22 | #define UPDTIME 2000 // update time in ms |
ktownsend | 0:7613d21e5974 | 23 | |
Rohit Grover |
32:7b7093b653a8 | 24 | BLEDevice ble; |
wd5gnr | 44:6a5d976d6e61 | 25 | Timer msclock; |
wd5gnr | 44:6a5d976d6e61 | 26 | DigitalOut activity(LED1); // blinks to show activity |
wd5gnr | 44:6a5d976d6e61 | 27 | DigitalOut errLED(LED2); // comes on if error occurs |
wd5gnr | 44:6a5d976d6e61 | 28 | DigitalIn btn1(BUTTON1); |
wd5gnr | 44:6a5d976d6e61 | 29 | DigitalIn btn2(BUTTON2); |
Rohit Grover |
31:93e50a3c3dc6 | 30 | |
Rohit Grover |
31:93e50a3c3dc6 | 31 | #define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console; |
Rohit Grover |
31:93e50a3c3dc6 | 32 | * it will have an impact on code-size and power consumption. */ |
ktownsend | 0:7613d21e5974 | 33 | |
Rohit Grover |
31:93e50a3c3dc6 | 34 | #if NEED_CONSOLE_OUTPUT |
Rohit Grover |
31:93e50a3c3dc6 | 35 | Serial pc(USBTX, USBRX); |
Rohit Grover |
31:93e50a3c3dc6 | 36 | #define DEBUG(...) { pc.printf(__VA_ARGS__); } |
Rohit Grover |
31:93e50a3c3dc6 | 37 | #else |
Rohit Grover |
31:93e50a3c3dc6 | 38 | #define DEBUG(...) /* nothing */ |
Rohit Grover |
31:93e50a3c3dc6 | 39 | #endif /* #if NEED_CONSOLE_OUTPUT */ |
ktownsend | 0:7613d21e5974 | 40 | |
wd5gnr | 44:6a5d976d6e61 | 41 | // Try a BLE function and if failed, light LED 2 and halt |
wd5gnr | 44:6a5d976d6e61 | 42 | // but don't catch fire.... |
wd5gnr | 44:6a5d976d6e61 | 43 | |
wd5gnr | 44:6a5d976d6e61 | 44 | void errTry(ble_error_t fn,int n=1) |
wd5gnr | 44:6a5d976d6e61 | 45 | { |
wd5gnr | 44:6a5d976d6e61 | 46 | if (fn) |
wd5gnr | 44:6a5d976d6e61 | 47 | { |
wd5gnr | 44:6a5d976d6e61 | 48 | while (1) |
wd5gnr | 44:6a5d976d6e61 | 49 | { |
wd5gnr | 44:6a5d976d6e61 | 50 | for (int i=0;i<n*2;i++) |
wd5gnr | 44:6a5d976d6e61 | 51 | { |
wd5gnr | 44:6a5d976d6e61 | 52 | wait_ms(250); |
wd5gnr | 44:6a5d976d6e61 | 53 | errLED=!errLED; |
wd5gnr | 44:6a5d976d6e61 | 54 | } |
wd5gnr | 44:6a5d976d6e61 | 55 | wait_ms(2000); |
wd5gnr | 44:6a5d976d6e61 | 56 | } |
wd5gnr | 44:6a5d976d6e61 | 57 | } |
wd5gnr | 44:6a5d976d6e61 | 58 | } |
wd5gnr | 44:6a5d976d6e61 | 59 | |
wd5gnr | 44:6a5d976d6e61 | 60 | |
wd5gnr | 44:6a5d976d6e61 | 61 | |
Rohit Grover |
10:391c1acf4b9d | 62 | /* |
Rohit Grover |
10:391c1acf4b9d | 63 | * Reference: |
Rohit Grover |
10:391c1acf4b9d | 64 | * Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18 |
Rohit Grover |
10:391c1acf4b9d | 65 | */ |
ktownsend | 0:7613d21e5974 | 66 | |
Rohit Grover |
14:dfdf0c8b1c09 | 67 | /* |
Rohit Grover |
15:4e1b36b73213 | 68 | * The Beacon payload (encapsulated within the MSD advertising data structure) |
Rohit Grover |
15:4e1b36b73213 | 69 | * has the following composition: |
Rohit Grover |
10:391c1acf4b9d | 70 | * 128-Bit UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 |
wd5gnr | 44:6a5d976d6e61 | 71 | * Major/Minor = 0000 / 0000 (We steal this for data) |
Rohit Grover |
10:391c1acf4b9d | 72 | * Tx Power = C8 |
Rohit Grover |
10:391c1acf4b9d | 73 | */ |
wd5gnr | 44:6a5d976d6e61 | 74 | uint8_t beaconPayload[] = { |
wd5gnr | 44:6a5d976d6e61 | 75 | 0x4C, 0x00, // vendor ID |
wd5gnr | 44:6a5d976d6e61 | 76 | 0x02, // packet type (2) |
wd5gnr | 44:6a5d976d6e61 | 77 | 0x15, // length |
wd5gnr | 44:6a5d976d6e61 | 78 | 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, // UUID |
Rohit Grover |
10:391c1acf4b9d | 79 | 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61, |
wd5gnr | 44:6a5d976d6e61 | 80 | 0x00, 0x00, // Major |
wd5gnr | 44:6a5d976d6e61 | 81 | 0x00, 0x00, // Minor |
wd5gnr | 44:6a5d976d6e61 | 82 | 0xC8 // TXPower |
wd5gnr | 44:6a5d976d6e61 | 83 | , 0x99 // one spare byte! |
Rohit Grover |
10:391c1acf4b9d | 84 | }; |
Rohit Grover |
10:391c1acf4b9d | 85 | |
wd5gnr | 44:6a5d976d6e61 | 86 | |
wd5gnr | 45:e64d1e920cd1 | 87 | // Read temperature |
wd5gnr | 45:e64d1e920cd1 | 88 | int temp_read() |
wd5gnr | 45:e64d1e920cd1 | 89 | { |
wd5gnr | 45:e64d1e920cd1 | 90 | int t; |
wd5gnr | 45:e64d1e920cd1 | 91 | NRF_TEMP->TASKS_START=1; |
wd5gnr | 45:e64d1e920cd1 | 92 | while (NRF_TEMP->EVENTS_DATARDY==0); |
wd5gnr | 45:e64d1e920cd1 | 93 | NRF_TEMP->EVENTS_DATARDY=0; |
wd5gnr | 45:e64d1e920cd1 | 94 | t=nrf_temp_read(); |
wd5gnr | 45:e64d1e920cd1 | 95 | NRF_TEMP->TASKS_STOP=1; |
wd5gnr | 45:e64d1e920cd1 | 96 | return t; |
wd5gnr | 45:e64d1e920cd1 | 97 | } |
wd5gnr | 45:e64d1e920cd1 | 98 | |
wd5gnr | 45:e64d1e920cd1 | 99 | |
wd5gnr | 44:6a5d976d6e61 | 100 | // Grab the sensors and put 55AA in major |
wd5gnr | 44:6a5d976d6e61 | 101 | // Put minor data for temperature reading |
wd5gnr | 44:6a5d976d6e61 | 102 | // (which returns 0 on this board) |
wd5gnr | 44:6a5d976d6e61 | 103 | // as well as switches |
wd5gnr | 44:6a5d976d6e61 | 104 | void readSensors() |
wd5gnr | 44:6a5d976d6e61 | 105 | { |
wd5gnr | 44:6a5d976d6e61 | 106 | int temp; |
wd5gnr | 44:6a5d976d6e61 | 107 | beaconPayload[20]=0x55; |
wd5gnr | 44:6a5d976d6e61 | 108 | beaconPayload[21]=0xAA; |
wd5gnr | 45:e64d1e920cd1 | 109 | temp=temp_read(); // (should read 0-1023) |
wd5gnr | 44:6a5d976d6e61 | 110 | if (!btn1) temp|=0x8000; // switches are inverted sense (0=pressed) |
wd5gnr | 44:6a5d976d6e61 | 111 | if (!btn2) temp|=0x4000; |
wd5gnr | 44:6a5d976d6e61 | 112 | |
wd5gnr | 44:6a5d976d6e61 | 113 | beaconPayload[22]=temp>>8; |
wd5gnr | 44:6a5d976d6e61 | 114 | beaconPayload[23]=temp&0xFF; |
wd5gnr | 44:6a5d976d6e61 | 115 | |
wd5gnr | 44:6a5d976d6e61 | 116 | } |
wd5gnr | 44:6a5d976d6e61 | 117 | |
wd5gnr | 44:6a5d976d6e61 | 118 | // Build up advertising packet including sensors |
wd5gnr | 44:6a5d976d6e61 | 119 | void setupBLE() |
wd5gnr | 44:6a5d976d6e61 | 120 | { |
wd5gnr | 44:6a5d976d6e61 | 121 | ble.clearAdvertisingPayload(); |
wd5gnr | 44:6a5d976d6e61 | 122 | readSensors(); |
wd5gnr | 44:6a5d976d6e61 | 123 | errTry(ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE),5); |
wd5gnr | 44:6a5d976d6e61 | 124 | errTry(ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, beaconPayload, sizeof(beaconPayload)),6); |
wd5gnr | 44:6a5d976d6e61 | 125 | |
wd5gnr | 44:6a5d976d6e61 | 126 | } |
wd5gnr | 44:6a5d976d6e61 | 127 | |
wd5gnr | 44:6a5d976d6e61 | 128 | |
wd5gnr | 44:6a5d976d6e61 | 129 | |
wd5gnr | 44:6a5d976d6e61 | 130 | |
wd5gnr | 44:6a5d976d6e61 | 131 | |
ktownsend | 0:7613d21e5974 | 132 | int main(void) |
ktownsend | 0:7613d21e5974 | 133 | { |
wd5gnr | 44:6a5d976d6e61 | 134 | char *devname="DDJ"; |
wd5gnr | 44:6a5d976d6e61 | 135 | DEBUG("Init\n\r"); |
wd5gnr | 44:6a5d976d6e61 | 136 | activity=errLED=0; |
wd5gnr | 44:6a5d976d6e61 | 137 | nrf_temp_init(); |
wd5gnr | 44:6a5d976d6e61 | 138 | errTry(ble.init(),1); |
wd5gnr | 45:e64d1e920cd1 | 139 | NRF_TEMP->TASKS_START=1; |
ktownsend | 0:7613d21e5974 | 140 | |
wd5gnr | 44:6a5d976d6e61 | 141 | // Build advert |
wd5gnr | 44:6a5d976d6e61 | 142 | setupBLE(); |
wd5gnr | 44:6a5d976d6e61 | 143 | |
wd5gnr | 44:6a5d976d6e61 | 144 | // Set up general parameters |
wd5gnr | 44:6a5d976d6e61 | 145 | errTry(ble.setDeviceName((uint8_t *)devname),2); |
wd5gnr | 44:6a5d976d6e61 | 146 | #if 0 |
wd5gnr | 44:6a5d976d6e61 | 147 | errTry(ble.setAdvertisingType(GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)); // this will give you one "ping" and no repeats |
wd5gnr | 44:6a5d976d6e61 | 148 | #else |
wd5gnr | 44:6a5d976d6e61 | 149 | ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); // This will give you a ping every interval |
wd5gnr | 44:6a5d976d6e61 | 150 | #endif |
wd5gnr | 44:6a5d976d6e61 | 151 | |
wd5gnr | 44:6a5d976d6e61 | 152 | ble.setAdvertisingInterval((16*ADVTIME)/10); /* 1s; in multiples of 0.625ms. is 1600 */ |
wd5gnr | 44:6a5d976d6e61 | 153 | |
wd5gnr | 44:6a5d976d6e61 | 154 | // start timer for sensor reading |
wd5gnr | 44:6a5d976d6e61 | 155 | msclock.start(); |
ktownsend | 0:7613d21e5974 | 156 | |
wd5gnr | 44:6a5d976d6e61 | 157 | while (true) { |
wd5gnr | 44:6a5d976d6e61 | 158 | msclock.reset(); |
wd5gnr | 44:6a5d976d6e61 | 159 | errTry(ble.startAdvertising(),3); // start advert |
wd5gnr | 44:6a5d976d6e61 | 160 | wait_ms(UPDTIME); // wait awhile |
wd5gnr | 44:6a5d976d6e61 | 161 | activity=!activity; // blink led |
wd5gnr | 44:6a5d976d6e61 | 162 | errTry(ble.stopAdvertising(),4); // stop advert |
wd5gnr | 44:6a5d976d6e61 | 163 | setupBLE(); // set up with new data |
ktownsend | 0:7613d21e5974 | 164 | } |
Rohit Grover |
31:93e50a3c3dc6 | 165 | |
Rohit Grover |
10:391c1acf4b9d | 166 | } |