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 Jun 04 12:39:32 2015 +0000
Revision:
11:c0885b74a63a
Parent:
10:f34ff4e47741
fixed direct control bug

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 11:c0885b74a63a 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 10:f34ff4e47741 52 volatile bool ble_is_connected = false;
yihui 10:f34ff4e47741 53
yihui 9:84cb66d0375d 54 volatile bool button_event = false;
yihui 9:84cb66d0375d 55
yihui 9:84cb66d0375d 56 const int MAX_ARGS = 8;
yihui 9:84cb66d0375d 57 char *argv[MAX_ARGS];
yihui 0:e910d9bb040f 58
yihui 9:84cb66d0375d 59 static const uint8_t SIZEOF_TX_RX_BUFFER = 32;
yihui 9:84cb66d0375d 60 uint8_t rxPayload[SIZEOF_TX_RX_BUFFER] = {0,};
yihui 9:84cb66d0375d 61
yihui 9:84cb66d0375d 62 extern "C" void power_on();
yihui 9:84cb66d0375d 63 extern "C" void power_off();
yihui 9:84cb66d0375d 64
yihui 9:84cb66d0375d 65 extern void node_init();
yihui 9:84cb66d0375d 66 extern void node_tick();
yihui 9:84cb66d0375d 67 extern void node_parse(int argc, char *argv[]);
yihui 9:84cb66d0375d 68
yihui 9:84cb66d0375d 69 int button_detect();
yihui 0:e910d9bb040f 70
yihui 10:f34ff4e47741 71 void connectionCallback(Gap::Handle_t handle, const Gap::ConnectionParams_t *params)
yihui 10:f34ff4e47741 72 {
yihui 10:f34ff4e47741 73 LOG("Connected\n");
yihui 10:f34ff4e47741 74 ble_is_connected = true;
yihui 10:f34ff4e47741 75 }
yihui 10:f34ff4e47741 76
rgrover1 5:4bc41267a03a 77 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
yihui 0:e910d9bb040f 78 {
yihui 9:84cb66d0375d 79 LOG("Disconnected!\n");
yihui 9:84cb66d0375d 80 LOG("Restarting the advertising process\n");
Rohit Grover 2:e060367b9024 81 ble.startAdvertising();
yihui 10:f34ff4e47741 82 ble_is_connected = false;
Rohit Grover 2:e060367b9024 83 }
yihui 0:e910d9bb040f 84
rgrover1 6:e0fc9072e853 85 void onDataWritten(const GattCharacteristicWriteCBParams *params)
yihui 0:e910d9bb040f 86 {
rgrover1 6:e0fc9072e853 87 if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
rgrover1 5:4bc41267a03a 88 uint16_t bytesRead = params->len;
yihui 9:84cb66d0375d 89 LOG("received %u bytes\n\r", bytesRead);
yihui 9:84cb66d0375d 90 if (bytesRead < sizeof(rxPayload)) {
yihui 9:84cb66d0375d 91 memcpy(rxPayload, params->data, bytesRead);
yihui 9:84cb66d0375d 92 rxPayload[bytesRead] = '\0';
yihui 9:84cb66d0375d 93 }
yihui 9:84cb66d0375d 94
yihui 9:84cb66d0375d 95 LOG("%s\n", (char *)rxPayload);
yihui 9:84cb66d0375d 96
yihui 9:84cb66d0375d 97 char *piece = strtok((char *)rxPayload, " ");
yihui 9:84cb66d0375d 98 int argc = 0;
yihui 9:84cb66d0375d 99 while (piece && argc < MAX_ARGS) {
yihui 9:84cb66d0375d 100 argv[argc++] = piece;
yihui 9:84cb66d0375d 101 piece = strtok(0, " ");
yihui 9:84cb66d0375d 102 }
yihui 9:84cb66d0375d 103
yihui 9:84cb66d0375d 104 if (argc > 0) {
yihui 9:84cb66d0375d 105 node_parse(argc, argv);
yihui 9:84cb66d0375d 106 }
yihui 9:84cb66d0375d 107
yihui 0:e910d9bb040f 108 }
Rohit Grover 2:e060367b9024 109 }
yihui 0:e910d9bb040f 110
yihui 9:84cb66d0375d 111 void tick(void)
Rohit Grover 2:e060367b9024 112 {
yihui 9:84cb66d0375d 113 node_tick();
yihui 9:84cb66d0375d 114 }
yihui 9:84cb66d0375d 115
yihui 9:84cb66d0375d 116 void button_down(void)
yihui 9:84cb66d0375d 117 {
yihui 9:84cb66d0375d 118 button_event = true;
Rohit Grover 2:e060367b9024 119 }
yihui 0:e910d9bb040f 120
yihui 0:e910d9bb040f 121 int main(void)
yihui 0:e910d9bb040f 122 {
yihui 9:84cb66d0375d 123 power_on();
yihui 9:84cb66d0375d 124 blue = LED_ON;
yihui 9:84cb66d0375d 125 green = LED_ON;
yihui 9:84cb66d0375d 126
yihui 9:84cb66d0375d 127 #if BUTTON_DOWN
yihui 9:84cb66d0375d 128 button.mode(PullDown);
yihui 9:84cb66d0375d 129 button.rise(button_down);
yihui 9:84cb66d0375d 130 #else
yihui 9:84cb66d0375d 131 button.mode(PullUp);
yihui 9:84cb66d0375d 132 button.fall(button_down);
yihui 9:84cb66d0375d 133 #endif
yihui 0:e910d9bb040f 134
yihui 9:84cb66d0375d 135 LOG("Initialising the nRF51822\n");
Rohit Grover 2:e060367b9024 136 ble.init();
yihui 10:f34ff4e47741 137 ble.onConnection(connectionCallback);
Rohit Grover 2:e060367b9024 138 ble.onDisconnection(disconnectionCallback);
Rohit Grover 2:e060367b9024 139 ble.onDataWritten(onDataWritten);
yihui 0:e910d9bb040f 140
Rohit Grover 2:e060367b9024 141 /* setup advertising */
Rohit Grover 2:e060367b9024 142 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
Rohit Grover 2:e060367b9024 143 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Rohit Grover 2:e060367b9024 144 ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
yihui 9:84cb66d0375d 145 (const uint8_t *)"NODE", sizeof("NODE"));
Rohit Grover 2:e060367b9024 146 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
rgrover1 6:e0fc9072e853 147 (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
yihui 0:e910d9bb040f 148
yihui 9:84cb66d0375d 149 DFUService dfu(ble);
yihui 0:e910d9bb040f 150
rgrover1 6:e0fc9072e853 151 UARTService uartService(ble);
rgrover1 6:e0fc9072e853 152 uartServicePtr = &uartService;
yihui 9:84cb66d0375d 153
yihui 9:84cb66d0375d 154 ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
yihui 9:84cb66d0375d 155 ble.startAdvertising();
yihui 9:84cb66d0375d 156
yihui 9:84cb66d0375d 157 node_init();
yihui 9:84cb66d0375d 158 ticker.attach(tick, 1);
yihui 0:e910d9bb040f 159
yihui 9:84cb66d0375d 160 blue = LED_OFF;
yihui 9:84cb66d0375d 161 green = LED_OFF;
yihui 9:84cb66d0375d 162
Rohit Grover 2:e060367b9024 163 while (true) {
yihui 9:84cb66d0375d 164 if (button_event) {
yihui 9:84cb66d0375d 165 int click;
yihui 9:84cb66d0375d 166
yihui 9:84cb66d0375d 167 green = LED_ON;
yihui 9:84cb66d0375d 168 click = button_detect();
yihui 9:84cb66d0375d 169 green = LED_OFF;
yihui 9:84cb66d0375d 170 LOG("click type: %d\n\r", click);
yihui 9:84cb66d0375d 171
yihui 9:84cb66d0375d 172 button_event = false;
yihui 9:84cb66d0375d 173
yihui 9:84cb66d0375d 174 if (1 == click) {
yihui 9:84cb66d0375d 175 } else if (2 == click) {
yihui 9:84cb66d0375d 176 //green = LED_ON;
yihui 9:84cb66d0375d 177 } else if (-1 == click) {
yihui 9:84cb66d0375d 178 green = LED_OFF;
yihui 9:84cb66d0375d 179 blue = LED_OFF;
yihui 9:84cb66d0375d 180 while (BUTTON_DOWN == button.read()) {
yihui 9:84cb66d0375d 181
yihui 9:84cb66d0375d 182 }
yihui 9:84cb66d0375d 183 nrf_delay_us(3000);
yihui 9:84cb66d0375d 184
yihui 9:84cb66d0375d 185 power_off();
yihui 9:84cb66d0375d 186 } else {
yihui 9:84cb66d0375d 187 continue;
yihui 9:84cb66d0375d 188 }
yihui 9:84cb66d0375d 189
yihui 9:84cb66d0375d 190 } else {
yihui 9:84cb66d0375d 191 ble.waitForEvent();
yihui 9:84cb66d0375d 192 }
yihui 0:e910d9bb040f 193 }
yihui 0:e910d9bb040f 194 }
yihui 9:84cb66d0375d 195
yihui 9:84cb66d0375d 196 int button_detect(void)
yihui 9:84cb66d0375d 197 {
yihui 9:84cb66d0375d 198 int t = 0;
yihui 9:84cb66d0375d 199
yihui 9:84cb66d0375d 200 while (1) {
yihui 9:84cb66d0375d 201 if (button.read() != BUTTON_DOWN) {
yihui 9:84cb66d0375d 202 if (t < 30) {
yihui 9:84cb66d0375d 203 return 0; // for anti shake
yihui 9:84cb66d0375d 204 } else {
yihui 9:84cb66d0375d 205 break;
yihui 9:84cb66d0375d 206 }
yihui 9:84cb66d0375d 207 }
yihui 9:84cb66d0375d 208
yihui 9:84cb66d0375d 209 if (t > 30000) { // More than 3 seconds
yihui 9:84cb66d0375d 210 return -1; // long click
yihui 9:84cb66d0375d 211 }
yihui 9:84cb66d0375d 212
yihui 9:84cb66d0375d 213 t++;
yihui 9:84cb66d0375d 214 nrf_delay_us(100);
yihui 9:84cb66d0375d 215 }
yihui 9:84cb66d0375d 216
yihui 9:84cb66d0375d 217 if (t > 4000) { // More than 0.4 seconds
yihui 9:84cb66d0375d 218 return 1; // single click
yihui 9:84cb66d0375d 219 }
yihui 9:84cb66d0375d 220
yihui 9:84cb66d0375d 221 while (true) {
yihui 9:84cb66d0375d 222 if (button.read() == BUTTON_DOWN) {
yihui 9:84cb66d0375d 223 nrf_delay_us(1000);
yihui 9:84cb66d0375d 224 if (button.read() == BUTTON_DOWN) {
yihui 9:84cb66d0375d 225 return 2; // double click
yihui 9:84cb66d0375d 226 }
yihui 9:84cb66d0375d 227
yihui 9:84cb66d0375d 228 t += 10;
yihui 9:84cb66d0375d 229 }
yihui 9:84cb66d0375d 230
yihui 9:84cb66d0375d 231 if (t > 4000) {
yihui 9:84cb66d0375d 232 return 1; // The interval of double click should less than 0.4 seconds, so it's single click
yihui 9:84cb66d0375d 233 }
yihui 9:84cb66d0375d 234
yihui 9:84cb66d0375d 235 t++;
yihui 9:84cb66d0375d 236 nrf_delay_us(100);
yihui 9:84cb66d0375d 237 }
yihui 9:84cb66d0375d 238 }