TYBLE16 on os5 sample programs
Dependencies: BME280 TextLCD nRF51_Vdd
Fork of TYBLE16_mbedlized_os5_BASE by
Please refer following notebook.
/users/kenjiArai/notebook/tyble16-module-as-mbed-os-5-board-mbedlization/
7_Uart_Client/main.cpp@1:9011c83e4178, 2018-04-14 (annotated)
- Committer:
- kenjiArai
- Date:
- Sat Apr 14 04:56:34 2018 +0000
- Revision:
- 1:9011c83e4178
added samples
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 1:9011c83e4178 | 1 | /* |
kenjiArai | 1:9011c83e4178 | 2 | * ------- BLE Central/Client UART function ----------------------------------- |
kenjiArai | 1:9011c83e4178 | 3 | * communicate with BLE_UART_Server program |
kenjiArai | 1:9011c83e4178 | 4 | * --- Tested on Switch Science mbed TY51822r3 --- |
kenjiArai | 1:9011c83e4178 | 5 | * |
kenjiArai | 1:9011c83e4178 | 6 | * Modified by Kenji Arai |
kenjiArai | 1:9011c83e4178 | 7 | * http://www.page.sannet.ne.jp/kenjia/index.html |
kenjiArai | 1:9011c83e4178 | 8 | * https://os.mbed.com/users/kenjiArai/ |
kenjiArai | 1:9011c83e4178 | 9 | * |
kenjiArai | 1:9011c83e4178 | 10 | * Started: April 8th, 2016 |
kenjiArai | 1:9011c83e4178 | 11 | * Revised: June 13th, 2016 |
kenjiArai | 1:9011c83e4178 | 12 | * Revised: Feburary 10th, 2018 Not set mac addr but use device name |
kenjiArai | 1:9011c83e4178 | 13 | * Revised: Feburary 11th, 2018 use mbed-os5.7.4 with CircularBuffer |
kenjiArai | 1:9011c83e4178 | 14 | * Revised: April 14th, 2018 only for TYBLE16 |
kenjiArai | 1:9011c83e4178 | 15 | * |
kenjiArai | 1:9011c83e4178 | 16 | * Original program (see original.cpp file): |
kenjiArai | 1:9011c83e4178 | 17 | * S130 potential unstability case [closed] by Fabien Comte |
kenjiArai | 1:9011c83e4178 | 18 | * https://devzone.nordicsemi.com/question/49705/ |
kenjiArai | 1:9011c83e4178 | 19 | * s130-potential-unstability-case/ |
kenjiArai | 1:9011c83e4178 | 20 | * GitHub Q&A by Fabien COMTE |
kenjiArai | 1:9011c83e4178 | 21 | * https://github.com/ARMmbed/ble/issues/69 |
kenjiArai | 1:9011c83e4178 | 22 | * Reference program: |
kenjiArai | 1:9011c83e4178 | 23 | * BLE_Central_test by noboru koshinaka |
kenjiArai | 1:9011c83e4178 | 24 | * https://os.mbed.com/users/noboruk/code/BLE_Central_test/ |
kenjiArai | 1:9011c83e4178 | 25 | * Tested Server Device: |
kenjiArai | 1:9011c83e4178 | 26 | * BLE_Uart_Server |
kenjiArai | 1:9011c83e4178 | 27 | * https://os.mbed.com/users/kenjiArai/code/BLE_Uart_Server/ |
kenjiArai | 1:9011c83e4178 | 28 | */ |
kenjiArai | 1:9011c83e4178 | 29 | |
kenjiArai | 1:9011c83e4178 | 30 | //#define EXAMPLE_7_UART_CLIENT |
kenjiArai | 1:9011c83e4178 | 31 | #ifdef EXAMPLE_7_UART_CLIENT |
kenjiArai | 1:9011c83e4178 | 32 | |
kenjiArai | 1:9011c83e4178 | 33 | // Include -------------------------------------------------------------------- |
kenjiArai | 1:9011c83e4178 | 34 | #include "mbed.h" |
kenjiArai | 1:9011c83e4178 | 35 | #include "BLE.h" |
kenjiArai | 1:9011c83e4178 | 36 | #include "DiscoveredCharacteristic.h" |
kenjiArai | 1:9011c83e4178 | 37 | #include "DiscoveredService.h" |
kenjiArai | 1:9011c83e4178 | 38 | #include "UARTService.h" |
kenjiArai | 1:9011c83e4178 | 39 | #include "CircularBuffer.h" |
kenjiArai | 1:9011c83e4178 | 40 | |
kenjiArai | 1:9011c83e4178 | 41 | // Definition ----------------------------------------------------------------- |
kenjiArai | 1:9011c83e4178 | 42 | //#define USE_MAC // if you use mac address, please define it |
kenjiArai | 1:9011c83e4178 | 43 | |
kenjiArai | 1:9011c83e4178 | 44 | #define NUM_ONCE 20 |
kenjiArai | 1:9011c83e4178 | 45 | #define BFSIZE (NUM_ONCE+4) |
kenjiArai | 1:9011c83e4178 | 46 | |
kenjiArai | 1:9011c83e4178 | 47 | //#define USE_DEBUG_MODE |
kenjiArai | 1:9011c83e4178 | 48 | #ifdef USE_DEBUG_MODE |
kenjiArai | 1:9011c83e4178 | 49 | #define DBG(...) { pc.printf(__VA_ARGS__); } |
kenjiArai | 1:9011c83e4178 | 50 | #else |
kenjiArai | 1:9011c83e4178 | 51 | #define DBG(...) |
kenjiArai | 1:9011c83e4178 | 52 | #endif |
kenjiArai | 1:9011c83e4178 | 53 | |
kenjiArai | 1:9011c83e4178 | 54 | #define SOFT_DEVICE_FATHER_HANDLE 3 |
kenjiArai | 1:9011c83e4178 | 55 | |
kenjiArai | 1:9011c83e4178 | 56 | // Object --------------------------------------------------------------------- |
kenjiArai | 1:9011c83e4178 | 57 | BLE& ble_uart = BLE::Instance(); |
kenjiArai | 1:9011c83e4178 | 58 | DigitalOut alivenessLED(LED1, 1); |
kenjiArai | 1:9011c83e4178 | 59 | DigitalOut connectedLED(D0, 0); |
kenjiArai | 1:9011c83e4178 | 60 | Serial pc(USBTX, USBRX, 115200); |
kenjiArai | 1:9011c83e4178 | 61 | //Serial pc(P0_3, P0_1, 115200); // for another board |
kenjiArai | 1:9011c83e4178 | 62 | Ticker ticker; |
kenjiArai | 1:9011c83e4178 | 63 | CircularBuffer<char, 1536> ser_bf; |
kenjiArai | 1:9011c83e4178 | 64 | Thread tsk; |
kenjiArai | 1:9011c83e4178 | 65 | |
kenjiArai | 1:9011c83e4178 | 66 | // ROM / Constant data -------------------------------------------------------- |
kenjiArai | 1:9011c83e4178 | 67 | #ifdef USE_MAC |
kenjiArai | 1:9011c83e4178 | 68 | #warning "You need to modify below value based on your board." |
kenjiArai | 1:9011c83e4178 | 69 | const Gap::Address_t mac_board_0 = {0x50, 0x2b, 0xea, 0x14, 0x95, 0xd2}; |
kenjiArai | 1:9011c83e4178 | 70 | const Gap::Address_t mac_board_1 = {0x59, 0x2c, 0xa8, 0x0e, 0xe2, 0xef}; |
kenjiArai | 1:9011c83e4178 | 71 | const Gap::Address_t mac_board_2 = {0x0f, 0x72, 0xbf, 0x43, 0xbc, 0xd0}; |
kenjiArai | 1:9011c83e4178 | 72 | const Gap::Address_t mac_board_3 = {0x83, 0xc9, 0x1a, 0x90, 0xdf, 0xd6}; |
kenjiArai | 1:9011c83e4178 | 73 | const Gap::Address_t mac_board_4 = {0x43, 0xa4, 0x36, 0x11, 0x5b, 0xeb}; |
kenjiArai | 1:9011c83e4178 | 74 | #else |
kenjiArai | 1:9011c83e4178 | 75 | const char PEER_NAME[] = "UART_PJL"; |
kenjiArai | 1:9011c83e4178 | 76 | #endif |
kenjiArai | 1:9011c83e4178 | 77 | |
kenjiArai | 1:9011c83e4178 | 78 | // RAM ------------------------------------------------------------------------ |
kenjiArai | 1:9011c83e4178 | 79 | Gap::Handle_t connectionHandle = 0xFFFF; |
kenjiArai | 1:9011c83e4178 | 80 | DiscoveredCharacteristic uartTXCharacteristic; |
kenjiArai | 1:9011c83e4178 | 81 | DiscoveredCharacteristic uartRXCharacteristic; |
kenjiArai | 1:9011c83e4178 | 82 | bool foundUartRXCharacteristic = false; |
kenjiArai | 1:9011c83e4178 | 83 | bool connected2server = false; |
kenjiArai | 1:9011c83e4178 | 84 | bool connection_tx = false; |
kenjiArai | 1:9011c83e4178 | 85 | bool connection_rx = false; |
kenjiArai | 1:9011c83e4178 | 86 | UARTService * uartServicePtr = NULL; |
kenjiArai | 1:9011c83e4178 | 87 | Gap::Address_t my_mac; |
kenjiArai | 1:9011c83e4178 | 88 | int my_board_index = -1; |
kenjiArai | 1:9011c83e4178 | 89 | bool received_uart_dat = false; |
kenjiArai | 1:9011c83e4178 | 90 | int8_t uart_buffer[BFSIZE]; |
kenjiArai | 1:9011c83e4178 | 91 | uint8_t uart_bf_len; |
kenjiArai | 1:9011c83e4178 | 92 | volatile bool rx_isr_busy = false; |
kenjiArai | 1:9011c83e4178 | 93 | |
kenjiArai | 1:9011c83e4178 | 94 | // Function prototypes -------------------------------------------------------- |
kenjiArai | 1:9011c83e4178 | 95 | // BLE |
kenjiArai | 1:9011c83e4178 | 96 | void advertisementCallback(const Gap::AdvertisementCallbackParams_t *); |
kenjiArai | 1:9011c83e4178 | 97 | void serviceDiscoveryCallback(const DiscoveredService *); |
kenjiArai | 1:9011c83e4178 | 98 | void characteristicDiscoveryCallback(const DiscoveredCharacteristic *); |
kenjiArai | 1:9011c83e4178 | 99 | void discoveryTerminationCallback(Gap::Handle_t ); |
kenjiArai | 1:9011c83e4178 | 100 | void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *); |
kenjiArai | 1:9011c83e4178 | 101 | void connectionCallback(const Gap::ConnectionCallbackParams_t *); |
kenjiArai | 1:9011c83e4178 | 102 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *); |
kenjiArai | 1:9011c83e4178 | 103 | // Interrupt related |
kenjiArai | 1:9011c83e4178 | 104 | void periodicCallback(void); |
kenjiArai | 1:9011c83e4178 | 105 | void serialRxCallback(void); |
kenjiArai | 1:9011c83e4178 | 106 | // serial receiving |
kenjiArai | 1:9011c83e4178 | 107 | void pc_ser_rx(void); |
kenjiArai | 1:9011c83e4178 | 108 | void preparation_sending_data(void); |
kenjiArai | 1:9011c83e4178 | 109 | // Pre-check |
kenjiArai | 1:9011c83e4178 | 110 | bool mac_equals(const Gap::Address_t, const Gap::Address_t); |
kenjiArai | 1:9011c83e4178 | 111 | int get_board_index(const Gap::Address_t); |
kenjiArai | 1:9011c83e4178 | 112 | void adjust_line(uint8_t *); |
kenjiArai | 1:9011c83e4178 | 113 | |
kenjiArai | 1:9011c83e4178 | 114 | //------------------------------------------------------------------------------ |
kenjiArai | 1:9011c83e4178 | 115 | // Control Program |
kenjiArai | 1:9011c83e4178 | 116 | //------------------------------------------------------------------------------ |
kenjiArai | 1:9011c83e4178 | 117 | int main(void) |
kenjiArai | 1:9011c83e4178 | 118 | { |
kenjiArai | 1:9011c83e4178 | 119 | alivenessLED = 0; |
kenjiArai | 1:9011c83e4178 | 120 | pc.attach(&serialRxCallback, Serial::RxIrq); |
kenjiArai | 1:9011c83e4178 | 121 | ticker.attach(periodicCallback, 1); |
kenjiArai | 1:9011c83e4178 | 122 | tsk.start(pc_ser_rx); |
kenjiArai | 1:9011c83e4178 | 123 | // clear terminal output |
kenjiArai | 1:9011c83e4178 | 124 | for (int k = 0; k < 3; k++) { |
kenjiArai | 1:9011c83e4178 | 125 | pc.printf("\r\n"); |
kenjiArai | 1:9011c83e4178 | 126 | } |
kenjiArai | 1:9011c83e4178 | 127 | // opening message |
kenjiArai | 1:9011c83e4178 | 128 | pc.printf("UART Communication / Client(Central) side\r\n"); |
kenjiArai | 1:9011c83e4178 | 129 | pc.printf(" need Server module (run BLE_Uart_Server program)\r\n"); |
kenjiArai | 1:9011c83e4178 | 130 | // Mixed role ************************************************************** |
kenjiArai | 1:9011c83e4178 | 131 | ble_uart.init(); |
kenjiArai | 1:9011c83e4178 | 132 | ble_uart.gap().onConnection(connectionCallback); |
kenjiArai | 1:9011c83e4178 | 133 | ble_uart.gap().onDisconnection(disconnectionCallback); |
kenjiArai | 1:9011c83e4178 | 134 | // Client(Central) role **************************************************** |
kenjiArai | 1:9011c83e4178 | 135 | ble_uart.gattClient().onHVX(onReceivedDataFromDeviceCallback); |
kenjiArai | 1:9011c83e4178 | 136 | ble_uart.gap().setScanParams(500, 450); |
kenjiArai | 1:9011c83e4178 | 137 | ble_uart.gap().startScan(advertisementCallback); |
kenjiArai | 1:9011c83e4178 | 138 | while(true) { |
kenjiArai | 1:9011c83e4178 | 139 | // allow notifications from Server(Peripheral) |
kenjiArai | 1:9011c83e4178 | 140 | if (foundUartRXCharacteristic && |
kenjiArai | 1:9011c83e4178 | 141 | !ble_uart.gattClient().isServiceDiscoveryActive()) { |
kenjiArai | 1:9011c83e4178 | 142 | // need to do the following only once |
kenjiArai | 1:9011c83e4178 | 143 | foundUartRXCharacteristic = false; |
kenjiArai | 1:9011c83e4178 | 144 | uint16_t value = BLE_HVX_NOTIFICATION; |
kenjiArai | 1:9011c83e4178 | 145 | ble_uart.gattClient().write( |
kenjiArai | 1:9011c83e4178 | 146 | GattClient::GATT_OP_WRITE_REQ, |
kenjiArai | 1:9011c83e4178 | 147 | connectionHandle, |
kenjiArai | 1:9011c83e4178 | 148 | uartRXCharacteristic.getValueHandle() + 1, |
kenjiArai | 1:9011c83e4178 | 149 | sizeof(uint16_t), |
kenjiArai | 1:9011c83e4178 | 150 | reinterpret_cast<const uint8_t *>(&value) |
kenjiArai | 1:9011c83e4178 | 151 | ); |
kenjiArai | 1:9011c83e4178 | 152 | } |
kenjiArai | 1:9011c83e4178 | 153 | if (received_uart_dat == true) { |
kenjiArai | 1:9011c83e4178 | 154 | received_uart_dat = false; |
kenjiArai | 1:9011c83e4178 | 155 | for(int i = 0; i < uart_bf_len; i++) { |
kenjiArai | 1:9011c83e4178 | 156 | //pc.printf("%c", uart_buffer[i]); |
kenjiArai | 1:9011c83e4178 | 157 | pc.putc(uart_buffer[i]); |
kenjiArai | 1:9011c83e4178 | 158 | } |
kenjiArai | 1:9011c83e4178 | 159 | } |
kenjiArai | 1:9011c83e4178 | 160 | ble_uart.waitForEvent(); |
kenjiArai | 1:9011c83e4178 | 161 | } |
kenjiArai | 1:9011c83e4178 | 162 | } |
kenjiArai | 1:9011c83e4178 | 163 | |
kenjiArai | 1:9011c83e4178 | 164 | void periodicCallback(void) |
kenjiArai | 1:9011c83e4178 | 165 | { |
kenjiArai | 1:9011c83e4178 | 166 | // Do blinky on alivenessLED to indicate system aliveness |
kenjiArai | 1:9011c83e4178 | 167 | alivenessLED = !alivenessLED; |
kenjiArai | 1:9011c83e4178 | 168 | if (connected2server) { |
kenjiArai | 1:9011c83e4178 | 169 | connectedLED = 1; |
kenjiArai | 1:9011c83e4178 | 170 | } else { |
kenjiArai | 1:9011c83e4178 | 171 | connectedLED = 0; |
kenjiArai | 1:9011c83e4178 | 172 | } |
kenjiArai | 1:9011c83e4178 | 173 | if (rx_isr_busy == true) { |
kenjiArai | 1:9011c83e4178 | 174 | rx_isr_busy = false; |
kenjiArai | 1:9011c83e4178 | 175 | } else { |
kenjiArai | 1:9011c83e4178 | 176 | tsk.signal_set(0x01); |
kenjiArai | 1:9011c83e4178 | 177 | } |
kenjiArai | 1:9011c83e4178 | 178 | } |
kenjiArai | 1:9011c83e4178 | 179 | |
kenjiArai | 1:9011c83e4178 | 180 | void serialRxCallback() |
kenjiArai | 1:9011c83e4178 | 181 | { |
kenjiArai | 1:9011c83e4178 | 182 | ser_bf.push(pc.getc()); |
kenjiArai | 1:9011c83e4178 | 183 | rx_isr_busy = true; |
kenjiArai | 1:9011c83e4178 | 184 | tsk.signal_set(0x01); |
kenjiArai | 1:9011c83e4178 | 185 | } |
kenjiArai | 1:9011c83e4178 | 186 | |
kenjiArai | 1:9011c83e4178 | 187 | void pc_ser_rx() |
kenjiArai | 1:9011c83e4178 | 188 | { |
kenjiArai | 1:9011c83e4178 | 189 | static uint8_t linebf_irq[BFSIZE]; |
kenjiArai | 1:9011c83e4178 | 190 | static volatile uint8_t linebf_irq_len = 0; |
kenjiArai | 1:9011c83e4178 | 191 | |
kenjiArai | 1:9011c83e4178 | 192 | while(true) { |
kenjiArai | 1:9011c83e4178 | 193 | Thread::signal_wait(0x01); |
kenjiArai | 1:9011c83e4178 | 194 | if (ser_bf.empty()) { |
kenjiArai | 1:9011c83e4178 | 195 | if (linebf_irq_len != 0) { |
kenjiArai | 1:9011c83e4178 | 196 | linebf_irq[linebf_irq_len] = 0; |
kenjiArai | 1:9011c83e4178 | 197 | adjust_line(linebf_irq); |
kenjiArai | 1:9011c83e4178 | 198 | linebf_irq_len = 0; |
kenjiArai | 1:9011c83e4178 | 199 | uartTXCharacteristic.write(NUM_ONCE, linebf_irq); |
kenjiArai | 1:9011c83e4178 | 200 | } |
kenjiArai | 1:9011c83e4178 | 201 | } |
kenjiArai | 1:9011c83e4178 | 202 | while(!ser_bf.empty()) { |
kenjiArai | 1:9011c83e4178 | 203 | char c; |
kenjiArai | 1:9011c83e4178 | 204 | ser_bf.pop(c); |
kenjiArai | 1:9011c83e4178 | 205 | if (c == '\b') { |
kenjiArai | 1:9011c83e4178 | 206 | linebf_irq_len--; |
kenjiArai | 1:9011c83e4178 | 207 | pc.putc(c); |
kenjiArai | 1:9011c83e4178 | 208 | pc.putc(' '); |
kenjiArai | 1:9011c83e4178 | 209 | pc.putc(c); |
kenjiArai | 1:9011c83e4178 | 210 | } else if ((c >= ' ') || (c == '\r') || (c == '\n')) { |
kenjiArai | 1:9011c83e4178 | 211 | bool overflow = false; |
kenjiArai | 1:9011c83e4178 | 212 | if ((c == '\r') || (c == '\n')) { |
kenjiArai | 1:9011c83e4178 | 213 | if (linebf_irq_len == NUM_ONCE - 1) { // remain only 1 buffer |
kenjiArai | 1:9011c83e4178 | 214 | overflow = true; |
kenjiArai | 1:9011c83e4178 | 215 | linebf_irq[linebf_irq_len++] = '\r'; |
kenjiArai | 1:9011c83e4178 | 216 | pc.putc('\r'); |
kenjiArai | 1:9011c83e4178 | 217 | } else { |
kenjiArai | 1:9011c83e4178 | 218 | overflow = false; |
kenjiArai | 1:9011c83e4178 | 219 | linebf_irq[linebf_irq_len++] = '\r'; |
kenjiArai | 1:9011c83e4178 | 220 | linebf_irq[linebf_irq_len++] = '\n'; |
kenjiArai | 1:9011c83e4178 | 221 | pc.printf("\r\n"); |
kenjiArai | 1:9011c83e4178 | 222 | } |
kenjiArai | 1:9011c83e4178 | 223 | } else { |
kenjiArai | 1:9011c83e4178 | 224 | linebf_irq[linebf_irq_len++] = c; |
kenjiArai | 1:9011c83e4178 | 225 | pc.putc(c); |
kenjiArai | 1:9011c83e4178 | 226 | } |
kenjiArai | 1:9011c83e4178 | 227 | if (linebf_irq_len >= NUM_ONCE ) { |
kenjiArai | 1:9011c83e4178 | 228 | linebf_irq[linebf_irq_len] = 0; |
kenjiArai | 1:9011c83e4178 | 229 | uartTXCharacteristic.write(linebf_irq_len, linebf_irq); |
kenjiArai | 1:9011c83e4178 | 230 | linebf_irq_len = 0; |
kenjiArai | 1:9011c83e4178 | 231 | if (overflow == true) { |
kenjiArai | 1:9011c83e4178 | 232 | overflow = false; |
kenjiArai | 1:9011c83e4178 | 233 | linebf_irq[linebf_irq_len++] = '\n'; |
kenjiArai | 1:9011c83e4178 | 234 | pc.putc('\n'); |
kenjiArai | 1:9011c83e4178 | 235 | } |
kenjiArai | 1:9011c83e4178 | 236 | } |
kenjiArai | 1:9011c83e4178 | 237 | } |
kenjiArai | 1:9011c83e4178 | 238 | } |
kenjiArai | 1:9011c83e4178 | 239 | } |
kenjiArai | 1:9011c83e4178 | 240 | } |
kenjiArai | 1:9011c83e4178 | 241 | |
kenjiArai | 1:9011c83e4178 | 242 | void adjust_line(uint8_t *bf) |
kenjiArai | 1:9011c83e4178 | 243 | { |
kenjiArai | 1:9011c83e4178 | 244 | uint8_t i, c; |
kenjiArai | 1:9011c83e4178 | 245 | |
kenjiArai | 1:9011c83e4178 | 246 | for (i = 0; i <NUM_ONCE; bf++, i++) { |
kenjiArai | 1:9011c83e4178 | 247 | c = *bf; |
kenjiArai | 1:9011c83e4178 | 248 | if (c == 0) { |
kenjiArai | 1:9011c83e4178 | 249 | break; |
kenjiArai | 1:9011c83e4178 | 250 | } |
kenjiArai | 1:9011c83e4178 | 251 | } |
kenjiArai | 1:9011c83e4178 | 252 | for (; i < NUM_ONCE; bf++, i++) { |
kenjiArai | 1:9011c83e4178 | 253 | *bf = 0x11; |
kenjiArai | 1:9011c83e4178 | 254 | } |
kenjiArai | 1:9011c83e4178 | 255 | *(bf + 1) = 0; |
kenjiArai | 1:9011c83e4178 | 256 | } |
kenjiArai | 1:9011c83e4178 | 257 | |
kenjiArai | 1:9011c83e4178 | 258 | void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params) |
kenjiArai | 1:9011c83e4178 | 259 | { |
kenjiArai | 1:9011c83e4178 | 260 | DBG( |
kenjiArai | 1:9011c83e4178 | 261 | "received HVX callback for handle %u; type %s\r\r\n", |
kenjiArai | 1:9011c83e4178 | 262 | params->handle, |
kenjiArai | 1:9011c83e4178 | 263 | (params->type == BLE_HVX_NOTIFICATION) ? "notification" : "indication" |
kenjiArai | 1:9011c83e4178 | 264 | ); |
kenjiArai | 1:9011c83e4178 | 265 | if (params->type == BLE_HVX_NOTIFICATION) { |
kenjiArai | 1:9011c83e4178 | 266 | if ((params->handle |
kenjiArai | 1:9011c83e4178 | 267 | == uartRXCharacteristic.getValueHandle()) && (params->len > 0)) { |
kenjiArai | 1:9011c83e4178 | 268 | uart_bf_len = params->len; |
kenjiArai | 1:9011c83e4178 | 269 | strcpy((char *)uart_buffer, (char *)params->data); |
kenjiArai | 1:9011c83e4178 | 270 | received_uart_dat = true; |
kenjiArai | 1:9011c83e4178 | 271 | } |
kenjiArai | 1:9011c83e4178 | 272 | } |
kenjiArai | 1:9011c83e4178 | 273 | } |
kenjiArai | 1:9011c83e4178 | 274 | |
kenjiArai | 1:9011c83e4178 | 275 | #ifdef USE_MAC |
kenjiArai | 1:9011c83e4178 | 276 | |
kenjiArai | 1:9011c83e4178 | 277 | bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2) |
kenjiArai | 1:9011c83e4178 | 278 | { |
kenjiArai | 1:9011c83e4178 | 279 | DBG("Address: "); |
kenjiArai | 1:9011c83e4178 | 280 | for (int i = 0; i < 6; i++) { |
kenjiArai | 1:9011c83e4178 | 281 | DBG("0x%02x ", mac_1[i]); |
kenjiArai | 1:9011c83e4178 | 282 | } |
kenjiArai | 1:9011c83e4178 | 283 | DBG("\r\n"); |
kenjiArai | 1:9011c83e4178 | 284 | for (int i = 0; i < 6; i++) { |
kenjiArai | 1:9011c83e4178 | 285 | if (mac_1[i] != mac_2[i]) { |
kenjiArai | 1:9011c83e4178 | 286 | DBG("0x%02x != 0x%02x at %d\r\n", mac_1[i], mac_2[i], i); |
kenjiArai | 1:9011c83e4178 | 287 | return false; |
kenjiArai | 1:9011c83e4178 | 288 | } else { |
kenjiArai | 1:9011c83e4178 | 289 | DBG("0x%02x == 0x%02x at %d\r\n", mac_1[i], mac_2[i], i); |
kenjiArai | 1:9011c83e4178 | 290 | } |
kenjiArai | 1:9011c83e4178 | 291 | } |
kenjiArai | 1:9011c83e4178 | 292 | return true; |
kenjiArai | 1:9011c83e4178 | 293 | } |
kenjiArai | 1:9011c83e4178 | 294 | |
kenjiArai | 1:9011c83e4178 | 295 | int get_board_index(const Gap::Address_t mac) |
kenjiArai | 1:9011c83e4178 | 296 | { |
kenjiArai | 1:9011c83e4178 | 297 | if (mac_equals(mac, mac_board_0)) { |
kenjiArai | 1:9011c83e4178 | 298 | return 0; |
kenjiArai | 1:9011c83e4178 | 299 | } |
kenjiArai | 1:9011c83e4178 | 300 | if (mac_equals(mac, mac_board_1)) { |
kenjiArai | 1:9011c83e4178 | 301 | return 1; |
kenjiArai | 1:9011c83e4178 | 302 | } |
kenjiArai | 1:9011c83e4178 | 303 | if (mac_equals(mac, mac_board_2)) { |
kenjiArai | 1:9011c83e4178 | 304 | return 2; |
kenjiArai | 1:9011c83e4178 | 305 | } |
kenjiArai | 1:9011c83e4178 | 306 | if (mac_equals(mac, mac_board_3)) { |
kenjiArai | 1:9011c83e4178 | 307 | return 3; |
kenjiArai | 1:9011c83e4178 | 308 | } |
kenjiArai | 1:9011c83e4178 | 309 | if (mac_equals(mac, mac_board_4)) { |
kenjiArai | 1:9011c83e4178 | 310 | return 4; |
kenjiArai | 1:9011c83e4178 | 311 | } |
kenjiArai | 1:9011c83e4178 | 312 | return -1; |
kenjiArai | 1:9011c83e4178 | 313 | } |
kenjiArai | 1:9011c83e4178 | 314 | |
kenjiArai | 1:9011c83e4178 | 315 | // Client(Central) role ******************************************************** |
kenjiArai | 1:9011c83e4178 | 316 | void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) |
kenjiArai | 1:9011c83e4178 | 317 | { |
kenjiArai | 1:9011c83e4178 | 318 | // connections |
kenjiArai | 1:9011c83e4178 | 319 | int peer_board_index = get_board_index(params->peerAddr); |
kenjiArai | 1:9011c83e4178 | 320 | if (peer_board_index != -1) { |
kenjiArai | 1:9011c83e4178 | 321 | pc.printf(""); |
kenjiArai | 1:9011c83e4178 | 322 | pc.printf( |
kenjiArai | 1:9011c83e4178 | 323 | "adv peerAddr [%02x %02x %02x %02x %02x %02x]\r\n", |
kenjiArai | 1:9011c83e4178 | 324 | params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], |
kenjiArai | 1:9011c83e4178 | 325 | params->peerAddr[2], params->peerAddr[1], params->peerAddr[0] |
kenjiArai | 1:9011c83e4178 | 326 | ); |
kenjiArai | 1:9011c83e4178 | 327 | pc.printf( |
kenjiArai | 1:9011c83e4178 | 328 | "rssi=%+4d, isScanResponse %u, AdvertisementType %u\r\n", |
kenjiArai | 1:9011c83e4178 | 329 | params->rssi, params->isScanResponse, params->type |
kenjiArai | 1:9011c83e4178 | 330 | ); |
kenjiArai | 1:9011c83e4178 | 331 | ble_uart.gap().connect( |
kenjiArai | 1:9011c83e4178 | 332 | params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL); |
kenjiArai | 1:9011c83e4178 | 333 | } |
kenjiArai | 1:9011c83e4178 | 334 | } |
kenjiArai | 1:9011c83e4178 | 335 | |
kenjiArai | 1:9011c83e4178 | 336 | #else |
kenjiArai | 1:9011c83e4178 | 337 | |
kenjiArai | 1:9011c83e4178 | 338 | // Client(Central) role ******************************************************** |
kenjiArai | 1:9011c83e4178 | 339 | void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) |
kenjiArai | 1:9011c83e4178 | 340 | { |
kenjiArai | 1:9011c83e4178 | 341 | bool name_match = false; |
kenjiArai | 1:9011c83e4178 | 342 | |
kenjiArai | 1:9011c83e4178 | 343 | // parse the advertising payload, looking for data type COMPLETE_LOCAL_NAME |
kenjiArai | 1:9011c83e4178 | 344 | // The advertising payload is a collection of key/value records where |
kenjiArai | 1:9011c83e4178 | 345 | // byte 0: length of the record excluding this byte |
kenjiArai | 1:9011c83e4178 | 346 | // byte 1: The key, it is the type of the data |
kenjiArai | 1:9011c83e4178 | 347 | // byte [2..N] The value. N is equal to byte0 - 1 |
kenjiArai | 1:9011c83e4178 | 348 | |
kenjiArai | 1:9011c83e4178 | 349 | for( uint8_t i = 0; i < params->advertisingDataLen; ++i) { |
kenjiArai | 1:9011c83e4178 | 350 | const uint8_t record_length = params->advertisingData[i]; |
kenjiArai | 1:9011c83e4178 | 351 | if (record_length == 0) { |
kenjiArai | 1:9011c83e4178 | 352 | continue; |
kenjiArai | 1:9011c83e4178 | 353 | } |
kenjiArai | 1:9011c83e4178 | 354 | const uint8_t type = params->advertisingData[i + 1]; |
kenjiArai | 1:9011c83e4178 | 355 | const uint8_t* value = params->advertisingData + i + 2; |
kenjiArai | 1:9011c83e4178 | 356 | const uint8_t value_length = record_length - 1; |
kenjiArai | 1:9011c83e4178 | 357 | |
kenjiArai | 1:9011c83e4178 | 358 | if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { |
kenjiArai | 1:9011c83e4178 | 359 | if ((value_length == sizeof(PEER_NAME)) |
kenjiArai | 1:9011c83e4178 | 360 | && (memcmp(value, PEER_NAME, value_length) == 0)) { |
kenjiArai | 1:9011c83e4178 | 361 | pc.printf( |
kenjiArai | 1:9011c83e4178 | 362 | "\r\nadv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, ", |
kenjiArai | 1:9011c83e4178 | 363 | params->peerAddr[5], params->peerAddr[4], |
kenjiArai | 1:9011c83e4178 | 364 | params->peerAddr[3], params->peerAddr[2], |
kenjiArai | 1:9011c83e4178 | 365 | params->peerAddr[1], params->peerAddr[0], |
kenjiArai | 1:9011c83e4178 | 366 | params->rssi |
kenjiArai | 1:9011c83e4178 | 367 | ); |
kenjiArai | 1:9011c83e4178 | 368 | pc.printf( |
kenjiArai | 1:9011c83e4178 | 369 | "isScanResponse %u, AdvertisementType %u\r\n", |
kenjiArai | 1:9011c83e4178 | 370 | params->isScanResponse, params->type |
kenjiArai | 1:9011c83e4178 | 371 | ); |
kenjiArai | 1:9011c83e4178 | 372 | name_match = true; |
kenjiArai | 1:9011c83e4178 | 373 | break; |
kenjiArai | 1:9011c83e4178 | 374 | } |
kenjiArai | 1:9011c83e4178 | 375 | } |
kenjiArai | 1:9011c83e4178 | 376 | i += record_length; |
kenjiArai | 1:9011c83e4178 | 377 | } |
kenjiArai | 1:9011c83e4178 | 378 | if( name_match != true ) { |
kenjiArai | 1:9011c83e4178 | 379 | return; |
kenjiArai | 1:9011c83e4178 | 380 | } |
kenjiArai | 1:9011c83e4178 | 381 | |
kenjiArai | 1:9011c83e4178 | 382 | pc.printf("Found device name : %s\r\n",PEER_NAME); |
kenjiArai | 1:9011c83e4178 | 383 | // connections |
kenjiArai | 1:9011c83e4178 | 384 | ble_uart.gap().connect(params->peerAddr, |
kenjiArai | 1:9011c83e4178 | 385 | Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL); |
kenjiArai | 1:9011c83e4178 | 386 | } |
kenjiArai | 1:9011c83e4178 | 387 | |
kenjiArai | 1:9011c83e4178 | 388 | #endif |
kenjiArai | 1:9011c83e4178 | 389 | |
kenjiArai | 1:9011c83e4178 | 390 | void serviceDiscoveryCallback(const DiscoveredService *service) |
kenjiArai | 1:9011c83e4178 | 391 | { |
kenjiArai | 1:9011c83e4178 | 392 | DBG("service found...\r\n"); |
kenjiArai | 1:9011c83e4178 | 393 | if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) { |
kenjiArai | 1:9011c83e4178 | 394 | DBG( |
kenjiArai | 1:9011c83e4178 | 395 | "Service UUID-%x attrs[%u %u]\r\n", |
kenjiArai | 1:9011c83e4178 | 396 | service->getUUID().getShortUUID(), |
kenjiArai | 1:9011c83e4178 | 397 | service->getStartHandle(), |
kenjiArai | 1:9011c83e4178 | 398 | service->getEndHandle() |
kenjiArai | 1:9011c83e4178 | 399 | ); |
kenjiArai | 1:9011c83e4178 | 400 | } else { |
kenjiArai | 1:9011c83e4178 | 401 | DBG("Service UUID-"); |
kenjiArai | 1:9011c83e4178 | 402 | const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID(); |
kenjiArai | 1:9011c83e4178 | 403 | for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { |
kenjiArai | 1:9011c83e4178 | 404 | DBG("%02x", longUUIDBytes[i]); |
kenjiArai | 1:9011c83e4178 | 405 | } |
kenjiArai | 1:9011c83e4178 | 406 | DBG(" attrs[%u %u]\r\n", |
kenjiArai | 1:9011c83e4178 | 407 | service->getStartHandle(), service->getEndHandle()); |
kenjiArai | 1:9011c83e4178 | 408 | } |
kenjiArai | 1:9011c83e4178 | 409 | } |
kenjiArai | 1:9011c83e4178 | 410 | |
kenjiArai | 1:9011c83e4178 | 411 | void characteristicDiscoveryCallback( |
kenjiArai | 1:9011c83e4178 | 412 | const DiscoveredCharacteristic *characteristicP) |
kenjiArai | 1:9011c83e4178 | 413 | { |
kenjiArai | 1:9011c83e4178 | 414 | DBG( |
kenjiArai | 1:9011c83e4178 | 415 | " C UUID-%x valueAttr[%u] props[%x]\r\n", |
kenjiArai | 1:9011c83e4178 | 416 | characteristicP->getUUID().getShortUUID(), |
kenjiArai | 1:9011c83e4178 | 417 | characteristicP->getValueHandle(), |
kenjiArai | 1:9011c83e4178 | 418 | (uint8_t)characteristicP->getProperties().broadcast() |
kenjiArai | 1:9011c83e4178 | 419 | ); |
kenjiArai | 1:9011c83e4178 | 420 | if (characteristicP->getUUID().getShortUUID() |
kenjiArai | 1:9011c83e4178 | 421 | == UARTServiceTXCharacteristicShortUUID) { |
kenjiArai | 1:9011c83e4178 | 422 | DBG("Sevice TX 0x%04x\r\n", UARTServiceTXCharacteristicShortUUID); |
kenjiArai | 1:9011c83e4178 | 423 | uartTXCharacteristic = *characteristicP; |
kenjiArai | 1:9011c83e4178 | 424 | connection_tx = true; |
kenjiArai | 1:9011c83e4178 | 425 | } else if (characteristicP->getUUID().getShortUUID() |
kenjiArai | 1:9011c83e4178 | 426 | == UARTServiceRXCharacteristicShortUUID) { |
kenjiArai | 1:9011c83e4178 | 427 | DBG("Sevice RX 0x%04x\r\n", UARTServiceRXCharacteristicShortUUID); |
kenjiArai | 1:9011c83e4178 | 428 | uartRXCharacteristic = *characteristicP; |
kenjiArai | 1:9011c83e4178 | 429 | foundUartRXCharacteristic = true; |
kenjiArai | 1:9011c83e4178 | 430 | connection_rx = true; |
kenjiArai | 1:9011c83e4178 | 431 | } |
kenjiArai | 1:9011c83e4178 | 432 | } |
kenjiArai | 1:9011c83e4178 | 433 | |
kenjiArai | 1:9011c83e4178 | 434 | void discoveryTerminationCallback(Gap::Handle_t connectionHandle) |
kenjiArai | 1:9011c83e4178 | 435 | { |
kenjiArai | 1:9011c83e4178 | 436 | DBG("terminated SD for handle=%u\r\n", connectionHandle); |
kenjiArai | 1:9011c83e4178 | 437 | } |
kenjiArai | 1:9011c83e4178 | 438 | |
kenjiArai | 1:9011c83e4178 | 439 | // Mixed role ****************************************************************** |
kenjiArai | 1:9011c83e4178 | 440 | void connectionCallback(const Gap::ConnectionCallbackParams_t *params) |
kenjiArai | 1:9011c83e4178 | 441 | { |
kenjiArai | 1:9011c83e4178 | 442 | if (params->role == Gap::CENTRAL) { |
kenjiArai | 1:9011c83e4178 | 443 | pc.printf("connected as Client(Central) (handle = %d)\r\n\r", |
kenjiArai | 1:9011c83e4178 | 444 | params->handle); |
kenjiArai | 1:9011c83e4178 | 445 | connected2server = true; |
kenjiArai | 1:9011c83e4178 | 446 | connectionHandle = params->handle; |
kenjiArai | 1:9011c83e4178 | 447 | ble_uart.gattClient().onServiceDiscoveryTermination( |
kenjiArai | 1:9011c83e4178 | 448 | discoveryTerminationCallback); |
kenjiArai | 1:9011c83e4178 | 449 | ble_uart.gattClient().launchServiceDiscovery( |
kenjiArai | 1:9011c83e4178 | 450 | params->handle, |
kenjiArai | 1:9011c83e4178 | 451 | serviceDiscoveryCallback, |
kenjiArai | 1:9011c83e4178 | 452 | characteristicDiscoveryCallback |
kenjiArai | 1:9011c83e4178 | 453 | ); |
kenjiArai | 1:9011c83e4178 | 454 | } |
kenjiArai | 1:9011c83e4178 | 455 | pc.printf( |
kenjiArai | 1:9011c83e4178 | 456 | "Client(Central/Myself) %02x:%02x:%02x:%02x:%02x:%02x\r\n", |
kenjiArai | 1:9011c83e4178 | 457 | params->ownAddr[5], params->ownAddr[4], params->ownAddr[3], |
kenjiArai | 1:9011c83e4178 | 458 | params->ownAddr[2], params->ownAddr[1], params->ownAddr[0] |
kenjiArai | 1:9011c83e4178 | 459 | ); |
kenjiArai | 1:9011c83e4178 | 460 | pc.printf( |
kenjiArai | 1:9011c83e4178 | 461 | "Connected Server(Peripheral) %02x:%02x:%02x:%02x:%02x:%02x\r\n", |
kenjiArai | 1:9011c83e4178 | 462 | params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], |
kenjiArai | 1:9011c83e4178 | 463 | params->peerAddr[2], params->peerAddr[1], params->peerAddr[0] |
kenjiArai | 1:9011c83e4178 | 464 | ); |
kenjiArai | 1:9011c83e4178 | 465 | } |
kenjiArai | 1:9011c83e4178 | 466 | |
kenjiArai | 1:9011c83e4178 | 467 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
kenjiArai | 1:9011c83e4178 | 468 | { |
kenjiArai | 1:9011c83e4178 | 469 | DBG("handle = %d ", params->handle); |
kenjiArai | 1:9011c83e4178 | 470 | pc.printf(" -> disconnected\r\n", params->handle); |
kenjiArai | 1:9011c83e4178 | 471 | connected2server = false; |
kenjiArai | 1:9011c83e4178 | 472 | // connection_1st = false; |
kenjiArai | 1:9011c83e4178 | 473 | connection_tx = false; |
kenjiArai | 1:9011c83e4178 | 474 | connection_rx = false; |
kenjiArai | 1:9011c83e4178 | 475 | if (params->handle == SOFT_DEVICE_FATHER_HANDLE) { |
kenjiArai | 1:9011c83e4178 | 476 | ble_uart.startAdvertising(); // restart advertising |
kenjiArai | 1:9011c83e4178 | 477 | } else { |
kenjiArai | 1:9011c83e4178 | 478 | ble_uart.gap().startScan(advertisementCallback);// restart scan |
kenjiArai | 1:9011c83e4178 | 479 | } |
kenjiArai | 1:9011c83e4178 | 480 | } |
kenjiArai | 1:9011c83e4178 | 481 | |
kenjiArai | 1:9011c83e4178 | 482 | #endif |