The firmware of the Grove Node
Dependencies: BLE_API color_pixels mbed-src-nrf51822 nRF51822
Fork of BLE_LoopbackUART by
main.cpp@11:c0885b74a63a, 2015-06-04 (annotated)
- 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?
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 | 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 | } |