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:
Sat Apr 16 07:32:21 2016 +0000
Revision:
0:0ef6455cbb4d
Child:
1:f68a5e55a60e
BLE Client UART function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:0ef6455cbb4d 1 /*
kenjiArai 0:0ef6455cbb4d 2 * ------- BLE Client UART function --------------------------------
kenjiArai 0:0ef6455cbb4d 3 * --- Tested on Switch Science mbed TY51822r3 ---
kenjiArai 0:0ef6455cbb4d 4 *
kenjiArai 0:0ef6455cbb4d 5 * Modified by Kenji Arai
kenjiArai 0:0ef6455cbb4d 6 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 0:0ef6455cbb4d 7 * http://mbed.org/users/kenjiArai/
kenjiArai 0:0ef6455cbb4d 8 *
kenjiArai 0:0ef6455cbb4d 9 * Started: April 8th, 2016
kenjiArai 0:0ef6455cbb4d 10 * Revised: April 16th, 2016
kenjiArai 0:0ef6455cbb4d 11 *
kenjiArai 0:0ef6455cbb4d 12 * Original program (see original.cpp file):
kenjiArai 0:0ef6455cbb4d 13 * S130 potential unstability case [closed] by Fabien Comte
kenjiArai 0:0ef6455cbb4d 14 * https://devzone.nordicsemi.com/question/49705/s130-potential-unstability-case/
kenjiArai 0:0ef6455cbb4d 15 * GitHub Q&A by Fabien COMTE
kenjiArai 0:0ef6455cbb4d 16 * https://github.com/ARMmbed/ble/issues/69
kenjiArai 0:0ef6455cbb4d 17 * Tested Peripheral Device:
kenjiArai 0:0ef6455cbb4d 18 * BLE_Uart_Peripheral
kenjiArai 0:0ef6455cbb4d 19 * https://developer.mbed.org/users/kenjiArai/code/BLE_Uart_Peripheral/
kenjiArai 0:0ef6455cbb4d 20 *
kenjiArai 0:0ef6455cbb4d 21 */
kenjiArai 0:0ef6455cbb4d 22
kenjiArai 0:0ef6455cbb4d 23 // Include ---------------------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 24 #include "mbed.h"
kenjiArai 0:0ef6455cbb4d 25 #include "BLE.h"
kenjiArai 0:0ef6455cbb4d 26 #include "UARTService.h"
kenjiArai 0:0ef6455cbb4d 27 #include "ble/DiscoveredCharacteristic.h"
kenjiArai 0:0ef6455cbb4d 28 #include "ble/DiscoveredService.h"
kenjiArai 0:0ef6455cbb4d 29
kenjiArai 0:0ef6455cbb4d 30 // Definition ------------------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 31 #define NEED_CONSOLE_OUTPUT 0
kenjiArai 0:0ef6455cbb4d 32
kenjiArai 0:0ef6455cbb4d 33 #if NEED_CONSOLE_OUTPUT
kenjiArai 0:0ef6455cbb4d 34 #define DEBUG(...) { printf(__VA_ARGS__); }
kenjiArai 0:0ef6455cbb4d 35 #else
kenjiArai 0:0ef6455cbb4d 36 #define DEBUG(...)
kenjiArai 0:0ef6455cbb4d 37 #endif
kenjiArai 0:0ef6455cbb4d 38
kenjiArai 0:0ef6455cbb4d 39 #define SOFT_DEVICE_FATHER_HANDLE 3
kenjiArai 0:0ef6455cbb4d 40 #define BOARDS_COUNT 3
kenjiArai 0:0ef6455cbb4d 41
kenjiArai 0:0ef6455cbb4d 42 // Object ----------------------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 43 BLE ble;
kenjiArai 0:0ef6455cbb4d 44 DigitalOut alivenessLED(LED1, 1);
kenjiArai 0:0ef6455cbb4d 45 DigitalOut connectedLED(D10, 0);
kenjiArai 0:0ef6455cbb4d 46 DigitalIn sw(D12, PullUp);
kenjiArai 0:0ef6455cbb4d 47 InterruptIn signal_sw(D12); // duplicated!!
kenjiArai 0:0ef6455cbb4d 48 Serial pc(USBTX, USBRX);
kenjiArai 0:0ef6455cbb4d 49 Ticker ticker;
kenjiArai 0:0ef6455cbb4d 50
kenjiArai 0:0ef6455cbb4d 51 // ROM / Constant data ---------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 52 #warning "You need to modify below value based on your board."
kenjiArai 0:0ef6455cbb4d 53 const Gap::Address_t mac_board_0 = {0x59, 0x2c, 0xa8, 0x0e, 0xe2, 0xef};
kenjiArai 0:0ef6455cbb4d 54 const Gap::Address_t mac_board_1 = {0x50, 0x2b, 0xea, 0x14, 0x95, 0xd2};
kenjiArai 0:0ef6455cbb4d 55 const Gap::Address_t mac_board_2 = {0x30, 0x74, 0x6d, 0xbd, 0x83, 0xf4};
kenjiArai 0:0ef6455cbb4d 56 #warning "You need to confirm your device name."
kenjiArai 0:0ef6455cbb4d 57 const static char DEVICE_NAME[] = "UART_C";
kenjiArai 0:0ef6455cbb4d 58 static const uint16_t uuid16_list[] = {UARTServiceShortUUID};
kenjiArai 0:0ef6455cbb4d 59
kenjiArai 0:0ef6455cbb4d 60 // RAM -------------------------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 61 Gap::Handle_t connectionHandle = 0xFFFF;
kenjiArai 0:0ef6455cbb4d 62 DiscoveredCharacteristic uartTXCharacteristic;
kenjiArai 0:0ef6455cbb4d 63 DiscoveredCharacteristic uartRXCharacteristic;
kenjiArai 0:0ef6455cbb4d 64 bool foundUartRXCharacteristic = false;
kenjiArai 0:0ef6455cbb4d 65 bool connected2peripheral = false;
kenjiArai 0:0ef6455cbb4d 66 UARTService * uartServicePtr = NULL;
kenjiArai 0:0ef6455cbb4d 67 Gap::Address_t my_mac;
kenjiArai 0:0ef6455cbb4d 68 int my_board_index = -1;
kenjiArai 0:0ef6455cbb4d 69 bool recieved_uart_dat0 = false;
kenjiArai 0:0ef6455cbb4d 70 int8_t uart_buffer0[24];
kenjiArai 0:0ef6455cbb4d 71 uint8_t uart_bf0_len;
kenjiArai 0:0ef6455cbb4d 72 bool recieved_uart_dat1 = false;
kenjiArai 0:0ef6455cbb4d 73 int8_t uart_buffer1[24];
kenjiArai 0:0ef6455cbb4d 74 uint8_t uart_bf1_len;
kenjiArai 0:0ef6455cbb4d 75 bool line_input = false;
kenjiArai 0:0ef6455cbb4d 76 uint8_t linebuf_irq[24];
kenjiArai 0:0ef6455cbb4d 77 int linebf_irq_len = 0;
kenjiArai 0:0ef6455cbb4d 78 uint8_t linebuf[24];
kenjiArai 0:0ef6455cbb4d 79 int linebf_len = 0;
kenjiArai 0:0ef6455cbb4d 80
kenjiArai 0:0ef6455cbb4d 81 // Function prototypes ---------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 82 // BLE
kenjiArai 0:0ef6455cbb4d 83 void onReceivedDataFromCentralCallback(const GattWriteCallbackParams *params);
kenjiArai 0:0ef6455cbb4d 84 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params);
kenjiArai 0:0ef6455cbb4d 85 void serviceDiscoveryCallback(const DiscoveredService *service);
kenjiArai 0:0ef6455cbb4d 86 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP);
kenjiArai 0:0ef6455cbb4d 87 void discoveryTerminationCallback(Gap::Handle_t connectionHandle);
kenjiArai 0:0ef6455cbb4d 88 void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params);
kenjiArai 0:0ef6455cbb4d 89 void connectionCallback(const Gap::ConnectionCallbackParams_t *params);
kenjiArai 0:0ef6455cbb4d 90 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params);
kenjiArai 0:0ef6455cbb4d 91 // Interrupt related
kenjiArai 0:0ef6455cbb4d 92 void periodicCallback(void);
kenjiArai 0:0ef6455cbb4d 93 void serialRxCallback(void);
kenjiArai 0:0ef6455cbb4d 94 // Pre-check
kenjiArai 0:0ef6455cbb4d 95 bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2);
kenjiArai 0:0ef6455cbb4d 96 int get_board_index(const Gap::Address_t mac);
kenjiArai 0:0ef6455cbb4d 97 void adjust_line(uint8_t *bf);
kenjiArai 0:0ef6455cbb4d 98
kenjiArai 0:0ef6455cbb4d 99 //-------------------------------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 100 // Control Program
kenjiArai 0:0ef6455cbb4d 101 //-------------------------------------------------------------------------------------------------
kenjiArai 0:0ef6455cbb4d 102 int main(void){
kenjiArai 0:0ef6455cbb4d 103 alivenessLED = 0;
kenjiArai 0:0ef6455cbb4d 104 pc.attach(&serialRxCallback, Serial::RxIrq);
kenjiArai 0:0ef6455cbb4d 105 ticker.attach(periodicCallback, 1);
kenjiArai 0:0ef6455cbb4d 106 for (int k = 0; k < 20; k++) { pc.printf("\r\n");} // clear terminal output
kenjiArai 0:0ef6455cbb4d 107 pc.printf("UART Communication / Client side\r\n"); // opening message
kenjiArai 0:0ef6455cbb4d 108 pc.printf(" Client(Central) and Peripheral(device)\r\n"); // opening message
kenjiArai 0:0ef6455cbb4d 109 // Mixed role *************************************************************
kenjiArai 0:0ef6455cbb4d 110 ble.init();
kenjiArai 0:0ef6455cbb4d 111 Gap::AddressType_t my_mac_type;
kenjiArai 0:0ef6455cbb4d 112 ble.gap().getAddress(&my_mac_type, my_mac);
kenjiArai 0:0ef6455cbb4d 113 my_board_index = get_board_index(my_mac);
kenjiArai 0:0ef6455cbb4d 114 DEBUG(
kenjiArai 0:0ef6455cbb4d 115 "me %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n",
kenjiArai 0:0ef6455cbb4d 116 my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0],
kenjiArai 0:0ef6455cbb4d 117 (my_mac_type == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random"
kenjiArai 0:0ef6455cbb4d 118 );
kenjiArai 0:0ef6455cbb4d 119 ble.gap().onConnection(connectionCallback);
kenjiArai 0:0ef6455cbb4d 120 ble.gap().onDisconnection(disconnectionCallback);
kenjiArai 0:0ef6455cbb4d 121 // Peripheral(Device) role ************************************************
kenjiArai 0:0ef6455cbb4d 122 ble.gattServer().onDataWritten(onReceivedDataFromCentralCallback);
kenjiArai 0:0ef6455cbb4d 123 UARTService uartService(ble);
kenjiArai 0:0ef6455cbb4d 124 uartServicePtr = &uartService;
kenjiArai 0:0ef6455cbb4d 125 // setup advertising
kenjiArai 0:0ef6455cbb4d 126 ble.accumulateAdvertisingPayload(
kenjiArai 0:0ef6455cbb4d 127 GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE
kenjiArai 0:0ef6455cbb4d 128 );
kenjiArai 0:0ef6455cbb4d 129 ble.accumulateAdvertisingPayload(
kenjiArai 0:0ef6455cbb4d 130 GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)
kenjiArai 0:0ef6455cbb4d 131 );
kenjiArai 0:0ef6455cbb4d 132 ble.accumulateAdvertisingPayload(
kenjiArai 0:0ef6455cbb4d 133 GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
kenjiArai 0:0ef6455cbb4d 134 (uint8_t *)uuid16_list,
kenjiArai 0:0ef6455cbb4d 135 sizeof(uuid16_list)
kenjiArai 0:0ef6455cbb4d 136 ); // UUID's broadcast in advertising packet (set advertising type)
kenjiArai 0:0ef6455cbb4d 137 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
kenjiArai 0:0ef6455cbb4d 138 ble.setAdvertisingInterval(100);
kenjiArai 0:0ef6455cbb4d 139 // Client(Central) role ***************************************************
kenjiArai 0:0ef6455cbb4d 140 ble.gattClient().onHVX(onReceivedDataFromDeviceCallback);
kenjiArai 0:0ef6455cbb4d 141 ble.gap().setScanParams(500, 450);
kenjiArai 0:0ef6455cbb4d 142 ble.startAdvertising(); // start advertising and scan
kenjiArai 0:0ef6455cbb4d 143 ble.gap().startScan(advertisementCallback);
kenjiArai 0:0ef6455cbb4d 144 while(true) {
kenjiArai 0:0ef6455cbb4d 145 // allow notifications from Peripheral(device)
kenjiArai 0:0ef6455cbb4d 146 if (foundUartRXCharacteristic && !ble.gattClient().isServiceDiscoveryActive()){
kenjiArai 0:0ef6455cbb4d 147 foundUartRXCharacteristic = false; // need to do the following only once
kenjiArai 0:0ef6455cbb4d 148 uint16_t value = BLE_HVX_NOTIFICATION;
kenjiArai 0:0ef6455cbb4d 149 ble.gattClient().write(
kenjiArai 0:0ef6455cbb4d 150 GattClient::GATT_OP_WRITE_REQ,
kenjiArai 0:0ef6455cbb4d 151 connectionHandle,
kenjiArai 0:0ef6455cbb4d 152 uartRXCharacteristic.getValueHandle() + 1,
kenjiArai 0:0ef6455cbb4d 153 sizeof(uint16_t),
kenjiArai 0:0ef6455cbb4d 154 reinterpret_cast<const uint8_t *>(&value)
kenjiArai 0:0ef6455cbb4d 155 );
kenjiArai 0:0ef6455cbb4d 156 }
kenjiArai 0:0ef6455cbb4d 157 if (recieved_uart_dat0 == true){
kenjiArai 0:0ef6455cbb4d 158 recieved_uart_dat0 = false;
kenjiArai 0:0ef6455cbb4d 159 for(int i = 0; i < uart_bf0_len; i++){
kenjiArai 0:0ef6455cbb4d 160 pc.printf("%c", uart_buffer0[i]);
kenjiArai 0:0ef6455cbb4d 161 }
kenjiArai 0:0ef6455cbb4d 162 pc.printf("\r\n");
kenjiArai 0:0ef6455cbb4d 163 }
kenjiArai 0:0ef6455cbb4d 164 if (recieved_uart_dat1 == true){
kenjiArai 0:0ef6455cbb4d 165 recieved_uart_dat1 = false;
kenjiArai 0:0ef6455cbb4d 166 for(int i = 0; i < uart_bf1_len; i++){
kenjiArai 0:0ef6455cbb4d 167 pc.printf("%c", uart_buffer1[i]);
kenjiArai 0:0ef6455cbb4d 168 }
kenjiArai 0:0ef6455cbb4d 169 pc.printf("\r\n");
kenjiArai 0:0ef6455cbb4d 170 }
kenjiArai 0:0ef6455cbb4d 171 if (line_input == true){
kenjiArai 0:0ef6455cbb4d 172 line_input = false;
kenjiArai 0:0ef6455cbb4d 173 // Client to Peripheral(central to device)
kenjiArai 0:0ef6455cbb4d 174 adjust_line(linebuf);
kenjiArai 0:0ef6455cbb4d 175 int ret = uartTXCharacteristic.write(20, linebuf);
kenjiArai 0:0ef6455cbb4d 176 if (ret == BLE_ERROR_NONE){
kenjiArai 0:0ef6455cbb4d 177 DEBUG("\r\ndone (c2p)\r\n");
kenjiArai 0:0ef6455cbb4d 178 } else if (ret == BLE_STACK_BUSY){
kenjiArai 0:0ef6455cbb4d 179 DEBUG("\r\nbusy (c2p)\r\n");
kenjiArai 0:0ef6455cbb4d 180 } else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED) {
kenjiArai 0:0ef6455cbb4d 181 DEBUG("\r\nnot connected (c2d)\r\n");
kenjiArai 0:0ef6455cbb4d 182 } else {
kenjiArai 0:0ef6455cbb4d 183 DEBUG("\r\ncode %d (c2d)\r\n", ret);
kenjiArai 0:0ef6455cbb4d 184 }
kenjiArai 0:0ef6455cbb4d 185 // Peripheral to Client(device to central)
kenjiArai 0:0ef6455cbb4d 186 if (ble.gap().getState().connected){
kenjiArai 0:0ef6455cbb4d 187 int ret = ble.gattServer().write(
kenjiArai 0:0ef6455cbb4d 188 uartServicePtr->getRXCharacteristicHandle(),
kenjiArai 0:0ef6455cbb4d 189 linebuf,
kenjiArai 0:0ef6455cbb4d 190 linebf_len
kenjiArai 0:0ef6455cbb4d 191 );
kenjiArai 0:0ef6455cbb4d 192 if (ret == BLE_ERROR_NONE){
kenjiArai 0:0ef6455cbb4d 193 DEBUG("\r\ndone (p2c)\r\n");
kenjiArai 0:0ef6455cbb4d 194 } else if (ret == BLE_STACK_BUSY){
kenjiArai 0:0ef6455cbb4d 195 DEBUG("\r\nbusy (p2c)\r\n");
kenjiArai 0:0ef6455cbb4d 196 } else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED){
kenjiArai 0:0ef6455cbb4d 197 DEBUG("\r\nnot connected (p2c)\r\n");
kenjiArai 0:0ef6455cbb4d 198 } else {
kenjiArai 0:0ef6455cbb4d 199 DEBUG("\r\ncode %d (p2c)\r\n", ret);
kenjiArai 0:0ef6455cbb4d 200 }
kenjiArai 0:0ef6455cbb4d 201 }
kenjiArai 0:0ef6455cbb4d 202 }
kenjiArai 0:0ef6455cbb4d 203 ble.waitForEvent(); // save power
kenjiArai 0:0ef6455cbb4d 204 }
kenjiArai 0:0ef6455cbb4d 205 }
kenjiArai 0:0ef6455cbb4d 206
kenjiArai 0:0ef6455cbb4d 207 void serialRxCallback(){
kenjiArai 0:0ef6455cbb4d 208 char c = pc.getc();
kenjiArai 0:0ef6455cbb4d 209 if (c == '\r') {
kenjiArai 0:0ef6455cbb4d 210 linebuf_irq[linebf_irq_len++] = c;
kenjiArai 0:0ef6455cbb4d 211 pc.printf("\r\n");
kenjiArai 0:0ef6455cbb4d 212 linebf_len = linebf_irq_len;
kenjiArai 0:0ef6455cbb4d 213 strcpy((char *)linebuf, (char *)linebuf_irq);
kenjiArai 0:0ef6455cbb4d 214 linebf_irq_len = 0;
kenjiArai 0:0ef6455cbb4d 215 line_input = true;
kenjiArai 0:0ef6455cbb4d 216 } else if ((c == '\b') && linebf_irq_len) {
kenjiArai 0:0ef6455cbb4d 217 linebf_irq_len--;
kenjiArai 0:0ef6455cbb4d 218 pc.putc(c);
kenjiArai 0:0ef6455cbb4d 219 pc.putc(' ');
kenjiArai 0:0ef6455cbb4d 220 pc.putc(c);
kenjiArai 0:0ef6455cbb4d 221 } else if (((uint8_t)c >= ' ') && (linebf_irq_len < 20)) {
kenjiArai 0:0ef6455cbb4d 222 linebuf_irq[linebf_irq_len++] = c;
kenjiArai 0:0ef6455cbb4d 223 pc.putc(c);
kenjiArai 0:0ef6455cbb4d 224 } else if ( c == 0x1f ){ // Control+?
kenjiArai 0:0ef6455cbb4d 225 SCB->AIRCR = 0x05fa0004; // System RESET!!
kenjiArai 0:0ef6455cbb4d 226 }
kenjiArai 0:0ef6455cbb4d 227 linebuf_irq[linebf_irq_len] = 0;
kenjiArai 0:0ef6455cbb4d 228 }
kenjiArai 0:0ef6455cbb4d 229
kenjiArai 0:0ef6455cbb4d 230 void adjust_line(uint8_t *bf){
kenjiArai 0:0ef6455cbb4d 231 uint8_t i, c;
kenjiArai 0:0ef6455cbb4d 232
kenjiArai 0:0ef6455cbb4d 233 for (i = 0; i <20; bf++, i++){
kenjiArai 0:0ef6455cbb4d 234 c = *bf;
kenjiArai 0:0ef6455cbb4d 235 if ( (c == '\r') || (c == '\n') || (c == 0)){
kenjiArai 0:0ef6455cbb4d 236 break;
kenjiArai 0:0ef6455cbb4d 237 }
kenjiArai 0:0ef6455cbb4d 238 }
kenjiArai 0:0ef6455cbb4d 239 for (; i < 20; bf++, i++){
kenjiArai 0:0ef6455cbb4d 240 *bf = ' ';
kenjiArai 0:0ef6455cbb4d 241 }
kenjiArai 0:0ef6455cbb4d 242 *(bf + 1) = 0;
kenjiArai 0:0ef6455cbb4d 243 }
kenjiArai 0:0ef6455cbb4d 244
kenjiArai 0:0ef6455cbb4d 245 // Peripheral(Device) role ****************************************************
kenjiArai 0:0ef6455cbb4d 246 void onReceivedDataFromCentralCallback(const GattWriteCallbackParams *params){
kenjiArai 0:0ef6455cbb4d 247 if (uartServicePtr != NULL){
kenjiArai 0:0ef6455cbb4d 248 if ((params->handle ==
kenjiArai 0:0ef6455cbb4d 249 uartServicePtr->getTXCharacteristicHandle()) && (params->len >= 1))
kenjiArai 0:0ef6455cbb4d 250 {
kenjiArai 0:0ef6455cbb4d 251 uart_bf0_len = params->len;
kenjiArai 0:0ef6455cbb4d 252 strcpy((char *)uart_buffer0, (char *)params->data);
kenjiArai 0:0ef6455cbb4d 253 recieved_uart_dat0 = true;
kenjiArai 0:0ef6455cbb4d 254 }
kenjiArai 0:0ef6455cbb4d 255 }
kenjiArai 0:0ef6455cbb4d 256 }
kenjiArai 0:0ef6455cbb4d 257
kenjiArai 0:0ef6455cbb4d 258 void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params){
kenjiArai 0:0ef6455cbb4d 259 DEBUG(
kenjiArai 0:0ef6455cbb4d 260 "received HVX callback for handle %u; type %s\r\r\n",
kenjiArai 0:0ef6455cbb4d 261 params->handle,
kenjiArai 0:0ef6455cbb4d 262 (params->type == BLE_HVX_NOTIFICATION) ? "notification" : "indication"
kenjiArai 0:0ef6455cbb4d 263 );
kenjiArai 0:0ef6455cbb4d 264 if (params->type == BLE_HVX_NOTIFICATION){
kenjiArai 0:0ef6455cbb4d 265 if ((params->handle
kenjiArai 0:0ef6455cbb4d 266 == uartRXCharacteristic.getValueHandle()) && (params->len > 0))
kenjiArai 0:0ef6455cbb4d 267 {
kenjiArai 0:0ef6455cbb4d 268 uart_bf1_len = params->len;
kenjiArai 0:0ef6455cbb4d 269 strcpy((char *)uart_buffer1, (char *)params->data);
kenjiArai 0:0ef6455cbb4d 270 recieved_uart_dat1 = true;
kenjiArai 0:0ef6455cbb4d 271 }
kenjiArai 0:0ef6455cbb4d 272 }
kenjiArai 0:0ef6455cbb4d 273 }
kenjiArai 0:0ef6455cbb4d 274
kenjiArai 0:0ef6455cbb4d 275 void periodicCallback(void){
kenjiArai 0:0ef6455cbb4d 276 alivenessLED = !alivenessLED; // Do blinky on alivenessLED to indicate system aliveness
kenjiArai 0:0ef6455cbb4d 277 if (connected2peripheral){
kenjiArai 0:0ef6455cbb4d 278 connectedLED = 1;
kenjiArai 0:0ef6455cbb4d 279 } else {
kenjiArai 0:0ef6455cbb4d 280 connectedLED = 0;
kenjiArai 0:0ef6455cbb4d 281 }
kenjiArai 0:0ef6455cbb4d 282 }
kenjiArai 0:0ef6455cbb4d 283
kenjiArai 0:0ef6455cbb4d 284 bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2){
kenjiArai 0:0ef6455cbb4d 285 DEBUG("Address: ");
kenjiArai 0:0ef6455cbb4d 286 for (int i = 0; i < 6; i++){
kenjiArai 0:0ef6455cbb4d 287 DEBUG("0x%02x ", mac_1[i]);
kenjiArai 0:0ef6455cbb4d 288 }
kenjiArai 0:0ef6455cbb4d 289 DEBUG("\r\n");
kenjiArai 0:0ef6455cbb4d 290 for (int i = 0; i < 6; i++){
kenjiArai 0:0ef6455cbb4d 291 if (mac_1[i] != mac_2[i]){
kenjiArai 0:0ef6455cbb4d 292 DEBUG("0x%02x != 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
kenjiArai 0:0ef6455cbb4d 293 return false;
kenjiArai 0:0ef6455cbb4d 294 } else {
kenjiArai 0:0ef6455cbb4d 295 DEBUG("0x%02x == 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
kenjiArai 0:0ef6455cbb4d 296 }
kenjiArai 0:0ef6455cbb4d 297 }
kenjiArai 0:0ef6455cbb4d 298 return true;
kenjiArai 0:0ef6455cbb4d 299 }
kenjiArai 0:0ef6455cbb4d 300
kenjiArai 0:0ef6455cbb4d 301 int get_board_index(const Gap::Address_t mac){
kenjiArai 0:0ef6455cbb4d 302 if (mac_equals(mac, mac_board_0)) { return 0;}
kenjiArai 0:0ef6455cbb4d 303 if (mac_equals(mac, mac_board_1)) { return 1;}
kenjiArai 0:0ef6455cbb4d 304 if (mac_equals(mac, mac_board_2)) { return 2;}
kenjiArai 0:0ef6455cbb4d 305 return -1;
kenjiArai 0:0ef6455cbb4d 306 }
kenjiArai 0:0ef6455cbb4d 307
kenjiArai 0:0ef6455cbb4d 308 // Client(Central) role *******************************************************
kenjiArai 0:0ef6455cbb4d 309 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params){
kenjiArai 0:0ef6455cbb4d 310 // connections
kenjiArai 0:0ef6455cbb4d 311 int peer_board_index = get_board_index(params->peerAddr);
kenjiArai 0:0ef6455cbb4d 312 if (peer_board_index != -1){
kenjiArai 0:0ef6455cbb4d 313 pc.printf("adv peerAddr");
kenjiArai 0:0ef6455cbb4d 314 pc.printf(
kenjiArai 0:0ef6455cbb4d 315 "[%02x %02x %02x %02x %02x %02x] rssi %+4d, isScanResponse %u, AdvertisementType %u",
kenjiArai 0:0ef6455cbb4d 316 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3],
kenjiArai 0:0ef6455cbb4d 317 params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
kenjiArai 0:0ef6455cbb4d 318 params->rssi,
kenjiArai 0:0ef6455cbb4d 319 params->isScanResponse,
kenjiArai 0:0ef6455cbb4d 320 params->type
kenjiArai 0:0ef6455cbb4d 321 );
kenjiArai 0:0ef6455cbb4d 322 pc.printf("\r\n");
kenjiArai 0:0ef6455cbb4d 323 ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
kenjiArai 0:0ef6455cbb4d 324 }
kenjiArai 0:0ef6455cbb4d 325 }
kenjiArai 0:0ef6455cbb4d 326
kenjiArai 0:0ef6455cbb4d 327 void serviceDiscoveryCallback(const DiscoveredService *service) {
kenjiArai 0:0ef6455cbb4d 328 DEBUG("service found...\r\n");
kenjiArai 0:0ef6455cbb4d 329 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
kenjiArai 0:0ef6455cbb4d 330 DEBUG(
kenjiArai 0:0ef6455cbb4d 331 "Service UUID-%x attrs[%u %u]\r\n",
kenjiArai 0:0ef6455cbb4d 332 service->getUUID().getShortUUID(),
kenjiArai 0:0ef6455cbb4d 333 service->getStartHandle(),
kenjiArai 0:0ef6455cbb4d 334 service->getEndHandle()
kenjiArai 0:0ef6455cbb4d 335 );
kenjiArai 0:0ef6455cbb4d 336 } else {
kenjiArai 0:0ef6455cbb4d 337 DEBUG("Service UUID-");
kenjiArai 0:0ef6455cbb4d 338 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
kenjiArai 0:0ef6455cbb4d 339 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
kenjiArai 0:0ef6455cbb4d 340 DEBUG("%02x", longUUIDBytes[i]);
kenjiArai 0:0ef6455cbb4d 341 }
kenjiArai 0:0ef6455cbb4d 342 DEBUG(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
kenjiArai 0:0ef6455cbb4d 343 }
kenjiArai 0:0ef6455cbb4d 344 }
kenjiArai 0:0ef6455cbb4d 345
kenjiArai 0:0ef6455cbb4d 346 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP){
kenjiArai 0:0ef6455cbb4d 347 DEBUG(
kenjiArai 0:0ef6455cbb4d 348 " C UUID-%x valueAttr[%u] props[%x]\r\n",
kenjiArai 0:0ef6455cbb4d 349 characteristicP->getUUID().getShortUUID(),
kenjiArai 0:0ef6455cbb4d 350 characteristicP->getValueHandle(),
kenjiArai 0:0ef6455cbb4d 351 (uint8_t)characteristicP->getProperties().broadcast()
kenjiArai 0:0ef6455cbb4d 352 );
kenjiArai 0:0ef6455cbb4d 353 if (characteristicP->getUUID().getShortUUID()
kenjiArai 0:0ef6455cbb4d 354 == UARTServiceTXCharacteristicShortUUID)
kenjiArai 0:0ef6455cbb4d 355 {
kenjiArai 0:0ef6455cbb4d 356 pc.printf("Sevice TX 0x%04x\r\n", UARTServiceTXCharacteristicShortUUID);
kenjiArai 0:0ef6455cbb4d 357 uartTXCharacteristic = *characteristicP;
kenjiArai 0:0ef6455cbb4d 358 } else if (characteristicP->getUUID().getShortUUID()
kenjiArai 0:0ef6455cbb4d 359 == UARTServiceRXCharacteristicShortUUID)
kenjiArai 0:0ef6455cbb4d 360 {
kenjiArai 0:0ef6455cbb4d 361 pc.printf("Sevice RX 0x%04x\r\n", UARTServiceRXCharacteristicShortUUID);
kenjiArai 0:0ef6455cbb4d 362 uartRXCharacteristic = *characteristicP;
kenjiArai 0:0ef6455cbb4d 363 foundUartRXCharacteristic = true;
kenjiArai 0:0ef6455cbb4d 364 }
kenjiArai 0:0ef6455cbb4d 365 }
kenjiArai 0:0ef6455cbb4d 366
kenjiArai 0:0ef6455cbb4d 367 void discoveryTerminationCallback(Gap::Handle_t connectionHandle){
kenjiArai 0:0ef6455cbb4d 368 DEBUG("terminated SD for handle=%u\r\n", connectionHandle);
kenjiArai 0:0ef6455cbb4d 369 }
kenjiArai 0:0ef6455cbb4d 370
kenjiArai 0:0ef6455cbb4d 371 // Mixed role *****************************************************************
kenjiArai 0:0ef6455cbb4d 372 void connectionCallback(const Gap::ConnectionCallbackParams_t *params){
kenjiArai 0:0ef6455cbb4d 373 if (params->role == Gap::CENTRAL) {
kenjiArai 0:0ef6455cbb4d 374 DEBUG("connected as Client(central) (handle = %d)\r\n\r", params->handle);
kenjiArai 0:0ef6455cbb4d 375 connected2peripheral = true;
kenjiArai 0:0ef6455cbb4d 376 connectionHandle = params->handle;
kenjiArai 0:0ef6455cbb4d 377 ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
kenjiArai 0:0ef6455cbb4d 378 ble.gattClient().launchServiceDiscovery(
kenjiArai 0:0ef6455cbb4d 379 params->handle,
kenjiArai 0:0ef6455cbb4d 380 serviceDiscoveryCallback,
kenjiArai 0:0ef6455cbb4d 381 characteristicDiscoveryCallback/*,
kenjiArai 0:0ef6455cbb4d 382 0xa000, 0xa001*/
kenjiArai 0:0ef6455cbb4d 383 );
kenjiArai 0:0ef6455cbb4d 384 } else {
kenjiArai 0:0ef6455cbb4d 385 DEBUG("connected as device (handle = %d)\r\n\r", params->handle);
kenjiArai 0:0ef6455cbb4d 386 DEBUG(
kenjiArai 0:0ef6455cbb4d 387 "Conn. params => min=%d, max=%d, slave=%d, supervision=%d\r\n",
kenjiArai 0:0ef6455cbb4d 388 params->connectionParams->minConnectionInterval,
kenjiArai 0:0ef6455cbb4d 389 params->connectionParams->maxConnectionInterval,
kenjiArai 0:0ef6455cbb4d 390 params->connectionParams->slaveLatency,
kenjiArai 0:0ef6455cbb4d 391 params->connectionParams->connectionSupervisionTimeout
kenjiArai 0:0ef6455cbb4d 392 );
kenjiArai 0:0ef6455cbb4d 393 Gap::ConnectionParams_t connectionParams;
kenjiArai 0:0ef6455cbb4d 394 connectionParams.minConnectionInterval = 6;
kenjiArai 0:0ef6455cbb4d 395 connectionParams.maxConnectionInterval = 12;
kenjiArai 0:0ef6455cbb4d 396 connectionParams.slaveLatency = 0;
kenjiArai 0:0ef6455cbb4d 397 connectionParams.connectionSupervisionTimeout = 500;
kenjiArai 0:0ef6455cbb4d 398 if (ble.updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE){
kenjiArai 0:0ef6455cbb4d 399 DEBUG("failed to update connection parameter\r\n");
kenjiArai 0:0ef6455cbb4d 400 }
kenjiArai 0:0ef6455cbb4d 401 }
kenjiArai 0:0ef6455cbb4d 402 DEBUG(
kenjiArai 0:0ef6455cbb4d 403 "own %02x:%02x:%02x:%02x:%02x:%02x (%s), peer %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n",
kenjiArai 0:0ef6455cbb4d 404 params->ownAddr[5], params->ownAddr[4], params->ownAddr[3],
kenjiArai 0:0ef6455cbb4d 405 params->ownAddr[2], params->ownAddr[1], params->ownAddr[0],
kenjiArai 0:0ef6455cbb4d 406 (params->ownAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random",
kenjiArai 0:0ef6455cbb4d 407 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3],
kenjiArai 0:0ef6455cbb4d 408 params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
kenjiArai 0:0ef6455cbb4d 409 (params->peerAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random"
kenjiArai 0:0ef6455cbb4d 410 );
kenjiArai 0:0ef6455cbb4d 411 }
kenjiArai 0:0ef6455cbb4d 412
kenjiArai 0:0ef6455cbb4d 413 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){
kenjiArai 0:0ef6455cbb4d 414 DEBUG("handle = %d ", params->handle);
kenjiArai 0:0ef6455cbb4d 415 pc.printf(" -> disconnected\r\n", params->handle);
kenjiArai 0:0ef6455cbb4d 416 connected2peripheral = false;
kenjiArai 0:0ef6455cbb4d 417 if (params->handle == SOFT_DEVICE_FATHER_HANDLE) {
kenjiArai 0:0ef6455cbb4d 418 ble.startAdvertising(); // restart advertising
kenjiArai 0:0ef6455cbb4d 419 } else {
kenjiArai 0:0ef6455cbb4d 420 ble.gap().startScan(advertisementCallback); // restart scan
kenjiArai 0:0ef6455cbb4d 421 }
kenjiArai 0:0ef6455cbb4d 422 }