The firmware of the Grove Node

Dependencies:   BLE_API color_pixels mbed-src-nrf51822 nRF51822

Fork of BLE_LoopbackUART by Bluetooth Low Energy

Committer:
yihui
Date:
Thu Nov 06 02:22:01 2014 +0000
Revision:
9:84cb66d0375d
Parent:
6:e0fc9072e853
Child:
10:f34ff4e47741
Grove Node initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 0:e910d9bb040f 1 /* mbed Microcontroller Library
yihui 0:e910d9bb040f 2 * Copyright (c) 2006-2013 ARM Limited
yihui 0:e910d9bb040f 3 *
yihui 0:e910d9bb040f 4 * Licensed under the Apache License, Version 2.0 (the "License");
yihui 0:e910d9bb040f 5 * you may not use this file except in compliance with the License.
yihui 0:e910d9bb040f 6 * You may obtain a copy of the License at
yihui 0:e910d9bb040f 7 *
yihui 0:e910d9bb040f 8 * http://www.apache.org/licenses/LICENSE-2.0
yihui 0:e910d9bb040f 9 *
yihui 0:e910d9bb040f 10 * Unless required by applicable law or agreed to in writing, software
yihui 0:e910d9bb040f 11 * distributed under the License is distributed on an "AS IS" BASIS,
yihui 0:e910d9bb040f 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
yihui 0:e910d9bb040f 13 * See the License for the specific language governing permissions and
yihui 0:e910d9bb040f 14 * limitations under the License.
yihui 0:e910d9bb040f 15 */
yihui 0:e910d9bb040f 16
yihui 0:e910d9bb040f 17 #include "mbed.h"
Rohit Grover 2:e060367b9024 18 #include "BLEDevice.h"
yihui 9:84cb66d0375d 19 #include "DFUService.h"
rgrover1 6:e0fc9072e853 20 #include "UARTService.h"
yihui 9:84cb66d0375d 21 #include "nrf_delay.h"
yihui 9:84cb66d0375d 22 #include "battery.h"
yihui 0:e910d9bb040f 23
yihui 9:84cb66d0375d 24 #define DEBUG 0
yihui 9:84cb66d0375d 25
yihui 9:84cb66d0375d 26 #if DEBUG // for Arch BLE
yihui 9:84cb66d0375d 27 #define LOG(...) { printf(__VA_ARGS__); }
yihui 9:84cb66d0375d 28 #define BUTTON_DOWN 1
yihui 9:84cb66d0375d 29 #define LED_ON 1
yihui 9:84cb66d0375d 30 #define LED_OFF 0
yihui 0:e910d9bb040f 31
yihui 9:84cb66d0375d 32 DigitalOut blue(p30);
yihui 9:84cb66d0375d 33 DigitalOut green(p17);
yihui 9:84cb66d0375d 34 InterruptIn button(p5);
yihui 9:84cb66d0375d 35 #else // for Grove Node BLE
yihui 9:84cb66d0375d 36 #define LOG(...)
yihui 9:84cb66d0375d 37 #define BUTTON_DOWN 0
yihui 9:84cb66d0375d 38 #define LED_ON 0
yihui 9:84cb66d0375d 39 #define LED_OFF 1
yihui 9:84cb66d0375d 40
yihui 9:84cb66d0375d 41 DigitalOut blue(p18);
yihui 9:84cb66d0375d 42 DigitalOut green(p17);
yihui 9:84cb66d0375d 43 InterruptIn button(p30);
yihui 9:84cb66d0375d 44 #endif
yihui 9:84cb66d0375d 45
yihui 9:84cb66d0375d 46 Battery battery(p5);
yihui 0:e910d9bb040f 47
Rohit Grover 2:e060367b9024 48 BLEDevice ble;
yihui 9:84cb66d0375d 49 UARTService *uartServicePtr;
yihui 9:84cb66d0375d 50 Ticker ticker;
yihui 9:84cb66d0375d 51
yihui 9:84cb66d0375d 52 volatile bool button_event = false;
yihui 9:84cb66d0375d 53
yihui 9:84cb66d0375d 54 const int MAX_ARGS = 8;
yihui 9:84cb66d0375d 55 char *argv[MAX_ARGS];
yihui 0:e910d9bb040f 56
yihui 9:84cb66d0375d 57 static const uint8_t SIZEOF_TX_RX_BUFFER = 32;
yihui 9:84cb66d0375d 58 uint8_t rxPayload[SIZEOF_TX_RX_BUFFER] = {0,};
yihui 9:84cb66d0375d 59
yihui 9:84cb66d0375d 60 extern "C" void power_on();
yihui 9:84cb66d0375d 61 extern "C" void power_off();
yihui 9:84cb66d0375d 62
yihui 9:84cb66d0375d 63 extern void node_init();
yihui 9:84cb66d0375d 64 extern void node_tick();
yihui 9:84cb66d0375d 65 extern void node_parse(int argc, char *argv[]);
yihui 9:84cb66d0375d 66
yihui 9:84cb66d0375d 67 int button_detect();
yihui 0:e910d9bb040f 68
rgrover1 5:4bc41267a03a 69 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
yihui 0:e910d9bb040f 70 {
yihui 9:84cb66d0375d 71 LOG("Disconnected!\n");
yihui 9:84cb66d0375d 72 LOG("Restarting the advertising process\n");
Rohit Grover 2:e060367b9024 73 ble.startAdvertising();
Rohit Grover 2:e060367b9024 74 }
yihui 0:e910d9bb040f 75
rgrover1 6:e0fc9072e853 76 void onDataWritten(const GattCharacteristicWriteCBParams *params)
yihui 0:e910d9bb040f 77 {
rgrover1 6:e0fc9072e853 78 if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
rgrover1 5:4bc41267a03a 79 uint16_t bytesRead = params->len;
yihui 9:84cb66d0375d 80 LOG("received %u bytes\n\r", bytesRead);
yihui 9:84cb66d0375d 81 if (bytesRead < sizeof(rxPayload)) {
yihui 9:84cb66d0375d 82 memcpy(rxPayload, params->data, bytesRead);
yihui 9:84cb66d0375d 83 rxPayload[bytesRead] = '\0';
yihui 9:84cb66d0375d 84 }
yihui 9:84cb66d0375d 85
yihui 9:84cb66d0375d 86 LOG("%s\n", (char *)rxPayload);
yihui 9:84cb66d0375d 87
yihui 9:84cb66d0375d 88 char *piece = strtok((char *)rxPayload, " ");
yihui 9:84cb66d0375d 89 int argc = 0;
yihui 9:84cb66d0375d 90 while (piece && argc < MAX_ARGS) {
yihui 9:84cb66d0375d 91 argv[argc++] = piece;
yihui 9:84cb66d0375d 92 piece = strtok(0, " ");
yihui 9:84cb66d0375d 93 }
yihui 9:84cb66d0375d 94
yihui 9:84cb66d0375d 95 if (argc > 0) {
yihui 9:84cb66d0375d 96 node_parse(argc, argv);
yihui 9:84cb66d0375d 97 }
yihui 9:84cb66d0375d 98
yihui 0:e910d9bb040f 99 }
Rohit Grover 2:e060367b9024 100 }
yihui 0:e910d9bb040f 101
yihui 9:84cb66d0375d 102 void tick(void)
Rohit Grover 2:e060367b9024 103 {
yihui 9:84cb66d0375d 104 node_tick();
yihui 9:84cb66d0375d 105 }
yihui 9:84cb66d0375d 106
yihui 9:84cb66d0375d 107 void button_down(void)
yihui 9:84cb66d0375d 108 {
yihui 9:84cb66d0375d 109 button_event = true;
Rohit Grover 2:e060367b9024 110 }
yihui 0:e910d9bb040f 111
yihui 0:e910d9bb040f 112 int main(void)
yihui 0:e910d9bb040f 113 {
yihui 9:84cb66d0375d 114 power_on();
yihui 9:84cb66d0375d 115 blue = LED_ON;
yihui 9:84cb66d0375d 116 green = LED_ON;
yihui 9:84cb66d0375d 117
yihui 9:84cb66d0375d 118 #if BUTTON_DOWN
yihui 9:84cb66d0375d 119 button.mode(PullDown);
yihui 9:84cb66d0375d 120 button.rise(button_down);
yihui 9:84cb66d0375d 121 #else
yihui 9:84cb66d0375d 122 button.mode(PullUp);
yihui 9:84cb66d0375d 123 button.fall(button_down);
yihui 9:84cb66d0375d 124 #endif
yihui 0:e910d9bb040f 125
yihui 9:84cb66d0375d 126 LOG("Initialising the nRF51822\n");
Rohit Grover 2:e060367b9024 127 ble.init();
Rohit Grover 2:e060367b9024 128 ble.onDisconnection(disconnectionCallback);
Rohit Grover 2:e060367b9024 129 ble.onDataWritten(onDataWritten);
yihui 0:e910d9bb040f 130
Rohit Grover 2:e060367b9024 131 /* setup advertising */
Rohit Grover 2:e060367b9024 132 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
Rohit Grover 2:e060367b9024 133 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Rohit Grover 2:e060367b9024 134 ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
yihui 9:84cb66d0375d 135 (const uint8_t *)"NODE", sizeof("NODE"));
Rohit Grover 2:e060367b9024 136 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
rgrover1 6:e0fc9072e853 137 (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
yihui 0:e910d9bb040f 138
yihui 9:84cb66d0375d 139 DFUService dfu(ble);
yihui 0:e910d9bb040f 140
rgrover1 6:e0fc9072e853 141 UARTService uartService(ble);
rgrover1 6:e0fc9072e853 142 uartServicePtr = &uartService;
yihui 9:84cb66d0375d 143
yihui 9:84cb66d0375d 144 ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
yihui 9:84cb66d0375d 145 ble.startAdvertising();
yihui 9:84cb66d0375d 146
yihui 9:84cb66d0375d 147 node_init();
yihui 9:84cb66d0375d 148 ticker.attach(tick, 1);
yihui 0:e910d9bb040f 149
yihui 9:84cb66d0375d 150 blue = LED_OFF;
yihui 9:84cb66d0375d 151 green = LED_OFF;
yihui 9:84cb66d0375d 152
Rohit Grover 2:e060367b9024 153 while (true) {
yihui 9:84cb66d0375d 154 if (button_event) {
yihui 9:84cb66d0375d 155 int click;
yihui 9:84cb66d0375d 156
yihui 9:84cb66d0375d 157 green = LED_ON;
yihui 9:84cb66d0375d 158 click = button_detect();
yihui 9:84cb66d0375d 159 green = LED_OFF;
yihui 9:84cb66d0375d 160 LOG("click type: %d\n\r", click);
yihui 9:84cb66d0375d 161
yihui 9:84cb66d0375d 162 button_event = false;
yihui 9:84cb66d0375d 163
yihui 9:84cb66d0375d 164 if (1 == click) {
yihui 9:84cb66d0375d 165 } else if (2 == click) {
yihui 9:84cb66d0375d 166 //green = LED_ON;
yihui 9:84cb66d0375d 167 } else if (-1 == click) {
yihui 9:84cb66d0375d 168 green = LED_OFF;
yihui 9:84cb66d0375d 169 blue = LED_OFF;
yihui 9:84cb66d0375d 170 while (BUTTON_DOWN == button.read()) {
yihui 9:84cb66d0375d 171
yihui 9:84cb66d0375d 172 }
yihui 9:84cb66d0375d 173 nrf_delay_us(3000);
yihui 9:84cb66d0375d 174
yihui 9:84cb66d0375d 175 power_off();
yihui 9:84cb66d0375d 176 } else {
yihui 9:84cb66d0375d 177 continue;
yihui 9:84cb66d0375d 178 }
yihui 9:84cb66d0375d 179
yihui 9:84cb66d0375d 180 } else {
yihui 9:84cb66d0375d 181 ble.waitForEvent();
yihui 9:84cb66d0375d 182 }
yihui 0:e910d9bb040f 183 }
yihui 0:e910d9bb040f 184 }
yihui 9:84cb66d0375d 185
yihui 9:84cb66d0375d 186 int button_detect(void)
yihui 9:84cb66d0375d 187 {
yihui 9:84cb66d0375d 188 int t = 0;
yihui 9:84cb66d0375d 189
yihui 9:84cb66d0375d 190 while (1) {
yihui 9:84cb66d0375d 191 if (button.read() != BUTTON_DOWN) {
yihui 9:84cb66d0375d 192 if (t < 30) {
yihui 9:84cb66d0375d 193 return 0; // for anti shake
yihui 9:84cb66d0375d 194 } else {
yihui 9:84cb66d0375d 195 break;
yihui 9:84cb66d0375d 196 }
yihui 9:84cb66d0375d 197 }
yihui 9:84cb66d0375d 198
yihui 9:84cb66d0375d 199 if (t > 30000) { // More than 3 seconds
yihui 9:84cb66d0375d 200 return -1; // long click
yihui 9:84cb66d0375d 201 }
yihui 9:84cb66d0375d 202
yihui 9:84cb66d0375d 203 t++;
yihui 9:84cb66d0375d 204 nrf_delay_us(100);
yihui 9:84cb66d0375d 205 }
yihui 9:84cb66d0375d 206
yihui 9:84cb66d0375d 207 if (t > 4000) { // More than 0.4 seconds
yihui 9:84cb66d0375d 208 return 1; // single click
yihui 9:84cb66d0375d 209 }
yihui 9:84cb66d0375d 210
yihui 9:84cb66d0375d 211 while (true) {
yihui 9:84cb66d0375d 212 if (button.read() == BUTTON_DOWN) {
yihui 9:84cb66d0375d 213 nrf_delay_us(1000);
yihui 9:84cb66d0375d 214 if (button.read() == BUTTON_DOWN) {
yihui 9:84cb66d0375d 215 return 2; // double click
yihui 9:84cb66d0375d 216 }
yihui 9:84cb66d0375d 217
yihui 9:84cb66d0375d 218 t += 10;
yihui 9:84cb66d0375d 219 }
yihui 9:84cb66d0375d 220
yihui 9:84cb66d0375d 221 if (t > 4000) {
yihui 9:84cb66d0375d 222 return 1; // The interval of double click should less than 0.4 seconds, so it's single click
yihui 9:84cb66d0375d 223 }
yihui 9:84cb66d0375d 224
yihui 9:84cb66d0375d 225 t++;
yihui 9:84cb66d0375d 226 nrf_delay_us(100);
yihui 9:84cb66d0375d 227 }
yihui 9:84cb66d0375d 228 }