![](/media/cache/profiles/f0fcf351df4eb6786e9bb6fc4e2dee02.jpg.50x50_q85.jpg)
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
Diff: main.cpp
- 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