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:
Thu Apr 21 11:20:46 2016 +0000
Revision:
1:f68a5e55a60e
Parent:
0:0ef6455cbb4d
Child:
2:6fb0b87b041d
change Client&Peripheral to Client&Server

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