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:
Tue Jun 14 14:02:15 2016 +0000
Revision:
15:9f9f5d82743d
Parent:
14:09f208b24460
Child:
16:7a9fde930f8a
disable advertising when idle

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
rgrover1 0:28f095301cb2 24 DigitalOut led1(LED1);
0xf10 12:2cb903df877d 25 DigitalOut led2(LED2);
0xf10 15:9f9f5d82743d 26 DigitalOut led3(LED3);
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 15:9f9f5d82743d 36 const uint16_t MAX_ADVERT_INTERVAL = 5000; /* msec */
0xf10 14:09f208b24460 37 static uint8_t gpio_states[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
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 14:09f208b24460 55 gpio_states[0]=0x01;
rgrover1 0:28f095301cb2 56 }
rgrover1 0:28f095301cb2 57
0xf10 14:09f208b24460 58 void button0ReleasedCallback(void)
rgrover1 0:28f095301cb2 59 {
rgrover1 9:0f6951db24f1 60 /* Note that the buttonReleasedCallback() executes in interrupt context, so it is safer to access
rgrover1 9:0f6951db24f1 61 * BLE device API from the main thread. */
rgrover1 9:0f6951db24f1 62 buttonState = RELEASED;
0xf10 14:09f208b24460 63 gpio_states[0]=0x00;
rgrover1 0:28f095301cb2 64 }
rgrover1 0:28f095301cb2 65
0xf10 14:09f208b24460 66 void button1PressedCallback(void) { buttonState = PRESSED; gpio_states[1]=0x01; }
0xf10 14:09f208b24460 67 void button1ReleasedCallback(void){ buttonState = RELEASED; gpio_states[1]=0x00; }
0xf10 14:09f208b24460 68 void button2PressedCallback(void) { buttonState = PRESSED; gpio_states[2]=0x01; }
0xf10 14:09f208b24460 69 void button2ReleasedCallback(void){ buttonState = RELEASED; gpio_states[2]=0x00; }
0xf10 14:09f208b24460 70 void button3PressedCallback(void) { buttonState = PRESSED; gpio_states[3]=0x01; }
0xf10 14:09f208b24460 71 void button3ReleasedCallback(void){ buttonState = RELEASED; gpio_states[3]=0x00; }
0xf10 14:09f208b24460 72 void button4PressedCallback(void) { buttonState = PRESSED; gpio_states[4]=0x01; }
0xf10 14:09f208b24460 73 void button4ReleasedCallback(void){ buttonState = RELEASED; gpio_states[4]=0x00; }
0xf10 14:09f208b24460 74 void button5PressedCallback(void) { buttonState = PRESSED; gpio_states[5]=0x01; }
0xf10 14:09f208b24460 75 void button5ReleasedCallback(void){ buttonState = RELEASED; gpio_states[5]=0x00; }
0xf10 14:09f208b24460 76
rgrover1 8:a7ba7aaba460 77 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
rgrover1 0:28f095301cb2 78 {
andresag 10:7943b5c1117a 79 BLE::Instance().gap().startAdvertising();
rgrover1 0:28f095301cb2 80 }
rgrover1 0:28f095301cb2 81
rgrover1 0:28f095301cb2 82 void periodicCallback(void)
rgrover1 0:28f095301cb2 83 {
0xf10 12:2cb903df877d 84 blinkLed();
rgrover1 0:28f095301cb2 85 }
rgrover1 0:28f095301cb2 86
andresag 10:7943b5c1117a 87 /**
andresag 10:7943b5c1117a 88 * This function is called when the ble initialization process has failled
andresag 10:7943b5c1117a 89 */
0xf10 14:09f208b24460 90 void onBleInitError(BLE &ble, ble_error_t bt_error)
andresag 10:7943b5c1117a 91 {
andresag 10:7943b5c1117a 92 /* Initialization error handling should go here */
0xf10 15:9f9f5d82743d 93
0xf10 15:9f9f5d82743d 94 printf("bt_error=%i\n\r",bt_error);
0xf10 13:0f26a3fc1f32 95 error("Panic!");
andresag 10:7943b5c1117a 96 }
andresag 10:7943b5c1117a 97
0xf10 11:5b6d98e98127 98 void setPir(uint8_t pir){
0xf10 14:09f208b24460 99 // http://tokencube.com/bluetooth-sensor.html
0xf10 13:0f26a3fc1f32 100 uint8_t data[] = {
0xf10 13:0f26a3fc1f32 101 0xee, 0xff, // Tokencube Manufacturer ID
0xf10 13:0f26a3fc1f32 102 0x04, // Token Module Version
0xf10 13:0f26a3fc1f32 103 0x01, // Firmware Version
0xf10 13:0f26a3fc1f32 104 0x11, // Page 1 of 1
0xf10 14:09f208b24460 105 0x07, pir, // pir value
0xf10 14:09f208b24460 106 // custom data - state of all 6 gpio's
0xf10 14:09f208b24460 107 0x0F, gpio_states[0], gpio_states[1], gpio_states[2], gpio_states[3], gpio_states[4], gpio_states[5]
0xf10 13:0f26a3fc1f32 108 };
0xf10 11:5b6d98e98127 109 BLE::Instance().gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data, sizeof(data));
0xf10 11:5b6d98e98127 110 }
0xf10 11:5b6d98e98127 111
andresag 10:7943b5c1117a 112 /**
andresag 10:7943b5c1117a 113 * Callback triggered when the ble initialization process has finished
andresag 10:7943b5c1117a 114 */
andresag 10:7943b5c1117a 115 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
andresag 10:7943b5c1117a 116 {
andresag 10:7943b5c1117a 117 BLE& ble = params->ble;
andresag 10:7943b5c1117a 118 ble_error_t error = params->error;
andresag 10:7943b5c1117a 119
andresag 10:7943b5c1117a 120 if (error != BLE_ERROR_NONE) {
andresag 10:7943b5c1117a 121 /* In case of error, forward the error handling to onBleInitError */
andresag 10:7943b5c1117a 122 onBleInitError(ble, error);
andresag 10:7943b5c1117a 123 return;
andresag 10:7943b5c1117a 124 }
andresag 10:7943b5c1117a 125
andresag 10:7943b5c1117a 126 /* Ensure that it is the default instance of BLE */
andresag 10:7943b5c1117a 127 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
andresag 10:7943b5c1117a 128 return;
andresag 10:7943b5c1117a 129 }
0xf10 11:5b6d98e98127 130
0xf10 13:0f26a3fc1f32 131 uint8_t macAddress[6] = {0x00};
0xf10 13:0f26a3fc1f32 132 BLEProtocol::AddressType_t pubAddr = BLEProtocol::AddressType::PUBLIC;
0xf10 13:0f26a3fc1f32 133 ble.gap().getAddress(&pubAddr, macAddress);
0xf10 13:0f26a3fc1f32 134
0xf10 13:0f26a3fc1f32 135 /* change device MAC address */
0xf10 13:0f26a3fc1f32 136 //const uint8_t address1[] = {0xe7,0xAA,0xAA,0xAA,0xAA,0xAA};
0xf10 13:0f26a3fc1f32 137 //ble.gap().setAddress(pubAddr, address1);
andresag 10:7943b5c1117a 138
andresag 10:7943b5c1117a 139 ble.gap().onDisconnection(disconnectionCallback);
andresag 10:7943b5c1117a 140
andresag 10:7943b5c1117a 141 /* setup advertising */
andresag 10:7943b5c1117a 142 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
andresag 10:7943b5c1117a 143 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
0xf10 13:0f26a3fc1f32 144
0xf10 15:9f9f5d82743d 145 ble.gap().setAdvertisingInterval(MIN_ADVERT_INTERVAL);
0xf10 11:5b6d98e98127 146 setPir(0x00);
0xf10 15:9f9f5d82743d 147 error = ble.gap().startAdvertising();
0xf10 15:9f9f5d82743d 148 if (error != BLE_ERROR_NONE) onBleInitError(ble, error);
0xf10 13:0f26a3fc1f32 149
0xf10 13:0f26a3fc1f32 150 // Print Interval and MAC Address
0xf10 15:9f9f5d82743d 151 uint16_t minInterval = ble.gap().getMinAdvertisingInterval();
0xf10 15:9f9f5d82743d 152 printf("MinAdvertisingInterval = %i\n\r", minInterval);
0xf10 13:0f26a3fc1f32 153 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 154
andresag 10:7943b5c1117a 155 }
andresag 10:7943b5c1117a 156
rgrover1 0:28f095301cb2 157 int main(void)
rgrover1 0:28f095301cb2 158 {
rgrover1 0:28f095301cb2 159 Ticker ticker;
0xf10 14:09f208b24460 160
0xf10 15:9f9f5d82743d 161 led1 = !0; led2 = !0; led3 = !0;
0xf10 14:09f208b24460 162
rgrover1 0:28f095301cb2 163 ticker.attach(periodicCallback, 1);
0xf10 14:09f208b24460 164 button0.fall(button0PressedCallback);
0xf10 14:09f208b24460 165 button0.rise(button0ReleasedCallback);
0xf10 14:09f208b24460 166 button1.fall(button1PressedCallback);
0xf10 14:09f208b24460 167 button1.rise(button1ReleasedCallback);
0xf10 14:09f208b24460 168 button2.fall(button2PressedCallback);
0xf10 14:09f208b24460 169 button2.rise(button2ReleasedCallback);
0xf10 14:09f208b24460 170 button3.fall(button3PressedCallback);
0xf10 14:09f208b24460 171 button3.rise(button3ReleasedCallback);
0xf10 14:09f208b24460 172 button4.fall(button4PressedCallback);
0xf10 14:09f208b24460 173 button4.rise(button4ReleasedCallback);
0xf10 14:09f208b24460 174 button5.fall(button5PressedCallback);
0xf10 14:09f208b24460 175 button5.rise(button5ReleasedCallback);
rgrover1 0:28f095301cb2 176
andresag 10:7943b5c1117a 177 BLE &ble = BLE::Instance();
andresag 10:7943b5c1117a 178 ble.init(bleInitComplete);
andresag 10:7943b5c1117a 179
0xf10 15:9f9f5d82743d 180 /* SpinWait for initialization to complete. This is necessary because the BLE object is used in the main loop below. */
andresag 10:7943b5c1117a 181 while (ble.hasInitialized() == false) { /* spin loop */ }
andresag 10:7943b5c1117a 182
0xf10 15:9f9f5d82743d 183 uint8_t cnt = 0;
rgrover1 0:28f095301cb2 184 while (true) {
andresag 10:7943b5c1117a 185 if (buttonState != IDLE) {
0xf10 15:9f9f5d82743d 186 if(buttonState == PRESSED) {
0xf10 15:9f9f5d82743d 187 led1=!1;
0xf10 15:9f9f5d82743d 188 setPir(0x01);
0xf10 15:9f9f5d82743d 189 }
0xf10 15:9f9f5d82743d 190 if(buttonState == RELEASED) {
0xf10 15:9f9f5d82743d 191 led1=!0;
0xf10 15:9f9f5d82743d 192 setPir(0x00);
0xf10 15:9f9f5d82743d 193 }
0xf10 15:9f9f5d82743d 194 cnt = 0;
rgrover1 9:0f6951db24f1 195 buttonState = IDLE;
rgrover1 9:0f6951db24f1 196 }
rgrover1 9:0f6951db24f1 197
0xf10 15:9f9f5d82743d 198
0xf10 15:9f9f5d82743d 199 if(cnt < 1){
0xf10 15:9f9f5d82743d 200 ble.gap().startAdvertising();
0xf10 15:9f9f5d82743d 201 led3 = !1;
0xf10 15:9f9f5d82743d 202 }
0xf10 15:9f9f5d82743d 203 if(cnt > 5){
0xf10 15:9f9f5d82743d 204 ble.gap().stopAdvertising();
0xf10 15:9f9f5d82743d 205 led3 = !0;
0xf10 15:9f9f5d82743d 206 }else{
0xf10 15:9f9f5d82743d 207 cnt++;
0xf10 15:9f9f5d82743d 208 }
0xf10 15:9f9f5d82743d 209
rgrover1 0:28f095301cb2 210 ble.waitForEvent();
0xf10 15:9f9f5d82743d 211 //printf("cnt=%i\n\r",cnt);
rgrover1 0:28f095301cb2 212 }
rgrover1 0:28f095301cb2 213 }