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
main.cpp
- Committer:
- kenjiArai
- Date:
- 2016-06-12
- Revision:
- 5:315161fd3d19
- Parent:
- 4:ed7848c6d374
File content as of revision 5:315161fd3d19:
/* * /////// 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 12th, 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.h" #include "DiscoveredCharacteristic.h" #include "DiscoveredService.h" #include "GapScanningParams.h" #include "ble_radio_notification.h" #include "ble_gap.h" #include "nrf_delay.h" #include "nRF51_Vdd.h" #include "TextLCD.h" #include "nRF51_lowpwr.h" // 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 1 // Serial or DEBUG & etc. #define USE_DEVICE_I2C 1 // Sensors with I2C, LCD, EEPROM, Driver chips & etc. #define USE_DEVICE_SPI 0 // Sensors with SPI, 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; } peripheral_t; #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; nrf_delay_us(100); LowPwr set_lowpwr(&lowpwr_table); 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 wait(1.0); // lcd 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.setCursor(TextLCD::CurOff_BlkOff); 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) { field_length = p_advdata[index]; field_type = p_advdata[index+1]; 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; } index += field_length + 1; } return NRF_ERROR_NOT_FOUND; } 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; 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) { 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) { 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) { 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) { PRINTF("terminated SD for handle %u\r\n", connectionHandle); } void triggerRead(const GattReadCallbackParams *response) { rcv_dt_len = response->len; memcpy(rcv_dt, response->data, rcv_dt_len); triggerRead_flag = true; } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ 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(2.0); ble.gap().startScan(scanCallback); }