noboru koshinaka
/
BLE_Central_test
ver1.0
main.cpp@0:82eed72bc4e4, 2018-02-07 (annotated)
- Committer:
- noboruk
- Date:
- Wed Feb 07 19:54:56 2018 +0000
- Revision:
- 0:82eed72bc4e4
ver1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
noboruk | 0:82eed72bc4e4 | 1 | /* |
noboruk | 0:82eed72bc4e4 | 2 | * ------- BLE Central/Client UART function ----------------------------------- |
noboruk | 0:82eed72bc4e4 | 3 | * communicate with BLE_UART_Server program |
noboruk | 0:82eed72bc4e4 | 4 | * --- Tested on Switch Science mbed TY51822r3 --- |
noboruk | 0:82eed72bc4e4 | 5 | * |
noboruk | 0:82eed72bc4e4 | 6 | * Modified by Kenji Arai |
noboruk | 0:82eed72bc4e4 | 7 | * http://www.page.sannet.ne.jp/kenjia/index.html |
noboruk | 0:82eed72bc4e4 | 8 | * http://mbed.org/users/kenjiArai/ |
noboruk | 0:82eed72bc4e4 | 9 | * |
noboruk | 0:82eed72bc4e4 | 10 | * Started: April 8th, 2016 |
noboruk | 0:82eed72bc4e4 | 11 | * Revised: June 13th, 2016 |
noboruk | 0:82eed72bc4e4 | 12 | * Revised: October 22nd, 2017 Run on mbed-OS-5.6.2 |
noboruk | 0:82eed72bc4e4 | 13 | * |
noboruk | 0:82eed72bc4e4 | 14 | * Original program (see original.cpp file): |
noboruk | 0:82eed72bc4e4 | 15 | * S130 potential unstability case [closed] by Fabien Comte |
noboruk | 0:82eed72bc4e4 | 16 | * https://devzone.nordicsemi.com/question/49705/ |
noboruk | 0:82eed72bc4e4 | 17 | * s130-potential-unstability-case/ |
noboruk | 0:82eed72bc4e4 | 18 | * GitHub Q&A by Fabien COMTE |
noboruk | 0:82eed72bc4e4 | 19 | * https://github.com/ARMmbed/ble/issues/69 |
noboruk | 0:82eed72bc4e4 | 20 | * Tested Server Device: |
noboruk | 0:82eed72bc4e4 | 21 | * BLE_Uart_Server |
noboruk | 0:82eed72bc4e4 | 22 | * https://developer.mbed.org/users/kenjiArai/code/BLE_Uart_Server/ |
noboruk | 0:82eed72bc4e4 | 23 | */ |
noboruk | 0:82eed72bc4e4 | 24 | |
noboruk | 0:82eed72bc4e4 | 25 | // 2018/02/07 太陽誘電 EYSGCNZWY 使用の試作機向けに改造 |
noboruk | 0:82eed72bc4e4 | 26 | |
noboruk | 0:82eed72bc4e4 | 27 | |
noboruk | 0:82eed72bc4e4 | 28 | // Include -------------------------------------------------------------------- |
noboruk | 0:82eed72bc4e4 | 29 | #include "mbed.h" |
noboruk | 0:82eed72bc4e4 | 30 | #include "BLE.h" |
noboruk | 0:82eed72bc4e4 | 31 | #include "UARTService.h" |
noboruk | 0:82eed72bc4e4 | 32 | #include "ble/DiscoveredCharacteristic.h" |
noboruk | 0:82eed72bc4e4 | 33 | #include "ble/DiscoveredService.h" |
noboruk | 0:82eed72bc4e4 | 34 | #include "RingBuffer.h" |
noboruk | 0:82eed72bc4e4 | 35 | |
noboruk | 0:82eed72bc4e4 | 36 | // Definition ----------------------------------------------------------------- |
noboruk | 0:82eed72bc4e4 | 37 | #define NUM_ONCE 20 |
noboruk | 0:82eed72bc4e4 | 38 | #define BFSIZE (NUM_ONCE+4) |
noboruk | 0:82eed72bc4e4 | 39 | |
noboruk | 0:82eed72bc4e4 | 40 | //#define USE_DEBUG_MODE |
noboruk | 0:82eed72bc4e4 | 41 | #ifdef USE_DEBUG_MODE |
noboruk | 0:82eed72bc4e4 | 42 | #define DBG(...) { pc.printf(__VA_ARGS__); } |
noboruk | 0:82eed72bc4e4 | 43 | #else |
noboruk | 0:82eed72bc4e4 | 44 | #define DBG(...) |
noboruk | 0:82eed72bc4e4 | 45 | #endif |
noboruk | 0:82eed72bc4e4 | 46 | |
noboruk | 0:82eed72bc4e4 | 47 | #define SOFT_DEVICE_FATHER_HANDLE 3 |
noboruk | 0:82eed72bc4e4 | 48 | |
noboruk | 0:82eed72bc4e4 | 49 | #define LED1_PIN P0_25 |
noboruk | 0:82eed72bc4e4 | 50 | #define LED2_PIN P0_23 |
noboruk | 0:82eed72bc4e4 | 51 | #define LED3_PIN P0_21 |
noboruk | 0:82eed72bc4e4 | 52 | #define EXT_OUT_PIN P0_9 |
noboruk | 0:82eed72bc4e4 | 53 | #define ROM_CS_PIN P0_12 |
noboruk | 0:82eed72bc4e4 | 54 | #define ROM_SCK_PIN P0_13 |
noboruk | 0:82eed72bc4e4 | 55 | #define ROM_SDI_PIN P0_15 |
noboruk | 0:82eed72bc4e4 | 56 | |
noboruk | 0:82eed72bc4e4 | 57 | // Object --------------------------------------------------------------------- |
noboruk | 0:82eed72bc4e4 | 58 | DigitalOut alivenessLED(LED1_PIN,1); |
noboruk | 0:82eed72bc4e4 | 59 | DigitalOut connectedLED(LED2_PIN,1); |
noboruk | 0:82eed72bc4e4 | 60 | DigitalOut out_led(LED3_PIN,1); |
noboruk | 0:82eed72bc4e4 | 61 | DigitalOut out_oc(EXT_OUT_PIN,0); //オープンコレクタ出力 |
noboruk | 0:82eed72bc4e4 | 62 | // |
noboruk | 0:82eed72bc4e4 | 63 | // UARTの端子ははEEPROMの端子を流用 |
noboruk | 0:82eed72bc4e4 | 64 | DigitalOut dummy_cs(ROM_CS_PIN,1); //Disable Chip |
noboruk | 0:82eed72bc4e4 | 65 | Serial pc(ROM_SDI_PIN,ROM_SCK_PIN, 19200); //SDI=TXD,SCK=RXD |
noboruk | 0:82eed72bc4e4 | 66 | |
noboruk | 0:82eed72bc4e4 | 67 | // Object |
noboruk | 0:82eed72bc4e4 | 68 | BLE ble; |
noboruk | 0:82eed72bc4e4 | 69 | Ticker ticker; |
noboruk | 0:82eed72bc4e4 | 70 | Ticker out_port_ticker; |
noboruk | 0:82eed72bc4e4 | 71 | RingBuffer ser_bf(1536); |
noboruk | 0:82eed72bc4e4 | 72 | Thread tsk; |
noboruk | 0:82eed72bc4e4 | 73 | |
noboruk | 0:82eed72bc4e4 | 74 | // ROM / Constant data -------------------------------------------------------- |
noboruk | 0:82eed72bc4e4 | 75 | //#warning "You need to modify below value based on your board." |
noboruk | 0:82eed72bc4e4 | 76 | //const Gap::Address_t mac_board_0 = {0xae,0x2f,0x0d,0x6b,0x49,0xea}; |
noboruk | 0:82eed72bc4e4 | 77 | // |
noboruk | 0:82eed72bc4e4 | 78 | const char PEER_NAME[] = "UART_S"; |
noboruk | 0:82eed72bc4e4 | 79 | // |
noboruk | 0:82eed72bc4e4 | 80 | // RAM ------------------------------------------------------------------------ |
noboruk | 0:82eed72bc4e4 | 81 | Gap::Handle_t connectionHandle = 0xFFFF; |
noboruk | 0:82eed72bc4e4 | 82 | DiscoveredCharacteristic uartTXCharacteristic; |
noboruk | 0:82eed72bc4e4 | 83 | DiscoveredCharacteristic uartRXCharacteristic; |
noboruk | 0:82eed72bc4e4 | 84 | bool foundUartRXCharacteristic = false; |
noboruk | 0:82eed72bc4e4 | 85 | bool connected2server = false; |
noboruk | 0:82eed72bc4e4 | 86 | bool connection_tx = false; |
noboruk | 0:82eed72bc4e4 | 87 | bool connection_rx = false; |
noboruk | 0:82eed72bc4e4 | 88 | UARTService * uartServicePtr = NULL; |
noboruk | 0:82eed72bc4e4 | 89 | Gap::Address_t my_mac; |
noboruk | 0:82eed72bc4e4 | 90 | int my_board_index = -1; |
noboruk | 0:82eed72bc4e4 | 91 | bool received_uart_dat = false; |
noboruk | 0:82eed72bc4e4 | 92 | int8_t uart_buffer[BFSIZE]; |
noboruk | 0:82eed72bc4e4 | 93 | uint8_t uart_bf_len; |
noboruk | 0:82eed72bc4e4 | 94 | volatile bool rx_isr_busy = false; |
noboruk | 0:82eed72bc4e4 | 95 | // |
noboruk | 0:82eed72bc4e4 | 96 | bool out_port_flag = false; |
noboruk | 0:82eed72bc4e4 | 97 | |
noboruk | 0:82eed72bc4e4 | 98 | // Function prototypes -------------------------------------------------------- |
noboruk | 0:82eed72bc4e4 | 99 | // BLE |
noboruk | 0:82eed72bc4e4 | 100 | void advertisementCallback(const Gap::AdvertisementCallbackParams_t *); |
noboruk | 0:82eed72bc4e4 | 101 | void serviceDiscoveryCallback(const DiscoveredService *); |
noboruk | 0:82eed72bc4e4 | 102 | void characteristicDiscoveryCallback(const DiscoveredCharacteristic *); |
noboruk | 0:82eed72bc4e4 | 103 | void discoveryTerminationCallback(Gap::Handle_t ); |
noboruk | 0:82eed72bc4e4 | 104 | void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *); |
noboruk | 0:82eed72bc4e4 | 105 | void connectionCallback(const Gap::ConnectionCallbackParams_t *); |
noboruk | 0:82eed72bc4e4 | 106 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *); |
noboruk | 0:82eed72bc4e4 | 107 | // |
noboruk | 0:82eed72bc4e4 | 108 | // Interrupt related |
noboruk | 0:82eed72bc4e4 | 109 | void periodicCallback(void); |
noboruk | 0:82eed72bc4e4 | 110 | void serialRxCallback(void); |
noboruk | 0:82eed72bc4e4 | 111 | void out_port_ticker_Callback(void); |
noboruk | 0:82eed72bc4e4 | 112 | // serial receiving |
noboruk | 0:82eed72bc4e4 | 113 | void pc_ser_rx(void); |
noboruk | 0:82eed72bc4e4 | 114 | void preparation_sending_data(void); |
noboruk | 0:82eed72bc4e4 | 115 | // Pre-check |
noboruk | 0:82eed72bc4e4 | 116 | void adjust_line(uint8_t *); |
noboruk | 0:82eed72bc4e4 | 117 | |
noboruk | 0:82eed72bc4e4 | 118 | //------------------------------------------------------------------------------ |
noboruk | 0:82eed72bc4e4 | 119 | // Control Program |
noboruk | 0:82eed72bc4e4 | 120 | //------------------------------------------------------------------------------ |
noboruk | 0:82eed72bc4e4 | 121 | int main(void) |
noboruk | 0:82eed72bc4e4 | 122 | { |
noboruk | 0:82eed72bc4e4 | 123 | dummy_cs = 1; |
noboruk | 0:82eed72bc4e4 | 124 | out_oc = 0; |
noboruk | 0:82eed72bc4e4 | 125 | alivenessLED = 1; |
noboruk | 0:82eed72bc4e4 | 126 | connectedLED = 1; |
noboruk | 0:82eed72bc4e4 | 127 | out_led = 1; |
noboruk | 0:82eed72bc4e4 | 128 | |
noboruk | 0:82eed72bc4e4 | 129 | pc.attach(&serialRxCallback, Serial::RxIrq); |
noboruk | 0:82eed72bc4e4 | 130 | ticker.attach(periodicCallback, 1); |
noboruk | 0:82eed72bc4e4 | 131 | tsk.start(pc_ser_rx); |
noboruk | 0:82eed72bc4e4 | 132 | |
noboruk | 0:82eed72bc4e4 | 133 | // clear terminal output |
noboruk | 0:82eed72bc4e4 | 134 | for (int k = 0; k < 5; k++) { pc.printf("\r\n");} |
noboruk | 0:82eed72bc4e4 | 135 | |
noboruk | 0:82eed72bc4e4 | 136 | // opening message |
noboruk | 0:82eed72bc4e4 | 137 | pc.printf("UART Communication / Central side\r\n"); |
noboruk | 0:82eed72bc4e4 | 138 | pc.printf(" need Peripheral module (run BLE_Peripheral_EYSGCNZWY program)\r\n"); |
noboruk | 0:82eed72bc4e4 | 139 | |
noboruk | 0:82eed72bc4e4 | 140 | // Mixed role ************************************************************** |
noboruk | 0:82eed72bc4e4 | 141 | ble.init(); |
noboruk | 0:82eed72bc4e4 | 142 | ble.gap().onConnection(connectionCallback); |
noboruk | 0:82eed72bc4e4 | 143 | ble.gap().onDisconnection(disconnectionCallback); |
noboruk | 0:82eed72bc4e4 | 144 | |
noboruk | 0:82eed72bc4e4 | 145 | // Client(Central) role **************************************************** |
noboruk | 0:82eed72bc4e4 | 146 | ble.gattClient().onHVX(onReceivedDataFromDeviceCallback); |
noboruk | 0:82eed72bc4e4 | 147 | ble.gap().setScanParams(500, 450); |
noboruk | 0:82eed72bc4e4 | 148 | ble.gap().startScan(advertisementCallback); |
noboruk | 0:82eed72bc4e4 | 149 | |
noboruk | 0:82eed72bc4e4 | 150 | while(true) |
noboruk | 0:82eed72bc4e4 | 151 | { |
noboruk | 0:82eed72bc4e4 | 152 | // allow notifications from Peripheral |
noboruk | 0:82eed72bc4e4 | 153 | if (foundUartRXCharacteristic && |
noboruk | 0:82eed72bc4e4 | 154 | !ble.gattClient().isServiceDiscoveryActive()) |
noboruk | 0:82eed72bc4e4 | 155 | { |
noboruk | 0:82eed72bc4e4 | 156 | // need to do the following only once |
noboruk | 0:82eed72bc4e4 | 157 | foundUartRXCharacteristic = false; |
noboruk | 0:82eed72bc4e4 | 158 | uint16_t value = BLE_HVX_NOTIFICATION; |
noboruk | 0:82eed72bc4e4 | 159 | ble.gattClient().write( |
noboruk | 0:82eed72bc4e4 | 160 | GattClient::GATT_OP_WRITE_REQ, |
noboruk | 0:82eed72bc4e4 | 161 | connectionHandle, |
noboruk | 0:82eed72bc4e4 | 162 | uartRXCharacteristic.getValueHandle() + 1, |
noboruk | 0:82eed72bc4e4 | 163 | sizeof(uint16_t), |
noboruk | 0:82eed72bc4e4 | 164 | reinterpret_cast<const uint8_t *>(&value) |
noboruk | 0:82eed72bc4e4 | 165 | ); |
noboruk | 0:82eed72bc4e4 | 166 | } |
noboruk | 0:82eed72bc4e4 | 167 | if (received_uart_dat == true){ |
noboruk | 0:82eed72bc4e4 | 168 | received_uart_dat = false; |
noboruk | 0:82eed72bc4e4 | 169 | for(int i = 0; i < uart_bf_len; i++){ |
noboruk | 0:82eed72bc4e4 | 170 | //pc.printf("%c", uart_buffer[i]); |
noboruk | 0:82eed72bc4e4 | 171 | pc.putc(uart_buffer[i]); |
noboruk | 0:82eed72bc4e4 | 172 | } |
noboruk | 0:82eed72bc4e4 | 173 | } |
noboruk | 0:82eed72bc4e4 | 174 | ble.waitForEvent(); |
noboruk | 0:82eed72bc4e4 | 175 | } |
noboruk | 0:82eed72bc4e4 | 176 | } |
noboruk | 0:82eed72bc4e4 | 177 | |
noboruk | 0:82eed72bc4e4 | 178 | |
noboruk | 0:82eed72bc4e4 | 179 | void periodicCallback(void) |
noboruk | 0:82eed72bc4e4 | 180 | { |
noboruk | 0:82eed72bc4e4 | 181 | // Do blinky on alivenessLED to indicate system aliveness |
noboruk | 0:82eed72bc4e4 | 182 | alivenessLED = !alivenessLED; |
noboruk | 0:82eed72bc4e4 | 183 | if (connected2server){ |
noboruk | 0:82eed72bc4e4 | 184 | connectedLED = 0; |
noboruk | 0:82eed72bc4e4 | 185 | } else { |
noboruk | 0:82eed72bc4e4 | 186 | connectedLED = 1; |
noboruk | 0:82eed72bc4e4 | 187 | } |
noboruk | 0:82eed72bc4e4 | 188 | if (rx_isr_busy == true){ |
noboruk | 0:82eed72bc4e4 | 189 | rx_isr_busy = false; |
noboruk | 0:82eed72bc4e4 | 190 | } else { |
noboruk | 0:82eed72bc4e4 | 191 | tsk.signal_set(0x01); |
noboruk | 0:82eed72bc4e4 | 192 | } |
noboruk | 0:82eed72bc4e4 | 193 | } |
noboruk | 0:82eed72bc4e4 | 194 | |
noboruk | 0:82eed72bc4e4 | 195 | void out_port_ticker_Callback(void) |
noboruk | 0:82eed72bc4e4 | 196 | { |
noboruk | 0:82eed72bc4e4 | 197 | out_led = 1; |
noboruk | 0:82eed72bc4e4 | 198 | out_oc = 0; |
noboruk | 0:82eed72bc4e4 | 199 | out_port_ticker.detach(); // |
noboruk | 0:82eed72bc4e4 | 200 | } |
noboruk | 0:82eed72bc4e4 | 201 | |
noboruk | 0:82eed72bc4e4 | 202 | void serialRxCallback() |
noboruk | 0:82eed72bc4e4 | 203 | { |
noboruk | 0:82eed72bc4e4 | 204 | ser_bf.save(pc.getc()); |
noboruk | 0:82eed72bc4e4 | 205 | rx_isr_busy = true; |
noboruk | 0:82eed72bc4e4 | 206 | tsk.signal_set(0x01); |
noboruk | 0:82eed72bc4e4 | 207 | } |
noboruk | 0:82eed72bc4e4 | 208 | |
noboruk | 0:82eed72bc4e4 | 209 | void pc_ser_rx() |
noboruk | 0:82eed72bc4e4 | 210 | { |
noboruk | 0:82eed72bc4e4 | 211 | static uint8_t linebf_irq[BFSIZE]; |
noboruk | 0:82eed72bc4e4 | 212 | static volatile uint8_t linebf_irq_len = 0; |
noboruk | 0:82eed72bc4e4 | 213 | |
noboruk | 0:82eed72bc4e4 | 214 | while(true){ |
noboruk | 0:82eed72bc4e4 | 215 | Thread::signal_wait(0x01); |
noboruk | 0:82eed72bc4e4 | 216 | if (ser_bf.check() == 0){ |
noboruk | 0:82eed72bc4e4 | 217 | if (linebf_irq_len != 0){ |
noboruk | 0:82eed72bc4e4 | 218 | linebf_irq[linebf_irq_len] = 0; |
noboruk | 0:82eed72bc4e4 | 219 | adjust_line(linebf_irq); |
noboruk | 0:82eed72bc4e4 | 220 | linebf_irq_len = 0; |
noboruk | 0:82eed72bc4e4 | 221 | uartTXCharacteristic.write(NUM_ONCE, linebf_irq); |
noboruk | 0:82eed72bc4e4 | 222 | } |
noboruk | 0:82eed72bc4e4 | 223 | } |
noboruk | 0:82eed72bc4e4 | 224 | while(ser_bf.check() != 0){ |
noboruk | 0:82eed72bc4e4 | 225 | char c = ser_bf.read(); |
noboruk | 0:82eed72bc4e4 | 226 | if (c == '\b'){ |
noboruk | 0:82eed72bc4e4 | 227 | linebf_irq_len--; |
noboruk | 0:82eed72bc4e4 | 228 | pc.putc(c); |
noboruk | 0:82eed72bc4e4 | 229 | pc.putc(' '); |
noboruk | 0:82eed72bc4e4 | 230 | pc.putc(c); |
noboruk | 0:82eed72bc4e4 | 231 | } else if ((c >= ' ') || (c == '\r') || (c == '\n')){ |
noboruk | 0:82eed72bc4e4 | 232 | bool overflow = false; |
noboruk | 0:82eed72bc4e4 | 233 | if ((c == '\r') || (c == '\n')) { |
noboruk | 0:82eed72bc4e4 | 234 | if (linebf_irq_len == NUM_ONCE - 1){// remain only 1 buffer |
noboruk | 0:82eed72bc4e4 | 235 | overflow = true; |
noboruk | 0:82eed72bc4e4 | 236 | linebf_irq[linebf_irq_len++] = '\r'; |
noboruk | 0:82eed72bc4e4 | 237 | pc.putc('\r'); |
noboruk | 0:82eed72bc4e4 | 238 | } else { |
noboruk | 0:82eed72bc4e4 | 239 | overflow = false; |
noboruk | 0:82eed72bc4e4 | 240 | linebf_irq[linebf_irq_len++] = '\r'; |
noboruk | 0:82eed72bc4e4 | 241 | linebf_irq[linebf_irq_len++] = '\n'; |
noboruk | 0:82eed72bc4e4 | 242 | pc.printf("\r\n"); |
noboruk | 0:82eed72bc4e4 | 243 | } |
noboruk | 0:82eed72bc4e4 | 244 | } else { |
noboruk | 0:82eed72bc4e4 | 245 | linebf_irq[linebf_irq_len++] = c; |
noboruk | 0:82eed72bc4e4 | 246 | pc.putc(c); |
noboruk | 0:82eed72bc4e4 | 247 | } |
noboruk | 0:82eed72bc4e4 | 248 | if (linebf_irq_len >= NUM_ONCE ){ |
noboruk | 0:82eed72bc4e4 | 249 | linebf_irq[linebf_irq_len] = 0; |
noboruk | 0:82eed72bc4e4 | 250 | uartTXCharacteristic.write(linebf_irq_len, linebf_irq); |
noboruk | 0:82eed72bc4e4 | 251 | linebf_irq_len = 0; |
noboruk | 0:82eed72bc4e4 | 252 | if (overflow == true){ |
noboruk | 0:82eed72bc4e4 | 253 | overflow = false; |
noboruk | 0:82eed72bc4e4 | 254 | linebf_irq[linebf_irq_len++] = '\n'; |
noboruk | 0:82eed72bc4e4 | 255 | pc.putc('\n'); |
noboruk | 0:82eed72bc4e4 | 256 | } |
noboruk | 0:82eed72bc4e4 | 257 | } |
noboruk | 0:82eed72bc4e4 | 258 | } |
noboruk | 0:82eed72bc4e4 | 259 | } |
noboruk | 0:82eed72bc4e4 | 260 | } |
noboruk | 0:82eed72bc4e4 | 261 | } |
noboruk | 0:82eed72bc4e4 | 262 | |
noboruk | 0:82eed72bc4e4 | 263 | void adjust_line(uint8_t *bf) |
noboruk | 0:82eed72bc4e4 | 264 | { |
noboruk | 0:82eed72bc4e4 | 265 | uint8_t i, c; |
noboruk | 0:82eed72bc4e4 | 266 | |
noboruk | 0:82eed72bc4e4 | 267 | for (i = 0; i <NUM_ONCE; bf++, i++){ |
noboruk | 0:82eed72bc4e4 | 268 | c = *bf; |
noboruk | 0:82eed72bc4e4 | 269 | if (c == 0){ break;} |
noboruk | 0:82eed72bc4e4 | 270 | } |
noboruk | 0:82eed72bc4e4 | 271 | for (; i < NUM_ONCE; bf++, i++){ *bf = 0x11;} |
noboruk | 0:82eed72bc4e4 | 272 | *(bf + 1) = 0; |
noboruk | 0:82eed72bc4e4 | 273 | } |
noboruk | 0:82eed72bc4e4 | 274 | |
noboruk | 0:82eed72bc4e4 | 275 | void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params) |
noboruk | 0:82eed72bc4e4 | 276 | { |
noboruk | 0:82eed72bc4e4 | 277 | DBG( |
noboruk | 0:82eed72bc4e4 | 278 | "received HVX callback for handle %u; type %s\r\r\n", |
noboruk | 0:82eed72bc4e4 | 279 | params->handle, |
noboruk | 0:82eed72bc4e4 | 280 | (params->type == BLE_HVX_NOTIFICATION) ? "notification" : "indication" |
noboruk | 0:82eed72bc4e4 | 281 | ); |
noboruk | 0:82eed72bc4e4 | 282 | if (params->type == BLE_HVX_NOTIFICATION){ |
noboruk | 0:82eed72bc4e4 | 283 | if ((params->handle |
noboruk | 0:82eed72bc4e4 | 284 | == uartRXCharacteristic.getValueHandle()) && (params->len > 0)) |
noboruk | 0:82eed72bc4e4 | 285 | { |
noboruk | 0:82eed72bc4e4 | 286 | uart_bf_len = params->len; |
noboruk | 0:82eed72bc4e4 | 287 | strcpy((char *)uart_buffer, (char *)params->data); |
noboruk | 0:82eed72bc4e4 | 288 | received_uart_dat = true; |
noboruk | 0:82eed72bc4e4 | 289 | // 0.5s port ON |
noboruk | 0:82eed72bc4e4 | 290 | out_led = 0; |
noboruk | 0:82eed72bc4e4 | 291 | out_oc = 1; |
noboruk | 0:82eed72bc4e4 | 292 | out_port_ticker.attach(out_port_ticker_Callback, 0.5); |
noboruk | 0:82eed72bc4e4 | 293 | } |
noboruk | 0:82eed72bc4e4 | 294 | } |
noboruk | 0:82eed72bc4e4 | 295 | } |
noboruk | 0:82eed72bc4e4 | 296 | |
noboruk | 0:82eed72bc4e4 | 297 | |
noboruk | 0:82eed72bc4e4 | 298 | // Client(Central) role ******************************************************** |
noboruk | 0:82eed72bc4e4 | 299 | void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) |
noboruk | 0:82eed72bc4e4 | 300 | { |
noboruk | 0:82eed72bc4e4 | 301 | bool name_match = false; |
noboruk | 0:82eed72bc4e4 | 302 | |
noboruk | 0:82eed72bc4e4 | 303 | // parse the advertising payload, looking for data type COMPLETE_LOCAL_NAME |
noboruk | 0:82eed72bc4e4 | 304 | // The advertising payload is a collection of key/value records where |
noboruk | 0:82eed72bc4e4 | 305 | // byte 0: length of the record excluding this byte |
noboruk | 0:82eed72bc4e4 | 306 | // byte 1: The key, it is the type of the data |
noboruk | 0:82eed72bc4e4 | 307 | // byte [2..N] The value. N is equal to byte0 - 1 |
noboruk | 0:82eed72bc4e4 | 308 | |
noboruk | 0:82eed72bc4e4 | 309 | for( uint8_t i = 0; i < params->advertisingDataLen; ++i) |
noboruk | 0:82eed72bc4e4 | 310 | { |
noboruk | 0:82eed72bc4e4 | 311 | const uint8_t record_length = params->advertisingData[i]; |
noboruk | 0:82eed72bc4e4 | 312 | if (record_length == 0) |
noboruk | 0:82eed72bc4e4 | 313 | { |
noboruk | 0:82eed72bc4e4 | 314 | continue; |
noboruk | 0:82eed72bc4e4 | 315 | } |
noboruk | 0:82eed72bc4e4 | 316 | const uint8_t type = params->advertisingData[i + 1]; |
noboruk | 0:82eed72bc4e4 | 317 | const uint8_t* value = params->advertisingData + i + 2; |
noboruk | 0:82eed72bc4e4 | 318 | const uint8_t value_length = record_length - 1; |
noboruk | 0:82eed72bc4e4 | 319 | |
noboruk | 0:82eed72bc4e4 | 320 | if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) |
noboruk | 0:82eed72bc4e4 | 321 | { |
noboruk | 0:82eed72bc4e4 | 322 | if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) |
noboruk | 0:82eed72bc4e4 | 323 | { |
noboruk | 0:82eed72bc4e4 | 324 | pc.printf( |
noboruk | 0:82eed72bc4e4 | 325 | "\r\nadv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n", |
noboruk | 0:82eed72bc4e4 | 326 | params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], |
noboruk | 0:82eed72bc4e4 | 327 | params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type |
noboruk | 0:82eed72bc4e4 | 328 | ); |
noboruk | 0:82eed72bc4e4 | 329 | name_match = true; |
noboruk | 0:82eed72bc4e4 | 330 | break; |
noboruk | 0:82eed72bc4e4 | 331 | } |
noboruk | 0:82eed72bc4e4 | 332 | } |
noboruk | 0:82eed72bc4e4 | 333 | i += record_length; |
noboruk | 0:82eed72bc4e4 | 334 | } |
noboruk | 0:82eed72bc4e4 | 335 | if( name_match != true ){ return; } |
noboruk | 0:82eed72bc4e4 | 336 | |
noboruk | 0:82eed72bc4e4 | 337 | pc.printf("Found device : %s\r\n",PEER_NAME); |
noboruk | 0:82eed72bc4e4 | 338 | // connections |
noboruk | 0:82eed72bc4e4 | 339 | ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL); |
noboruk | 0:82eed72bc4e4 | 340 | |
noboruk | 0:82eed72bc4e4 | 341 | } |
noboruk | 0:82eed72bc4e4 | 342 | |
noboruk | 0:82eed72bc4e4 | 343 | void serviceDiscoveryCallback(const DiscoveredService *service) |
noboruk | 0:82eed72bc4e4 | 344 | { |
noboruk | 0:82eed72bc4e4 | 345 | DBG("service found...\r\n"); |
noboruk | 0:82eed72bc4e4 | 346 | if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT){ |
noboruk | 0:82eed72bc4e4 | 347 | DBG( |
noboruk | 0:82eed72bc4e4 | 348 | "Service UUID-%x attrs[%u %u]\r\n", |
noboruk | 0:82eed72bc4e4 | 349 | service->getUUID().getShortUUID(), |
noboruk | 0:82eed72bc4e4 | 350 | service->getStartHandle(), |
noboruk | 0:82eed72bc4e4 | 351 | service->getEndHandle() |
noboruk | 0:82eed72bc4e4 | 352 | ); |
noboruk | 0:82eed72bc4e4 | 353 | } else { |
noboruk | 0:82eed72bc4e4 | 354 | DBG("Service UUID-"); |
noboruk | 0:82eed72bc4e4 | 355 | const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID(); |
noboruk | 0:82eed72bc4e4 | 356 | for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { |
noboruk | 0:82eed72bc4e4 | 357 | DBG("%02x", longUUIDBytes[i]); |
noboruk | 0:82eed72bc4e4 | 358 | } |
noboruk | 0:82eed72bc4e4 | 359 | DBG(" attrs[%u %u]\r\n", |
noboruk | 0:82eed72bc4e4 | 360 | service->getStartHandle(), service->getEndHandle()); |
noboruk | 0:82eed72bc4e4 | 361 | } |
noboruk | 0:82eed72bc4e4 | 362 | } |
noboruk | 0:82eed72bc4e4 | 363 | |
noboruk | 0:82eed72bc4e4 | 364 | void characteristicDiscoveryCallback( |
noboruk | 0:82eed72bc4e4 | 365 | const DiscoveredCharacteristic *characteristicP) |
noboruk | 0:82eed72bc4e4 | 366 | { |
noboruk | 0:82eed72bc4e4 | 367 | DBG( |
noboruk | 0:82eed72bc4e4 | 368 | " C UUID-%x valueAttr[%u] props[%x]\r\n", |
noboruk | 0:82eed72bc4e4 | 369 | characteristicP->getUUID().getShortUUID(), |
noboruk | 0:82eed72bc4e4 | 370 | characteristicP->getValueHandle(), |
noboruk | 0:82eed72bc4e4 | 371 | (uint8_t)characteristicP->getProperties().broadcast() |
noboruk | 0:82eed72bc4e4 | 372 | ); |
noboruk | 0:82eed72bc4e4 | 373 | if (characteristicP->getUUID().getShortUUID() |
noboruk | 0:82eed72bc4e4 | 374 | == UARTServiceTXCharacteristicShortUUID) |
noboruk | 0:82eed72bc4e4 | 375 | { |
noboruk | 0:82eed72bc4e4 | 376 | DBG("Sevice TX 0x%04x\r\n", UARTServiceTXCharacteristicShortUUID); |
noboruk | 0:82eed72bc4e4 | 377 | uartTXCharacteristic = *characteristicP; |
noboruk | 0:82eed72bc4e4 | 378 | connection_tx = true; |
noboruk | 0:82eed72bc4e4 | 379 | } else if (characteristicP->getUUID().getShortUUID() |
noboruk | 0:82eed72bc4e4 | 380 | == UARTServiceRXCharacteristicShortUUID) |
noboruk | 0:82eed72bc4e4 | 381 | { |
noboruk | 0:82eed72bc4e4 | 382 | DBG("Sevice RX 0x%04x\r\n", UARTServiceRXCharacteristicShortUUID); |
noboruk | 0:82eed72bc4e4 | 383 | uartRXCharacteristic = *characteristicP; |
noboruk | 0:82eed72bc4e4 | 384 | foundUartRXCharacteristic = true; |
noboruk | 0:82eed72bc4e4 | 385 | connection_rx = true; |
noboruk | 0:82eed72bc4e4 | 386 | } |
noboruk | 0:82eed72bc4e4 | 387 | } |
noboruk | 0:82eed72bc4e4 | 388 | |
noboruk | 0:82eed72bc4e4 | 389 | void discoveryTerminationCallback(Gap::Handle_t connectionHandle) |
noboruk | 0:82eed72bc4e4 | 390 | { |
noboruk | 0:82eed72bc4e4 | 391 | DBG("terminated SD for handle=%u\r\n", connectionHandle); |
noboruk | 0:82eed72bc4e4 | 392 | } |
noboruk | 0:82eed72bc4e4 | 393 | |
noboruk | 0:82eed72bc4e4 | 394 | // Mixed role ****************************************************************** |
noboruk | 0:82eed72bc4e4 | 395 | void connectionCallback(const Gap::ConnectionCallbackParams_t *params) |
noboruk | 0:82eed72bc4e4 | 396 | { |
noboruk | 0:82eed72bc4e4 | 397 | if (params->role == Gap::CENTRAL) { |
noboruk | 0:82eed72bc4e4 | 398 | pc.printf("connected as Client(Central) (handle = %d)\r\n\r", |
noboruk | 0:82eed72bc4e4 | 399 | params->handle); |
noboruk | 0:82eed72bc4e4 | 400 | connected2server = true; |
noboruk | 0:82eed72bc4e4 | 401 | connectionHandle = params->handle; |
noboruk | 0:82eed72bc4e4 | 402 | ble.gattClient().onServiceDiscoveryTermination( |
noboruk | 0:82eed72bc4e4 | 403 | discoveryTerminationCallback); |
noboruk | 0:82eed72bc4e4 | 404 | ble.gattClient().launchServiceDiscovery( |
noboruk | 0:82eed72bc4e4 | 405 | params->handle, |
noboruk | 0:82eed72bc4e4 | 406 | serviceDiscoveryCallback, |
noboruk | 0:82eed72bc4e4 | 407 | characteristicDiscoveryCallback |
noboruk | 0:82eed72bc4e4 | 408 | ); |
noboruk | 0:82eed72bc4e4 | 409 | } |
noboruk | 0:82eed72bc4e4 | 410 | pc.printf( |
noboruk | 0:82eed72bc4e4 | 411 | "Client(Central/Myself) %02x:%02x:%02x:%02x:%02x:%02x\r\n", |
noboruk | 0:82eed72bc4e4 | 412 | params->ownAddr[5], params->ownAddr[4], params->ownAddr[3], |
noboruk | 0:82eed72bc4e4 | 413 | params->ownAddr[2], params->ownAddr[1], params->ownAddr[0] |
noboruk | 0:82eed72bc4e4 | 414 | ); |
noboruk | 0:82eed72bc4e4 | 415 | pc.printf( |
noboruk | 0:82eed72bc4e4 | 416 | "Connected Sever(peripheral) %02x:%02x:%02x:%02x:%02x:%02x\r\n", |
noboruk | 0:82eed72bc4e4 | 417 | params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], |
noboruk | 0:82eed72bc4e4 | 418 | params->peerAddr[2], params->peerAddr[1], params->peerAddr[0] |
noboruk | 0:82eed72bc4e4 | 419 | ); |
noboruk | 0:82eed72bc4e4 | 420 | } |
noboruk | 0:82eed72bc4e4 | 421 | |
noboruk | 0:82eed72bc4e4 | 422 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
noboruk | 0:82eed72bc4e4 | 423 | { |
noboruk | 0:82eed72bc4e4 | 424 | DBG("handle = %d ", params->handle); |
noboruk | 0:82eed72bc4e4 | 425 | pc.printf(" -> disconnected\r\n", params->handle); |
noboruk | 0:82eed72bc4e4 | 426 | connected2server = false; |
noboruk | 0:82eed72bc4e4 | 427 | // connection_1st = false; |
noboruk | 0:82eed72bc4e4 | 428 | connection_tx = false; |
noboruk | 0:82eed72bc4e4 | 429 | connection_rx = false; |
noboruk | 0:82eed72bc4e4 | 430 | if (params->handle == SOFT_DEVICE_FATHER_HANDLE) { |
noboruk | 0:82eed72bc4e4 | 431 | ble.startAdvertising(); // restart advertising |
noboruk | 0:82eed72bc4e4 | 432 | } else { |
noboruk | 0:82eed72bc4e4 | 433 | ble.gap().startScan(advertisementCallback); // restart scan |
noboruk | 0:82eed72bc4e4 | 434 | } |
noboruk | 0:82eed72bc4e4 | 435 | } |
noboruk | 0:82eed72bc4e4 | 436 | |
noboruk | 0:82eed72bc4e4 | 437 |