example firmware for nRF51-Dongle to use with Opentrigger

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_Button by Bluetooth Low Energy

http://www.opentrigger.com

Committer:
0xf10
Date:
Mon Jul 18 14:55:35 2016 +0000
Revision:
20:7d2043754467
Parent:
19:3807de5c6a58
force deepsleep

Who changed what in which revision?

UserRevisionLine numberNew contents of line
0xf10 15:9f9f5d82743d 1 /* nRF51 mbed opentrigger example
0xf10 15:9f9f5d82743d 2 * Copyright (c) 2016 Florian Fida
0xf10 15:9f9f5d82743d 3 *
0xf10 15:9f9f5d82743d 4 * based on 'Demo for an Input Service'
0xf10 15:9f9f5d82743d 5 * https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_Button/
0xf10 15:9f9f5d82743d 6 *
rgrover1 0:28f095301cb2 7 *
rgrover1 0:28f095301cb2 8 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 0:28f095301cb2 9 * you may not use this file except in compliance with the License.
rgrover1 0:28f095301cb2 10 * You may obtain a copy of the License at
rgrover1 0:28f095301cb2 11 *
rgrover1 0:28f095301cb2 12 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 0:28f095301cb2 13 *
rgrover1 0:28f095301cb2 14 * Unless required by applicable law or agreed to in writing, software
rgrover1 0:28f095301cb2 15 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 0:28f095301cb2 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 0:28f095301cb2 17 * See the License for the specific language governing permissions and
rgrover1 0:28f095301cb2 18 * limitations under the License.
rgrover1 0:28f095301cb2 19 */
rgrover1 0:28f095301cb2 20
rgrover1 0:28f095301cb2 21 #include "mbed.h"
andresag 10:7943b5c1117a 22 #include "ble/BLE.h"
rgrover1 0:28f095301cb2 23
0xf10 16:7a9fde930f8a 24 DigitalOut led1(LED1); /* RED : Indicating a pressed button */
0xf10 16:7a9fde930f8a 25 DigitalOut led2(LED2); /* GREEN : Blinking to indicate that the device is running */
0xf10 16:7a9fde930f8a 26 DigitalOut led3(LED3); /* BLUE : Only on when advertising */
0xf10 15:9f9f5d82743d 27
0xf10 14:09f208b24460 28 InterruptIn button0(P0_15);
0xf10 14:09f208b24460 29 InterruptIn button1(P0_16);
0xf10 14:09f208b24460 30 InterruptIn button2(P0_17);
0xf10 14:09f208b24460 31 InterruptIn button3(P0_18);
0xf10 14:09f208b24460 32 InterruptIn button4(P0_19);
0xf10 14:09f208b24460 33 InterruptIn button5(P0_20);
rgrover1 0:28f095301cb2 34
0xf10 13:0f26a3fc1f32 35 const uint16_t MIN_ADVERT_INTERVAL = 50; /* msec */
0xf10 16:7a9fde930f8a 36 static uint8_t gpio_states[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; /* initial state is up */
0xf10 19:3807de5c6a58 37 static uint8_t event_id = 0;
rgrover1 0:28f095301cb2 38
rgrover1 9:0f6951db24f1 39 enum {
rgrover1 9:0f6951db24f1 40 RELEASED = 0,
rgrover1 9:0f6951db24f1 41 PRESSED,
rgrover1 9:0f6951db24f1 42 IDLE
rgrover1 9:0f6951db24f1 43 };
rgrover1 9:0f6951db24f1 44 static uint8_t buttonState = IDLE;
rgrover1 9:0f6951db24f1 45
0xf10 11:5b6d98e98127 46 void blinkLed(void){
0xf10 12:2cb903df877d 47 led2 = !led2;
0xf10 11:5b6d98e98127 48 }
0xf10 11:5b6d98e98127 49
0xf10 14:09f208b24460 50 void button0PressedCallback(void)
rgrover1 0:28f095301cb2 51 {
rgrover1 9:0f6951db24f1 52 /* Note that the buttonPressedCallback() executes in interrupt context, so it is safer to access
rgrover1 9:0f6951db24f1 53 * BLE device API from the main thread. */
rgrover1 9:0f6951db24f1 54 buttonState = PRESSED;
0xf10 16:7a9fde930f8a 55 gpio_states[0]=0x00;
0xf10 19:3807de5c6a58 56 event_id++;
rgrover1 0:28f095301cb2 57 }
rgrover1 0:28f095301cb2 58
0xf10 14:09f208b24460 59 void button0ReleasedCallback(void)
rgrover1 0:28f095301cb2 60 {
rgrover1 9:0f6951db24f1 61 /* Note that the buttonReleasedCallback() executes in interrupt context, so it is safer to access
rgrover1 9:0f6951db24f1 62 * BLE device API from the main thread. */
rgrover1 9:0f6951db24f1 63 buttonState = RELEASED;
0xf10 16:7a9fde930f8a 64 gpio_states[0]=0x01;
0xf10 19:3807de5c6a58 65 event_id++;
rgrover1 0:28f095301cb2 66 }
rgrover1 0:28f095301cb2 67
0xf10 14:09f208b24460 68
0xf10 16:7a9fde930f8a 69 // Callbacks for the other 5 Buttons
0xf10 19:3807de5c6a58 70 void button1PressedCallback(void) { buttonState = PRESSED; gpio_states[1]=0x00; event_id++; }
0xf10 19:3807de5c6a58 71 void button1ReleasedCallback(void){ buttonState = RELEASED; gpio_states[1]=0x01; event_id++; }
0xf10 19:3807de5c6a58 72 void button2PressedCallback(void) { buttonState = PRESSED; gpio_states[2]=0x00; event_id++; }
0xf10 19:3807de5c6a58 73 void button2ReleasedCallback(void){ buttonState = RELEASED; gpio_states[2]=0x01; event_id++; }
0xf10 19:3807de5c6a58 74 void button3PressedCallback(void) { buttonState = PRESSED; gpio_states[3]=0x00; event_id++; }
0xf10 19:3807de5c6a58 75 void button3ReleasedCallback(void){ buttonState = RELEASED; gpio_states[3]=0x01; event_id++; }
0xf10 19:3807de5c6a58 76 void button4PressedCallback(void) { buttonState = PRESSED; gpio_states[4]=0x00; event_id++; }
0xf10 19:3807de5c6a58 77 void button4ReleasedCallback(void){ buttonState = RELEASED; gpio_states[4]=0x01; event_id++; }
0xf10 19:3807de5c6a58 78 void button5PressedCallback(void) { buttonState = PRESSED; gpio_states[5]=0x00; event_id++; }
0xf10 19:3807de5c6a58 79 void button5ReleasedCallback(void){ buttonState = RELEASED; gpio_states[5]=0x01; event_id++; }
0xf10 16:7a9fde930f8a 80
0xf10 16:7a9fde930f8a 81 // Just in case
rgrover1 8:a7ba7aaba460 82 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
rgrover1 0:28f095301cb2 83 {
andresag 10:7943b5c1117a 84 BLE::Instance().gap().startAdvertising();
rgrover1 0:28f095301cb2 85 }
rgrover1 0:28f095301cb2 86
rgrover1 0:28f095301cb2 87 void periodicCallback(void)
rgrover1 0:28f095301cb2 88 {
0xf10 12:2cb903df877d 89 blinkLed();
rgrover1 0:28f095301cb2 90 }
rgrover1 0:28f095301cb2 91
andresag 10:7943b5c1117a 92 /**
andresag 10:7943b5c1117a 93 * This function is called when the ble initialization process has failled
andresag 10:7943b5c1117a 94 */
0xf10 14:09f208b24460 95 void onBleInitError(BLE &ble, ble_error_t bt_error)
andresag 10:7943b5c1117a 96 {
andresag 10:7943b5c1117a 97 /* Initialization error handling should go here */
0xf10 15:9f9f5d82743d 98
0xf10 15:9f9f5d82743d 99 printf("bt_error=%i\n\r",bt_error);
0xf10 13:0f26a3fc1f32 100 error("Panic!");
andresag 10:7943b5c1117a 101 }
andresag 10:7943b5c1117a 102
0xf10 16:7a9fde930f8a 103 bool gpioSet(void){
0xf10 16:7a9fde930f8a 104 return
0xf10 16:7a9fde930f8a 105 gpio_states[0] == 0x00 ||
0xf10 16:7a9fde930f8a 106 gpio_states[1] == 0x00 ||
0xf10 16:7a9fde930f8a 107 gpio_states[2] == 0x00 ||
0xf10 16:7a9fde930f8a 108 gpio_states[3] == 0x00 ||
0xf10 16:7a9fde930f8a 109 gpio_states[4] == 0x00 ||
0xf10 16:7a9fde930f8a 110 gpio_states[5] == 0x00
0xf10 16:7a9fde930f8a 111 ;
0xf10 16:7a9fde930f8a 112 }
0xf10 16:7a9fde930f8a 113
0xf10 16:7a9fde930f8a 114 void updateManufacturerData(void){
0xf10 16:7a9fde930f8a 115
0xf10 16:7a9fde930f8a 116 // disable interrupts while building the package to avoid a race condition
0xf10 16:7a9fde930f8a 117 __disable_irq();
0xf10 16:7a9fde930f8a 118
0xf10 14:09f208b24460 119 // http://tokencube.com/bluetooth-sensor.html
0xf10 13:0f26a3fc1f32 120 uint8_t data[] = {
0xf10 19:3807de5c6a58 121 0xee, 0xff, // Tokencube Manufacturer ID
0xf10 19:3807de5c6a58 122 0x04, // Token Module Version
0xf10 19:3807de5c6a58 123 0x01, // Firmware Version
0xf10 19:3807de5c6a58 124 0x11, // Page 1 of 1
0xf10 19:3807de5c6a58 125 0x07, gpioSet() ? 0x01 : 0x00, // PIR value (0x00 = off, 0x01 = on)
0xf10 19:3807de5c6a58 126 0x0F, event_id, // EventId (0x00 - 0xFF, every time a button gets pressed, the EventId changes)
0xf10 19:3807de5c6a58 127 gpio_states[0], gpio_states[1], // 6 GPIO Values (0x00 = down, 0x01 = up)
0xf10 19:3807de5c6a58 128 gpio_states[2], gpio_states[3],
0xf10 19:3807de5c6a58 129 gpio_states[4], gpio_states[5],
0xf10 13:0f26a3fc1f32 130 };
0xf10 16:7a9fde930f8a 131
0xf10 16:7a9fde930f8a 132 __enable_irq();
0xf10 11:5b6d98e98127 133 BLE::Instance().gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data, sizeof(data));
0xf10 11:5b6d98e98127 134 }
0xf10 11:5b6d98e98127 135
andresag 10:7943b5c1117a 136 /**
andresag 10:7943b5c1117a 137 * Callback triggered when the ble initialization process has finished
andresag 10:7943b5c1117a 138 */
andresag 10:7943b5c1117a 139 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
andresag 10:7943b5c1117a 140 {
andresag 10:7943b5c1117a 141 BLE& ble = params->ble;
andresag 10:7943b5c1117a 142 ble_error_t error = params->error;
andresag 10:7943b5c1117a 143
andresag 10:7943b5c1117a 144 if (error != BLE_ERROR_NONE) {
andresag 10:7943b5c1117a 145 /* In case of error, forward the error handling to onBleInitError */
andresag 10:7943b5c1117a 146 onBleInitError(ble, error);
andresag 10:7943b5c1117a 147 return;
andresag 10:7943b5c1117a 148 }
andresag 10:7943b5c1117a 149
andresag 10:7943b5c1117a 150 /* Ensure that it is the default instance of BLE */
andresag 10:7943b5c1117a 151 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
andresag 10:7943b5c1117a 152 return;
andresag 10:7943b5c1117a 153 }
0xf10 11:5b6d98e98127 154
0xf10 13:0f26a3fc1f32 155 uint8_t macAddress[6] = {0x00};
0xf10 13:0f26a3fc1f32 156 BLEProtocol::AddressType_t pubAddr = BLEProtocol::AddressType::PUBLIC;
0xf10 13:0f26a3fc1f32 157 ble.gap().getAddress(&pubAddr, macAddress);
0xf10 13:0f26a3fc1f32 158
0xf10 13:0f26a3fc1f32 159 /* change device MAC address */
0xf10 13:0f26a3fc1f32 160 //const uint8_t address1[] = {0xe7,0xAA,0xAA,0xAA,0xAA,0xAA};
0xf10 13:0f26a3fc1f32 161 //ble.gap().setAddress(pubAddr, address1);
andresag 10:7943b5c1117a 162
andresag 10:7943b5c1117a 163 ble.gap().onDisconnection(disconnectionCallback);
andresag 10:7943b5c1117a 164
andresag 10:7943b5c1117a 165 /* setup advertising */
andresag 10:7943b5c1117a 166 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
andresag 10:7943b5c1117a 167 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
0xf10 13:0f26a3fc1f32 168
0xf10 15:9f9f5d82743d 169 ble.gap().setAdvertisingInterval(MIN_ADVERT_INTERVAL);
0xf10 16:7a9fde930f8a 170 updateManufacturerData();
0xf10 15:9f9f5d82743d 171 error = ble.gap().startAdvertising();
0xf10 15:9f9f5d82743d 172 if (error != BLE_ERROR_NONE) onBleInitError(ble, error);
0xf10 13:0f26a3fc1f32 173
0xf10 13:0f26a3fc1f32 174 // Print Interval and MAC Address
0xf10 15:9f9f5d82743d 175 uint16_t minInterval = ble.gap().getMinAdvertisingInterval();
0xf10 15:9f9f5d82743d 176 printf("MinAdvertisingInterval = %i\n\r", minInterval);
0xf10 13:0f26a3fc1f32 177 printf("MAC Address = %02X:%02X:%02X:%02X:%02X:%02X\n\r", macAddress[5], macAddress[4], macAddress[3], macAddress[2], macAddress[1], macAddress[0]);
andresag 10:7943b5c1117a 178
andresag 10:7943b5c1117a 179 }
andresag 10:7943b5c1117a 180
rgrover1 0:28f095301cb2 181 int main(void)
0xf10 20:7d2043754467 182 {
0xf10 16:7a9fde930f8a 183 // Turn off all LED's
0xf10 15:9f9f5d82743d 184 led1 = !0; led2 = !0; led3 = !0;
0xf10 14:09f208b24460 185
0xf10 16:7a9fde930f8a 186 // Put all GPIO's in PullUp mode, so we do not need pullup resistors.
0xf10 16:7a9fde930f8a 187 button0.mode(PullUp);
0xf10 16:7a9fde930f8a 188 button1.mode(PullUp);
0xf10 16:7a9fde930f8a 189 button2.mode(PullUp);
0xf10 16:7a9fde930f8a 190 button3.mode(PullUp);
0xf10 16:7a9fde930f8a 191 button4.mode(PullUp);
0xf10 16:7a9fde930f8a 192 button5.mode(PullUp);
0xf10 16:7a9fde930f8a 193
0xf10 16:7a9fde930f8a 194 // Setup handler for all buttons
0xf10 14:09f208b24460 195 button0.fall(button0PressedCallback);
0xf10 14:09f208b24460 196 button0.rise(button0ReleasedCallback);
0xf10 14:09f208b24460 197 button1.fall(button1PressedCallback);
0xf10 14:09f208b24460 198 button1.rise(button1ReleasedCallback);
0xf10 14:09f208b24460 199 button2.fall(button2PressedCallback);
0xf10 14:09f208b24460 200 button2.rise(button2ReleasedCallback);
0xf10 14:09f208b24460 201 button3.fall(button3PressedCallback);
0xf10 14:09f208b24460 202 button3.rise(button3ReleasedCallback);
0xf10 14:09f208b24460 203 button4.fall(button4PressedCallback);
0xf10 14:09f208b24460 204 button4.rise(button4ReleasedCallback);
0xf10 14:09f208b24460 205 button5.fall(button5PressedCallback);
0xf10 14:09f208b24460 206 button5.rise(button5ReleasedCallback);
0xf10 16:7a9fde930f8a 207
0xf10 16:7a9fde930f8a 208 // This will make our green led blink
0xf10 20:7d2043754467 209 Ticker ticker;
0xf10 16:7a9fde930f8a 210 ticker.attach(periodicCallback, 1);
rgrover1 0:28f095301cb2 211
andresag 10:7943b5c1117a 212 BLE &ble = BLE::Instance();
andresag 10:7943b5c1117a 213 ble.init(bleInitComplete);
andresag 10:7943b5c1117a 214
0xf10 15:9f9f5d82743d 215 /* SpinWait for initialization to complete. This is necessary because the BLE object is used in the main loop below. */
andresag 10:7943b5c1117a 216 while (ble.hasInitialized() == false) { /* spin loop */ }
andresag 10:7943b5c1117a 217
0xf10 15:9f9f5d82743d 218 uint8_t cnt = 0;
rgrover1 0:28f095301cb2 219 while (true) {
0xf10 16:7a9fde930f8a 220
0xf10 16:7a9fde930f8a 221 // we only care about situations where a button was pressed
andresag 10:7943b5c1117a 222 if (buttonState != IDLE) {
0xf10 16:7a9fde930f8a 223 if(buttonState == PRESSED) led1=!1;
0xf10 16:7a9fde930f8a 224 if(buttonState == RELEASED) led1=!0;
0xf10 20:7d2043754467 225 ticker.attach(periodicCallback, 1);
0xf10 16:7a9fde930f8a 226 updateManufacturerData();
0xf10 15:9f9f5d82743d 227 cnt = 0;
rgrover1 9:0f6951db24f1 228 buttonState = IDLE;
rgrover1 9:0f6951db24f1 229 }
rgrover1 9:0f6951db24f1 230
0xf10 18:2b328834f64f 231
0xf10 18:2b328834f64f 232 // start advertising
0xf10 15:9f9f5d82743d 233 if(cnt < 1){
0xf10 15:9f9f5d82743d 234 ble.gap().startAdvertising();
0xf10 15:9f9f5d82743d 235 led3 = !1;
0xf10 17:33d38b30e640 236 }else if(cnt == 1){
0xf10 17:33d38b30e640 237 updateManufacturerData();
0xf10 18:2b328834f64f 238 }
0xf10 18:2b328834f64f 239
0xf10 18:2b328834f64f 240 // stop advertising after 3 cycles
0xf10 18:2b328834f64f 241 if(cnt > 3){
0xf10 15:9f9f5d82743d 242 ble.gap().stopAdvertising();
0xf10 15:9f9f5d82743d 243 led3 = !0;
0xf10 20:7d2043754467 244 led2 = !0;
0xf10 20:7d2043754467 245 ticker.detach();
0xf10 20:7d2043754467 246 deepsleep();
0xf10 15:9f9f5d82743d 247 }else{
0xf10 16:7a9fde930f8a 248 if(!gpioSet()) cnt++;
0xf10 15:9f9f5d82743d 249 }
0xf10 15:9f9f5d82743d 250
rgrover1 0:28f095301cb2 251 ble.waitForEvent();
0xf10 15:9f9f5d82743d 252 //printf("cnt=%i\n\r",cnt);
rgrover1 0:28f095301cb2 253 }
rgrover1 0:28f095301cb2 254 }