Pair function with BLE_Paired_Sever. If missing BLE_Paired_Server side, BZ will ON for notice.

Dependencies:   BLE_API TextLCD mbed nRF51822 nRF51_LowPwr nRF51_Vdd

Revision:
4:ed7848c6d374
Parent:
3:d6f80e11a7f4
Child:
5:315161fd3d19
diff -r d6f80e11a7f4 -r ed7848c6d374 main.cpp
--- a/main.cpp	Wed Mar 30 11:21:50 2016 +0000
+++ b/main.cpp	Wed Jun 01 12:36:23 2016 +0000
@@ -1,48 +1,326 @@
+/*
+ *  /////// Tested on Switch Science mbed TY51822r3 ///////
+ *  Modified by Kenji Arai
+ *      http://www.page.sannet.ne.jp/kenjia/index.html
+ *      http://mbed.org/users/kenjiArai/
+ *
+ *      Started:  April     8th, 2016
+ *      Revised:  June      1st, 2016
+ *
+ *  Original program:
+ *      BLE_Nano_CentralTest
+ *      https://developer.mbed.org/users/mbed_tw_hoehoe/code/BLE_Nano_CentralTest/
+ *      S130 potential unstability case [closed] by Fabien Comte
+ *      https://devzone.nordicsemi.com/question/49705/s130-potential-unstability-case/
+ *  Tested Device:
+ *      BLE_Paired_Server
+ *
+ */
+
+//  Include ---------------------------------------------------------------------------------------
 #include "mbed.h"
-#include "ble/BLE.h"
-#include "ble/DiscoveredCharacteristic.h"
-#include "ble/DiscoveredService.h"
-#include "ble/GapScanningParams.h"
+#include "BLE.h"
+#include "DiscoveredCharacteristic.h"
+#include "DiscoveredService.h"
+#include "GapScanningParams.h"
 #include "ble_radio_notification.h"
 #include "ble_gap.h"
-
-BLE ble;
-Serial pc(USBTX, USBRX);
-
-const uint8_t MPU6050_service_uuid[] = {
-    0x45,0x35,0x56,0x80,0x0F,0xD8,0x5F,0xB5,0x51,0x48,0x30,0x27,0x06,0x9B,0x3F,0xD9
-};
+#include "nrf_delay.h"
+#include "nRF51_Vdd.h"
+#include "TextLCD.h"
+#include "nRF51_lowpwr.h"
 
-const uint8_t MPU6050_Accel_Characteristic_uuid[] = {
-    0x45,0x35,0x56,0x81,0x0F,0xD8,0x5F,0xB5,0x51,0x48,0x30,0x27,0x06,0x9B,0x3F,0xD9
-};
-
-DiscoveredCharacteristic accelChar;
-UUID serviceUUID(MPU6050_service_uuid);
-UUID accelUUID(MPU6050_Accel_Characteristic_uuid);
-
-#define NUMBER_OF_PERIPHERALS 3
+//  Definition ------------------------------------------------------------------------------------
+//  Before using this function, please specify your program are used following functions or not.
+#define    USE_DEVICE_STDIO_MESSAGES       0   // printf
+#define    USE_DEVICE_SERIAL               0   // Serial or DEBUG & etc.
+#define    USE_DEVICE_I2C                  1   // Sensors with I2C, LCD, EEPROM, Driver chips & etc.
+#define    USE_DEVICE_SPI                  0   // Sensors with SOI, LCD, EEPROM, Driver chips & etc.
+#define    USE_DEVICE_SPISLAVE             0   // Communication with master vis SPI
+#define    USE_DEVICE_PWMOUT               0   // PWM duty output, Serve & etc.
+#define    USE_DEVICE_ANALOGIN             0   // Analog adc
 
 typedef struct {
     Gap::Handle_t   handle;
     Gap::Address_t  address;
-    bool    connected;
-    uint8_t*    deviceName;
+    bool            connected;
+    uint8_t*        deviceName;
 } peripheral_t;
 
-static peripheral_t gs_peripheral[NUMBER_OF_PERIPHERALS];
+#define LIMIT_JUDGE_CNT         4
+
+#if USE_DEVICE_SERIAL
+#define BAUD(x)                 pc.baud(x)
+#define GETC(x)                 pc.getc(x)
+#define PUTC(x)                 pc.putc(x)
+#define PRINTF(...)             pc.printf(__VA_ARGS__)
+#define READABLE(x)             pc.readable(x)
+#define ATTACH(x,y)             pc.attach(x,y)
+#else
+#define BAUD(x)
+#define GETC(x)                 'c'
+#define PUTC(x)
+#define PRINTF(...)
+#define READABLE(x)
+#define ATTACH(x,y)
+#endif
+
+//  Object ----------------------------------------------------------------------------------------
+BLE         ble;
+DigitalOut  alivenessLED(LED1, 1);
+DigitalOut  connectedLED(LED2, 0);
+DigitalOut  buzzer(LED3, 0);
+#if USE_DEVICE_SERIAL 
+Serial      pc(USBTX, USBRX);
+#endif
+Ticker      ticker;
+nRF51_Vdd   vdd(3.6f, 1.8f, ONLY4VDD);
+I2C         i2c1(P0_28, P0_29);         // SDA, SCL
+TextLCD_I2C_N   lcd(&i2c1, ST7036_SA2, TextLCD::LCD8x2, NC, TextLCD::ST7032_3V3);
+
+//  ROM / Constant data ---------------------------------------------------------------------------
+//#warning "You need to modify below values based on your board."
+const Gap::Address_t    mac_board_0   = {0x98, 0x11, 0x9b, 0x73, 0x1a, 0xe7};   // FRISK
+/* followings are other own board
+const Gap::Address_t    mac_board_0   = {0x50, 0x2b, 0xea, 0x14, 0x95, 0xd2};   // Nano
+const Gap::Address_t    mac_board_0   = {0x98, 0x11, 0x9b, 0x73, 0x1a, 0xe7};   // FRISK
+const Gap::Address_t    mac_board_0   = {0x30, 0x74, 0x6d, 0xbd, 0x83, 0xf4};   // TY None Pin BLK
+const Gap::Address_t    mac_board_0   = {0x59, 0x2c, 0xa8, 0x0e, 0xe2, 0xef};   // TY cut PCB
+*/
+const int8_t            tx_power_level[8] =
+                        {
+                            RADIO_TXPOWER_TXPOWER_Pos4dBm,      // 0
+                            RADIO_TXPOWER_TXPOWER_0dBm,         // 1
+                            RADIO_TXPOWER_TXPOWER_Neg4dBm,      // 2
+                            RADIO_TXPOWER_TXPOWER_Neg8dBm,      // 3
+                            RADIO_TXPOWER_TXPOWER_Neg12dBm,     // 4
+                            RADIO_TXPOWER_TXPOWER_Neg16dBm,     // 5
+                            RADIO_TXPOWER_TXPOWER_Neg20dBm,     // 6
+                            RADIO_TXPOWER_TXPOWER_Neg30dBm      // 7
+                        };
+
+const nRF51_LOWPWR_TypeDef  lowpwr_table = 
+                        {
+                        #if USE_DEVICE_STDIO_MESSAGES 
+                            true,
+                        #else
+                            false,
+                        #endif
+                        #if USE_DEVICE_SERIAL
+                            true,
+                        #else
+                            false,
+                        #endif
+                        #if USE_DEVICE_I2C
+                            true,
+                        #else
+                            false,
+                        #endif
+                        #if USE_DEVICE_SPI
+                            true,
+                        #else
+                            false,
+                        #endif
+                        #if USE_DEVICE_SPISLAVE
+                            true,
+                        #else
+                            false,
+                        #endif
+                        #if USE_DEVICE_PWMOUT
+                            true,
+                        #else
+                            false,
+                        #endif
+                        #if USE_DEVICE_ANALOGIN
+                            true
+                        #else
+                            false
+                        #endif
+                        };
+
+//  RAM -------------------------------------------------------------------------------------------
+Gap::Address_t  my_mac;
+int             my_board_index  = -1;
+int8_t          alive_board     = 0;
+int8_t          judge_counter   = 0;
+static peripheral_t         peripheral_inf;
+DiscoveredCharacteristic    peripheral_dat_readChar;
+DiscoveredCharacteristic    central_dat_readChar;
+volatile bool   trigger5Sec_flag = false;
+volatile bool   triggerRead_flag = false;
+uint16_t        rcv_dt_len;
+uint8_t         rcv_dt[32];
+uint32_t        counter;
+uint8_t         contrast;
+
+//  Function prototypes ---------------------------------------------------------------------------
+void periodicCallback(void);
+uint32_t ble_advdata_parser(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata,
+                            uint8_t *len, uint8_t *p_field_data);
+void scanCallback(const Gap::AdvertisementCallbackParams_t *params);
+void serviceDiscoveryCallback(const DiscoveredService *service);
+void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP);
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params);
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle);
+void triggerRead(const GattReadCallbackParams *response);
+void triggerToggledWrite(const GattWriteCallbackParams *response);
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params);
+void serialRxCallback();
+void periodicCallback(void);
+bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2);
+void osc_5KHz(uint32_t time_sec);
+uint8_t auto_contrast(float vdd);
+
+//-------------------------------------------------------------------------------------------------
+//  Control Program
+//-------------------------------------------------------------------------------------------------
+int main(void) {
+    uint8_t *p;
 
-uint32_t ble_advdata_parser(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata, uint8_t *len, uint8_t *p_field_data)
+    nrf_delay_us(100);
+    ticker.attach(periodicCallback, 5); /* Blink LED every second */
+    ATTACH(&serialRxCallback, Serial::RxIrq);
+    for (int k = 0; k < 20; k++) { PRINTF("\r\n");}
+    PRINTF("Check paired Peripheral board\r\n"); // opening message
+    LowPwr set_lowpwr(&lowpwr_table);
+    // lcd
+    lcd.setCursor(TextLCD::CurOff_BlkOff);
+    lcd.locate(0, 0);    // 1st line top
+    //          12345678
+    lcd.printf("TY51822r");
+    lcd.locate(0, 1);    // 2nd line top
+    //        12345678
+    lcd.puts(" JH1PJL ");
+    contrast = auto_contrast(vdd.read_real_value());
+    lcd.setContrast(contrast);
+    // BLE
+    ble.init();
+    ble.onConnection(connectionCallback);
+    ble.onDisconnection(disconnectionCallback);
+    ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+    ble.gattClient().onDataRead(triggerRead);
+    ble.gap().setScanParams(500, 400);
+    ble.gap().setTxPower(tx_power_level[0]);
+    ble.gap().startScan(scanCallback);
+    alive_board = 0;
+    while (true) {
+        if (trigger5Sec_flag == true){
+            trigger5Sec_flag = false;
+            peripheral_dat_readChar.read();
+            if (alive_board){
+                --judge_counter;
+                if (judge_counter < 0){
+                    judge_counter = -1;
+                }
+            }
+        }
+        if (triggerRead_flag == true){
+            triggerRead_flag = false;
+            alivenessLED = 0;
+            PRINTF("%s", rcv_dt);
+            PRINTF("\r\n");
+            if (counter & 1UL){      // Change a screen contents
+                p = rcv_dt + 2;
+                lcd.locate(0, 0);    // 1st line top
+                //          12345678
+                lcd.printf(" Server "); 
+                lcd.locate(0, 1);    // 2nd line top
+                lcd.printf("%s", p);
+            } else {
+                lcd.locate(0, 0);    // 1st line top
+                //          12345678
+                lcd.printf(" Client "); 
+                lcd.locate(0, 1);    // 2nd line top
+                lcd.printf(" %3.2f[V]", vdd.read_real_value());
+            }
+            contrast = auto_contrast(vdd.read_real_value());
+            lcd.setContrast(contrast);
+            ++judge_counter;
+            if (judge_counter > LIMIT_JUDGE_CNT){
+                judge_counter = LIMIT_JUDGE_CNT;
+                alive_board = 1;
+            }
+        }
+        PRINTF("state %+d\r\n", judge_counter);
+        if ( judge_counter == -1){
+            PRINTF("%c", 0x07);  // Ring a PC terminal bell 
+            lcd.locate(0, 0);    // 1st line top
+            //          12345678
+            lcd.printf(" Server "); 
+            lcd.locate(0, 1);    // 2nd line top
+            //          12345678
+            lcd.printf("is gone!");
+            alivenessLED = !alivenessLED;
+            osc_5KHz(3);
+        }
+        ble.waitForEvent();
+    }
+}
+
+void osc_5KHz(uint32_t time_sec){
+    for (int32_t t = 0; t < time_sec; t++){   // Durartion
+        for (int32_t n = 0; n < 5000; n++){   // 1sec with 5KHz
+            buzzer = 1;
+            nrf_delay_us(100);
+            buzzer = 0;
+            nrf_delay_us(100);
+        }
+    }
+    buzzer = 0;
+}
+
+uint8_t auto_contrast(float vdd){
+    #define OFFSET_CONST    15
+    #define SIZE_OF_TBL     50
+    uint8_t n = 0;
+    const static uint16_t const_table[] =
+        {
+          360, 355, 350, 345, 340, 335, 330, 325, 320, 315, 310, 305, 300,
+          295, 290, 285, 280, 275, 270, 265, 260, 257, 253, 250, 247, 243,
+          240, 237, 233, 230, 227, 223, 220, 217, 215, 212, 210, 208, 206,
+          204, 202, 200, 197, 195, 193, 190, 185, 180, 170, 100
+        };
+    
+    uint16_t v = (uint16_t)(vdd * 100);
+    for (; n < 50; n++){
+        if (v >= const_table[n]){
+            break;
+        }
+    }
+    return n + OFFSET_CONST;
+}
+
+void serialRxCallback(){
+    char c = GETC();
+    PUTC(c);
+    if ( c == 0x1f ){           // Control+?
+        NVIC_SystemReset();     // System RESET!!
+    }
+}
+
+void periodicCallback(void){
+    alivenessLED = 1;
+    trigger5Sec_flag = true;
+    counter++;
+}
+
+uint32_t ble_advdata_parser
+(
+    uint8_t type,
+    uint8_t advdata_len,
+    uint8_t *p_advdata,
+    uint8_t *len,
+    uint8_t *p_field_data
+)
 {
     uint8_t index=0;
     uint8_t field_length, field_type;
     
-    while(index<advdata_len)
-    {
+    while(index<advdata_len) {
         field_length = p_advdata[index];
         field_type   = p_advdata[index+1];
-        if(field_type == type)
-        {
+        PRINTF("len=%d, field_type=%x, type=%d\r\n", field_length, field_type, type);
+        if(field_type == type) {
             memcpy(p_field_data, &p_advdata[index+2], (field_length-1));
             *len = field_length - 1;
             return NRF_SUCCESS;
@@ -52,110 +330,156 @@
     return NRF_ERROR_NOT_FOUND;
 }
 
-void scanCallback(const Gap::AdvertisementCallbackParams_t *params) {
-    pc.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
-           params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
-           params->rssi, params->isScanResponse, params->type);
-    
-    uint8_t len;
-    uint8_t adv_name[31];
-    if( NRF_SUCCESS == ble_advdata_parser(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
-                             params->advertisingDataLen,
-                            (uint8_t *)params->advertisingData, &len, adv_name)){
+bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2){
+    PRINTF("\r\nAddress: ");
+    for (int i = 0; i < 6; i++){
+        PRINTF("0x%02x ", mac_1[i]);
+    }
+    PRINTF("\r\n");
+    for (int i = 0; i < 6; i++){
+        if (mac_1[i] != mac_2[i]){
+            PRINTF("0x%02x != 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
+            return false;
+        } else {
+            PRINTF("0x%02x == 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
+        }
+    }
+    return true;
+}
+
+void scanCallback(const Gap::AdvertisementCallbackParams_t *params){
+uint8_t     len;
+uint8_t     adv_name[32];
+uint32_t    action_result;
 
-        for(uint8_t i=0; i<3; i++){
-            if(gs_peripheral[i].connected == false){
-                memcpy(gs_peripheral[i].address, params->peerAddr, sizeof(params->peerAddr)); 
-                gs_peripheral[i].deviceName = adv_name;
-                ble.connect(params->peerAddr, BLEProtocol::AddressType::RANDOM_STATIC, NULL, NULL);
-                break;
-            }
+    PRINTF("adv peerAddr");
+    PRINTF(
+        "[%02x %02x %02x %02x %02x %02x] rssi %+4d, isScanResponse %u, AdvertisementType %u",
+        params->peerAddr[5],
+        params->peerAddr[4],
+        params->peerAddr[3],
+        params->peerAddr[2],
+        params->peerAddr[1],
+        params->peerAddr[0],
+        params->rssi,
+        params->isScanResponse,
+        params->type
+    );
+    if (mac_equals(params->peerAddr, mac_board_0) == false){
+        PRINTF(" not expected peripheral device\r\n");
+        return;
+    }
+    action_result = ble_advdata_parser(
+                            BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
+                            params->advertisingDataLen,
+                            (uint8_t *)params->advertisingData,
+                            &len,
+                            adv_name
+                    );
+    if( action_result == NRF_SUCCESS){
+        PRINTF("NRF_SUCCESS\r\n");
+        if(peripheral_inf.connected == false){
+            memcpy(peripheral_inf.address, params->peerAddr, sizeof(params->peerAddr)); 
+            peripheral_inf.deviceName = adv_name;
+            ble.connect(params->peerAddr, BLEProtocol::AddressType::RANDOM_STATIC, NULL, NULL);
         }
         ble.stopScan();
+    } else {
+         PRINTF("NRF_ERROR_NOT_FOUND\r\n");
     }
 }
 
 void serviceDiscoveryCallback(const DiscoveredService *service) {
-    pc.printf("service found...\r\n");    
+    PRINTF("service found...\r\n");
+    if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        PRINTF("Service UUID-%x attrs[%u %u]\r\n",
+                service->getUUID().getShortUUID(),
+                service->getStartHandle(),
+                service->getEndHandle()
+        );
+    } else {
+        PRINTF("Service UUID-");
+        const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
+        for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
+            PRINTF("%02x", longUUIDBytes[i]);
+        }
+        PRINTF(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
+    }
 }
 
 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
-    pc.printf("characteristicDiscoveryCallback\r\n");
-    
-    accelChar = *characteristicP;
-    
-    for(uint8_t i=0; i<3; i++){
-        if(gs_peripheral[i].connected){
-            ble.gattClient().read(characteristicP->getConnectionHandle(), characteristicP->getValueHandle(), 0);
-        }
+    PRINTF("characteristicDiscoveryCallback\r\n");
+    if (characteristicP->getUUID().getShortUUID() == 0xa001){
+        PRINTF("UUID=0xa001\r\n");
+        peripheral_dat_readChar = *characteristicP;
     }
-
+    if(peripheral_inf.connected){
+        ble.gattClient().read(
+            characteristicP->getConnectionHandle(),
+            characteristicP->getValueHandle(),
+            0
+        );
+    }
 }
 
 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
-    pc.printf("GAP_EVT_CONNECTED\r\n");
-    if (params->role == Gap::CENTRAL) {
-
-        for(uint8_t i=0; i<3; i++){
-            if(gs_peripheral[i].connected == false){
-                gs_peripheral[i].handle = params->handle;
-                gs_peripheral[i].connected = true;
-                break;
-            }
-        }
-                
-        ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, serviceUUID, accelUUID);
-        
+    PRINTF("connected\r\n");
+    connectedLED = 1;
+    if (params->role != Gap::CENTRAL) {
+        return;
+    }
+    if(peripheral_inf.connected == false){
+        peripheral_inf.handle = params->handle;
+        peripheral_inf.connected = true;
+    }
+    PRINTF("connectionHandle = params->handle %u\r\n", params->handle);
+    ble.gattClient().launchServiceDiscovery(
+        params->handle,
+        serviceDiscoveryCallback,
+        characteristicDiscoveryCallback,
+        0xa000,
+        0xa001
+    );
+    printf("connected as device (handle = %d)\r\n\r", params->handle);
+    printf(
+        "Conn. params => min=%d, max=%d, slave=%d, supervision=%d\r\n",
+        params->connectionParams->minConnectionInterval,
+        params->connectionParams->maxConnectionInterval,
+        params->connectionParams->slaveLatency,
+        params->connectionParams->connectionSupervisionTimeout
+    );
+    Gap::ConnectionParams_t connectionParams;
+    connectionParams.minConnectionInterval        = 200;
+    connectionParams.maxConnectionInterval        = 500;
+    connectionParams.slaveLatency                 = 0;
+    connectionParams.connectionSupervisionTimeout = 1500;
+    if (BLE::Instance(
+        BLE::DEFAULT_INSTANCE).gap().updateConnectionParams(params->handle,
+        &connectionParams) != BLE_ERROR_NONE
+    ){
+        printf("failed to update connection parameter\r\n");
     }
 }
 
 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
-    pc.printf("terminated SD for handle %u\r\n", connectionHandle);
+    PRINTF("terminated SD for handle %u\r\n", connectionHandle);
 }
 
 void triggerRead(const GattReadCallbackParams *response) {
-    pc.printf("triggerRead.....\r\n");
-    
-    pc.printf("len: %d\r\n", response->len);
-    const uint8_t *data = response->data;
-    pc.printf("data ");
-    for(int i=0; i < response->len; i++){
-        pc.printf("%f ", (float)data[i]);  
-    }
-    pc.printf("\r\n");
-    accelChar.read();
+    rcv_dt_len = response->len;
+    memcpy(rcv_dt, response->data, rcv_dt_len); 
+    triggerRead_flag = true;
 }
 
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){
-    pc.printf("disconnected\r\n");
-    
-    for(uint8_t i=0; i<3; i++){
-        if(gs_peripheral[i].handle == params->handle){
-            gs_peripheral[i].connected = false;
-            gs_peripheral[i].handle = 0xFFFF;
-        }
+    PRINTF("disconnected\r\n");
+    judge_counter = -1;
+    alive_board = 0;
+    connectedLED = 0;
+    if(peripheral_inf.handle == params->handle){
+        peripheral_inf.connected = false;
+        peripheral_inf.handle = 0xffff;
     }
-    wait(8.0);
+    wait(2.0);
     ble.gap().startScan(scanCallback);
 }
-
-int main(void) {
-    pc.baud(9600);
-    wait(8.0);
-    pc.printf("start\r\n");
-
-    ble.init();
-
-    ble.onConnection(connectionCallback);
-    ble.onDisconnection(disconnectionCallback);
-    ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
-    ble.gattClient().onDataRead(triggerRead);
-    //ble.gattClient().onDataWrite(triggerToggledWrite);
-
-    ble.gap().setScanParams(500, 400);
-    ble.gap().startScan(scanCallback);
-
-    while (true) {
-        ble.waitForEvent();
-    }
-}
\ No newline at end of file