The firmware of the Grove Node
Dependencies: BLE_API color_pixels mbed-src-nrf51822 nRF51822
Fork of BLE_LoopbackUART by
main.cpp@9:84cb66d0375d, 2014-11-06 (annotated)
- 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?
User | Revision | Line number | New 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 | } |