test firmware for BLE Micro V1.3 1. test io, vcc and ble 2. act as a UART to BLE bridge
Dependencies: BLE_API Buffer mbed
Fork of BLE_LEDBlinker by
main.cpp@12:c4090cb58976, 2015-12-08 (annotated)
- Committer:
- arch
- Date:
- Tue Dec 08 08:34:22 2015 +0000
- Revision:
- 12:c4090cb58976
- Parent:
- 11:c8cbc4bc2c17
fix USBTX/USBRX pins config
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
arch | 11:c8cbc4bc2c17 | 1 | // nRF51822 lib revision 534 |
rgrover1 | 0:415d7f24cb91 | 2 | |
rgrover1 | 0:415d7f24cb91 | 3 | #include "mbed.h" |
rgrover1 | 6:1730f66fb14d | 4 | #include "ble/BLE.h" |
rgrover1 | 6:1730f66fb14d | 5 | #include "ble/DiscoveredCharacteristic.h" |
rgrover1 | 6:1730f66fb14d | 6 | #include "ble/DiscoveredService.h" |
arch | 11:c8cbc4bc2c17 | 7 | #include "ble/services/UARTService.h" |
arch | 11:c8cbc4bc2c17 | 8 | #include "ble/services/DFUService.h" |
arch | 11:c8cbc4bc2c17 | 9 | #include "Buffer.h" |
arch | 11:c8cbc4bc2c17 | 10 | |
arch | 11:c8cbc4bc2c17 | 11 | |
arch | 11:c8cbc4bc2c17 | 12 | #define LOG(args...) // printf(args) |
arch | 11:c8cbc4bc2c17 | 13 | |
rgrover1 | 0:415d7f24cb91 | 14 | |
rgrover1 | 6:1730f66fb14d | 15 | BLE ble; |
arch | 11:c8cbc4bc2c17 | 16 | UARTService *bleuart; |
rgrover1 | 6:1730f66fb14d | 17 | |
rgrover1 | 1:1db45b17552e | 18 | bool triggerLedCharacteristic = false; |
rgrover1 | 0:415d7f24cb91 | 19 | DiscoveredCharacteristic ledCharacteristic; |
arch | 11:c8cbc4bc2c17 | 20 | int saved_test_result = 0; |
arch | 11:c8cbc4bc2c17 | 21 | volatile int current_test_status = 1; |
arch | 11:c8cbc4bc2c17 | 22 | uint32_t device_scan_time = 0; |
arch | 11:c8cbc4bc2c17 | 23 | uint32_t device_found_time = 0; |
arch | 11:c8cbc4bc2c17 | 24 | uint32_t device_connected_time = 0; |
rgrover1 | 0:415d7f24cb91 | 25 | |
arch | 11:c8cbc4bc2c17 | 26 | int test_is_passed(); |
arch | 11:c8cbc4bc2c17 | 27 | int test_save_result(int result); |
arch | 11:c8cbc4bc2c17 | 28 | int test_check_io(); |
arch | 11:c8cbc4bc2c17 | 29 | int test_check_vcc(); |
arch | 11:c8cbc4bc2c17 | 30 | int test_output_result(int result); |
arch | 11:c8cbc4bc2c17 | 31 | |
arch | 11:c8cbc4bc2c17 | 32 | Serial *uart; |
arch | 11:c8cbc4bc2c17 | 33 | Buffer <char> uartRxBuffer(0x100); |
arch | 11:c8cbc4bc2c17 | 34 | |
arch | 11:c8cbc4bc2c17 | 35 | uint8_t bleIsConnected = 0; |
arch | 11:c8cbc4bc2c17 | 36 | uint8_t bleTxFlag = 0; |
rgrover1 | 0:415d7f24cb91 | 37 | |
arch | 11:c8cbc4bc2c17 | 38 | bool rxPayloadUpdated = false; |
arch | 11:c8cbc4bc2c17 | 39 | uint8_t rxPayload[20 + 1] = {0,}; |
arch | 11:c8cbc4bc2c17 | 40 | uint8_t txPayload[20 + 1] = {0,}; |
rgrover1 | 0:415d7f24cb91 | 41 | |
arch | 11:c8cbc4bc2c17 | 42 | void uart2ble(void) |
arch | 11:c8cbc4bc2c17 | 43 | { |
arch | 11:c8cbc4bc2c17 | 44 | uint16_t bytesToWrite = 0; |
arch | 11:c8cbc4bc2c17 | 45 | for (int i = 0; i < 20; i++) { |
arch | 11:c8cbc4bc2c17 | 46 | if (uartRxBuffer.available()) { |
arch | 11:c8cbc4bc2c17 | 47 | txPayload[bytesToWrite] = uartRxBuffer; |
arch | 11:c8cbc4bc2c17 | 48 | bytesToWrite++; |
arch | 11:c8cbc4bc2c17 | 49 | } |
arch | 11:c8cbc4bc2c17 | 50 | } |
arch | 11:c8cbc4bc2c17 | 51 | |
arch | 11:c8cbc4bc2c17 | 52 | if (bytesToWrite != 0) { |
arch | 11:c8cbc4bc2c17 | 53 | bleTxFlag = 1; |
arch | 11:c8cbc4bc2c17 | 54 | |
arch | 11:c8cbc4bc2c17 | 55 | ble.updateCharacteristicValue(bleuart->getRXCharacteristicHandle(), txPayload, bytesToWrite); |
rgrover1 | 0:415d7f24cb91 | 56 | } else { |
arch | 11:c8cbc4bc2c17 | 57 | bleTxFlag = 0; |
rgrover1 | 0:415d7f24cb91 | 58 | } |
rgrover1 | 0:415d7f24cb91 | 59 | } |
rgrover1 | 0:415d7f24cb91 | 60 | |
arch | 11:c8cbc4bc2c17 | 61 | void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) |
arch | 11:c8cbc4bc2c17 | 62 | { |
arch | 11:c8cbc4bc2c17 | 63 | if (params->peerAddr[0] != params->peerAddr[5]) { /* !ALERT! Alter this filter to suit your device. */ |
arch | 11:c8cbc4bc2c17 | 64 | return; |
rgrover1 | 0:415d7f24cb91 | 65 | } |
arch | 11:c8cbc4bc2c17 | 66 | device_found_time = us_ticker_read(); |
arch | 11:c8cbc4bc2c17 | 67 | |
arch | 11:c8cbc4bc2c17 | 68 | LOG("device found @ %d\r\n", device_found_time); |
arch | 11:c8cbc4bc2c17 | 69 | |
arch | 11:c8cbc4bc2c17 | 70 | LOG("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n", |
arch | 11:c8cbc4bc2c17 | 71 | params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0], |
arch | 11:c8cbc4bc2c17 | 72 | params->rssi, params->isScanResponse, params->type); |
arch | 11:c8cbc4bc2c17 | 73 | |
arch | 11:c8cbc4bc2c17 | 74 | ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_PUBLIC, NULL, NULL); |
rgrover1 | 0:415d7f24cb91 | 75 | } |
rgrover1 | 0:415d7f24cb91 | 76 | |
rgrover1 | 0:415d7f24cb91 | 77 | |
arch | 11:c8cbc4bc2c17 | 78 | void connectionCallback(const Gap::ConnectionCallbackParams_t *params) |
arch | 11:c8cbc4bc2c17 | 79 | { |
rgrover1 | 0:415d7f24cb91 | 80 | if (params->role == Gap::CENTRAL) { |
arch | 11:c8cbc4bc2c17 | 81 | device_connected_time = us_ticker_read(); |
arch | 11:c8cbc4bc2c17 | 82 | |
arch | 11:c8cbc4bc2c17 | 83 | LOG("device connected @ %d\r\n", device_connected_time); |
arch | 11:c8cbc4bc2c17 | 84 | if (current_test_status == 3) |
arch | 11:c8cbc4bc2c17 | 85 | { |
arch | 11:c8cbc4bc2c17 | 86 | current_test_status = 0; |
arch | 12:c4090cb58976 | 87 | test_output_result(0); |
arch | 11:c8cbc4bc2c17 | 88 | test_save_result(0); |
arch | 11:c8cbc4bc2c17 | 89 | } |
arch | 11:c8cbc4bc2c17 | 90 | |
arch | 11:c8cbc4bc2c17 | 91 | } else { |
arch | 11:c8cbc4bc2c17 | 92 | LOG("connected\r\n"); |
arch | 11:c8cbc4bc2c17 | 93 | |
arch | 11:c8cbc4bc2c17 | 94 | bleIsConnected = 1; |
arch | 11:c8cbc4bc2c17 | 95 | bleTxFlag = 0; |
arch | 11:c8cbc4bc2c17 | 96 | uartRxBuffer.clear(); |
rgrover1 | 0:415d7f24cb91 | 97 | } |
rgrover1 | 0:415d7f24cb91 | 98 | } |
rgrover1 | 0:415d7f24cb91 | 99 | |
arch | 11:c8cbc4bc2c17 | 100 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
arch | 11:c8cbc4bc2c17 | 101 | { |
arch | 11:c8cbc4bc2c17 | 102 | LOG("Disconnected!\n\r"); |
arch | 11:c8cbc4bc2c17 | 103 | LOG("Restarting the advertising process\n\r"); |
arch | 11:c8cbc4bc2c17 | 104 | |
arch | 11:c8cbc4bc2c17 | 105 | bleTxFlag = 0; |
arch | 11:c8cbc4bc2c17 | 106 | bleIsConnected = 0; |
arch | 11:c8cbc4bc2c17 | 107 | |
arch | 11:c8cbc4bc2c17 | 108 | ble.startAdvertising(); |
arch | 11:c8cbc4bc2c17 | 109 | |
arch | 11:c8cbc4bc2c17 | 110 | } |
arch | 11:c8cbc4bc2c17 | 111 | |
arch | 11:c8cbc4bc2c17 | 112 | void onDataWritten(const GattWriteCallbackParams *params) |
arch | 11:c8cbc4bc2c17 | 113 | { |
arch | 11:c8cbc4bc2c17 | 114 | if ((bleuart != NULL) && (params->handle == bleuart->getTXCharacteristicHandle())) { |
arch | 11:c8cbc4bc2c17 | 115 | uint16_t bytesRead = params->len; |
arch | 11:c8cbc4bc2c17 | 116 | LOG("received %u bytes\n\r", bytesRead); |
arch | 11:c8cbc4bc2c17 | 117 | // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); |
arch | 11:c8cbc4bc2c17 | 118 | |
arch | 11:c8cbc4bc2c17 | 119 | for (int i = 0; i < bytesRead; i++) { |
arch | 11:c8cbc4bc2c17 | 120 | uart->putc(params->data[i]); |
rgrover1 | 0:415d7f24cb91 | 121 | } |
rgrover1 | 0:415d7f24cb91 | 122 | } |
rgrover1 | 0:415d7f24cb91 | 123 | } |
rgrover1 | 0:415d7f24cb91 | 124 | |
arch | 11:c8cbc4bc2c17 | 125 | void onDataSent(unsigned count) |
arch | 11:c8cbc4bc2c17 | 126 | { |
arch | 11:c8cbc4bc2c17 | 127 | LOG("onDataSent\r\n"); |
arch | 11:c8cbc4bc2c17 | 128 | |
arch | 11:c8cbc4bc2c17 | 129 | uart2ble(); |
rgrover1 | 0:415d7f24cb91 | 130 | } |
rgrover1 | 0:415d7f24cb91 | 131 | |
arch | 11:c8cbc4bc2c17 | 132 | int main(void) |
arch | 11:c8cbc4bc2c17 | 133 | { |
arch | 11:c8cbc4bc2c17 | 134 | int io_status; |
arch | 11:c8cbc4bc2c17 | 135 | int vcc_status; |
arch | 12:c4090cb58976 | 136 | |
arch | 11:c8cbc4bc2c17 | 137 | saved_test_result = test_is_passed(); |
arch | 11:c8cbc4bc2c17 | 138 | if (!saved_test_result) { |
arch | 12:c4090cb58976 | 139 | { |
arch | 12:c4090cb58976 | 140 | uart = new Serial(p20, p21); // release USBTX and USBRX |
arch | 12:c4090cb58976 | 141 | uart->baud(38400); |
arch | 12:c4090cb58976 | 142 | } |
arch | 12:c4090cb58976 | 143 | |
arch | 11:c8cbc4bc2c17 | 144 | io_status = test_check_io(); |
arch | 11:c8cbc4bc2c17 | 145 | vcc_status = test_check_vcc(); |
arch | 11:c8cbc4bc2c17 | 146 | |
arch | 11:c8cbc4bc2c17 | 147 | if (io_status) { |
arch | 11:c8cbc4bc2c17 | 148 | test_output_result(1); |
arch | 11:c8cbc4bc2c17 | 149 | } else { |
arch | 11:c8cbc4bc2c17 | 150 | current_test_status = 2; |
arch | 11:c8cbc4bc2c17 | 151 | if (vcc_status) { |
arch | 11:c8cbc4bc2c17 | 152 | test_output_result(2); |
arch | 11:c8cbc4bc2c17 | 153 | } else { |
arch | 11:c8cbc4bc2c17 | 154 | current_test_status = 3; |
arch | 11:c8cbc4bc2c17 | 155 | } |
arch | 11:c8cbc4bc2c17 | 156 | } |
arch | 11:c8cbc4bc2c17 | 157 | |
arch | 11:c8cbc4bc2c17 | 158 | } else { |
arch | 12:c4090cb58976 | 159 | test_output_result(0); |
arch | 12:c4090cb58976 | 160 | uart = new Serial(p8, p7); |
arch | 12:c4090cb58976 | 161 | uart->baud(38400); |
arch | 11:c8cbc4bc2c17 | 162 | } |
arch | 11:c8cbc4bc2c17 | 163 | |
rgrover1 | 0:415d7f24cb91 | 164 | |
arch | 12:c4090cb58976 | 165 | |
rgrover1 | 0:415d7f24cb91 | 166 | |
rgrover1 | 0:415d7f24cb91 | 167 | ble.init(); |
rgrover1 | 5:3bbad34d1a85 | 168 | ble.gap().onConnection(connectionCallback); |
rgrover1 | 5:3bbad34d1a85 | 169 | ble.gap().onDisconnection(disconnectionCallback); |
arch | 11:c8cbc4bc2c17 | 170 | ble.onDataWritten(onDataWritten); |
arch | 11:c8cbc4bc2c17 | 171 | ble.onDataSent(onDataSent); |
rgrover1 | 0:415d7f24cb91 | 172 | |
arch | 11:c8cbc4bc2c17 | 173 | if (!saved_test_result) { |
arch | 11:c8cbc4bc2c17 | 174 | LOG("io test %s\r\n", io_status ? "failed" : "ok"); |
arch | 11:c8cbc4bc2c17 | 175 | LOG("vcc test %s\r\n", vcc_status ? "failed" : "ok"); |
arch | 11:c8cbc4bc2c17 | 176 | |
arch | 11:c8cbc4bc2c17 | 177 | LOG("enable ble centre role\r\n"); |
arch | 11:c8cbc4bc2c17 | 178 | |
arch | 11:c8cbc4bc2c17 | 179 | ble.gap().setScanParams(500, 400); |
arch | 11:c8cbc4bc2c17 | 180 | ble.gap().startScan(advertisementCallback); |
arch | 11:c8cbc4bc2c17 | 181 | device_scan_time = us_ticker_read(); |
arch | 11:c8cbc4bc2c17 | 182 | LOG("scan device @ %d\r\n", device_scan_time); |
rgrover1 | 0:415d7f24cb91 | 183 | |
arch | 11:c8cbc4bc2c17 | 184 | { |
arch | 11:c8cbc4bc2c17 | 185 | int wait_time_us = 0; |
arch | 11:c8cbc4bc2c17 | 186 | while (current_test_status == 3 && wait_time_us < 10000000) { |
arch | 11:c8cbc4bc2c17 | 187 | wait_us(1); |
arch | 11:c8cbc4bc2c17 | 188 | wait_time_us++; |
arch | 11:c8cbc4bc2c17 | 189 | } |
arch | 11:c8cbc4bc2c17 | 190 | |
arch | 11:c8cbc4bc2c17 | 191 | if (current_test_status == 0) { |
arch | 11:c8cbc4bc2c17 | 192 | LOG("from scan to connected: %d", device_connected_time - device_scan_time); |
arch | 11:c8cbc4bc2c17 | 193 | } else if (current_test_status == 3) { |
arch | 12:c4090cb58976 | 194 | test_output_result(3); |
arch | 11:c8cbc4bc2c17 | 195 | } |
arch | 11:c8cbc4bc2c17 | 196 | } |
arch | 11:c8cbc4bc2c17 | 197 | } |
arch | 11:c8cbc4bc2c17 | 198 | |
arch | 11:c8cbc4bc2c17 | 199 | /* setup advertising */ |
arch | 11:c8cbc4bc2c17 | 200 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); |
arch | 11:c8cbc4bc2c17 | 201 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
arch | 11:c8cbc4bc2c17 | 202 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
arch | 11:c8cbc4bc2c17 | 203 | (const uint8_t *)"BLE UART", sizeof("BLE UART") - 1); |
arch | 11:c8cbc4bc2c17 | 204 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, |
arch | 11:c8cbc4bc2c17 | 205 | (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); |
arch | 11:c8cbc4bc2c17 | 206 | |
arch | 11:c8cbc4bc2c17 | 207 | bleuart = new UARTService(ble); |
arch | 11:c8cbc4bc2c17 | 208 | DFUService *dfu = new DFUService(ble); |
arch | 11:c8cbc4bc2c17 | 209 | |
arch | 11:c8cbc4bc2c17 | 210 | ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ |
arch | 11:c8cbc4bc2c17 | 211 | ble.startAdvertising(); |
rgrover1 | 0:415d7f24cb91 | 212 | |
rgrover1 | 0:415d7f24cb91 | 213 | while (true) { |
arch | 11:c8cbc4bc2c17 | 214 | if (bleIsConnected) { |
arch | 11:c8cbc4bc2c17 | 215 | uint32_t timeout = 1000; |
arch | 11:c8cbc4bc2c17 | 216 | while (timeout) { |
arch | 11:c8cbc4bc2c17 | 217 | timeout--; |
arch | 11:c8cbc4bc2c17 | 218 | if (uart->readable()) { |
arch | 11:c8cbc4bc2c17 | 219 | uartRxBuffer.put((char)uart->getc()); |
arch | 11:c8cbc4bc2c17 | 220 | timeout = 1000; |
arch | 11:c8cbc4bc2c17 | 221 | } |
arch | 11:c8cbc4bc2c17 | 222 | } |
arch | 11:c8cbc4bc2c17 | 223 | |
arch | 11:c8cbc4bc2c17 | 224 | if (bleIsConnected && bleTxFlag == 0 && uartRxBuffer.available()) { |
arch | 11:c8cbc4bc2c17 | 225 | uart2ble(); |
arch | 11:c8cbc4bc2c17 | 226 | bleTxFlag = 1; |
arch | 11:c8cbc4bc2c17 | 227 | } |
arch | 11:c8cbc4bc2c17 | 228 | } else { |
arch | 11:c8cbc4bc2c17 | 229 | ble.waitForEvent(); |
rgrover1 | 0:415d7f24cb91 | 230 | } |
rgrover1 | 0:415d7f24cb91 | 231 | } |
rgrover1 | 0:415d7f24cb91 | 232 | } |
arch | 11:c8cbc4bc2c17 | 233 | |
arch | 11:c8cbc4bc2c17 | 234 | extern "C" void HardFault_Handler() |
arch | 11:c8cbc4bc2c17 | 235 | { |
arch | 11:c8cbc4bc2c17 | 236 | NVIC_SystemReset(); |
arch | 11:c8cbc4bc2c17 | 237 | } |