BLE Client UART function

Dependencies:   RingBuffer

This is a BLE Client (Central) program for nRF51.
You can communicate with mbed BLE using "BLE_Uart_Server" program as follows.
/users/kenjiArai/code/BLE_Uart_Server/
Please refer following my notebook.
/users/kenjiArai/notebook/ble-client-and-peripheral-using-switch-sience-ty51/#

Committer:
kenjiArai
Date:
Sun Feb 11 02:04:44 2018 +0000
Revision:
5:e90d7b6f83cb
Parent:
4:342b665fb826
use Mbed-os5 dedicated class "CircularBuffer"

Who changed what in which revision?

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