Central/ Peripheral example: Central Device connects to a Peripheral called "LED" and a characteristic is toggled automatically with a random sleep interval (10-100ms) -> BLE_LED_PERIPHERAL needed With a external uC the latency Time of a round trip is measured via pin interrupts.

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_LED_CENTRAL_TIME_AUTO by Alex Gernhaeuser

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "ble/BLE.h"
00019 #include "ble/DiscoveredCharacteristic.h"
00020 #include "ble/Gap.h"
00021 
00022 DigitalOut alivenessLED(p16, 1);
00023 DigitalOut gateLED(p15,1);
00024 DigitalOut flagStart(p2, 0);
00025 DigitalOut flagStop(p3, 1);
00026 
00027 
00028 //InterruptIn button(p9);
00029 Serial pc(p5, p4);
00030 Ticker ticker, loop;
00031 Timer latency;
00032 
00033 timestamp_t latencyTime;
00034 uint8_t toggledValue = 0x1;
00035 uint8_t counter = 0;
00036 uint8_t randNumber = 5;
00037 uint8_t randCount = 10;
00038 
00039 static DiscoveredCharacteristic ledCharacteristic;
00040 static const char PEER_NAME[] = "LED";
00041 static Gap::ConnectionParams_t para;
00042 
00043 void periodicCallback(void) 
00044 { 
00045     if(!BLE::Instance().getGapState().connected){
00046         alivenessLED = !alivenessLED; /* Do blinky on LED1 while waiting for BLE events */ 
00047         gateLED = 1;    
00048     }
00049     counter += 1;
00050 }
00051 
00052 void triggerCallback(void)
00053 {   
00054     randCount = 0;
00055     if(!BLE::Instance().getGapState().connected){
00056         //pc.printf("not connected \n");
00057         return;
00058     }
00059     else{
00060         if(counter > 5 && flagStop.read()){
00061             alivenessLED = 1;
00062             //latency.start(); 
00063             flagStart = 1;
00064             flagStop = 0;
00065             toggledValue = toggledValue ^ 0x1;
00066             ledCharacteristic.write(1, &toggledValue);
00067             //pc.printf("AckStatus = %i \n", AckStatus);
00068         }    
00069     }
00070 }
00071 
00072 void randCallback(void) 
00073 {   
00074     //Gap::GapState_t GapInfo; //class Gap with struct GapState_t
00075     randCount += 1;
00076     if(randCount > randNumber+1 && BLE::Instance().getGapState().connected){
00077     //if(BLE::Instance().getGapState().connected){
00078 
00079         triggerCallback();
00080         gateLED = !gateLED;
00081     }      
00082 }
00083 
00084 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) 
00085 {
00086     for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
00087 
00088         const uint8_t record_length = params->advertisingData[i];
00089         if (record_length == 0) {
00090             continue;
00091         }
00092         const uint8_t type = params->advertisingData[i + 1]; // PDU Advertising // AD length 1B / AD type 1B / AD data 0-22B //
00093         const uint8_t* value = params->advertisingData + i + 2; //pointer adresse + i + 2, so AD data
00094         const uint8_t value_length = record_length - 1;
00095 
00096         if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { //0x09 is type of complete local name
00097             if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) { /* compares name LED with advertisingData*/
00098                 pc.printf(
00099                     "adv peerAddr[%02x %02x %02x %02x %02x %02x], LocalName %s, rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
00100                     params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2],
00101                     params->peerAddr[1], params->peerAddr[0], value, params->rssi, params->isScanResponse, params->type
00102                 );
00103                 printf("\r\n");
00104 
00105                 //create wanted ConnectionParameters (defined in nrf51822/target_nrf5/source/nrf5xGap.cpp)
00106                 para.minConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(100);
00107                 para.maxConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(100);
00108                 para.slaveLatency = 0;
00109                 para.connectionSupervisionTimeout = 600;
00110                 
00111                 BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, &para, NULL);
00112                 break;
00113             }
00114         }
00115         i += record_length;
00116     }
00117 }
00118 
00119 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) 
00120 {
00121     pc.printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().read());
00122     if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* LED characteristic of device (Read/Write) */
00123         ledCharacteristic        = *characteristicP;
00124     }
00125 }
00126 
00127 void writeResponseCallback(const GattWriteCallbackParams *response) 
00128 {
00129     if (response->handle == ledCharacteristic.getValueHandle()) { //handle is ID of connection
00130         //ledCharacteristic.read();
00131         //latency.stop();
00132         flagStart = 0;
00133         flagStop = 1;
00134         //latencyTime = latency.read_high_resolution_us();
00135         //latency.reset();
00136 
00137         //pc.printf("ledCharacteristic: %d %d\r\n",response->data[0],response->data[1]);
00138         //pc.printf("Latency Time: %d us \n",latencyTime);
00139         //writeVal(latencyTime);
00140         randNumber = rand()%10;    //number between 0 and 9
00141         /*pc.printf("triggerRead: handle %u, writeOp %u \r\n", response->connHandle, response->writeOp);
00142             for (unsigned index = 0; index < response->len; index++) {
00143                  printf("%c[%02x]", response->data[index], response->data[index]);
00144             }
00145         pc.printf("\r\n");*/
00146     }
00147 }
00148 
00149 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) 
00150 {
00151     if (params->role == Gap::CENTRAL) {
00152         BLE &ble = BLE::Instance();
00153         //ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
00154         ble.gattClient().launchServiceDiscovery(params->handle, NULL, characteristicDiscoveryCallback, 0xa000, 0xa001);
00155         
00156         uint16_t slaveLat = params->connectionParams->slaveLatency;
00157         uint16_t maxConnectionInt = params->connectionParams->maxConnectionInterval;
00158         uint16_t minConnectionInt = params->connectionParams->minConnectionInterval;
00159         uint16_t connectionTimeout = params->connectionParams->connectionSupervisionTimeout;
00160 
00161         pc.printf("slaveLatency %u, minConnection %u, maxConnection %u, connectionTimeout %u \n", slaveLat, minConnectionInt, maxConnectionInt, connectionTimeout);
00162         pc.printf("handle %u, role %u \n", params->handle, params->role);
00163         pc.printf("connected\r\n");
00164         pc.printf("\r\n");
00165     }
00166 }
00167 
00168 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) 
00169 {
00170     pc.printf("disconnected\r\n");
00171     /* Start scanning and try to connect again */
00172     BLE::Instance().gap().startScan(advertisementCallback);
00173     counter = 0;
00174 }
00175 
00176 void onBleInitError(BLE &ble, ble_error_t error)
00177 {
00178    /* Initialization error handling should go here */
00179 }
00180 
00181 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00182 {
00183     BLE&        ble   = params->ble;
00184     ble_error_t error = params->error;
00185 
00186     if (error != BLE_ERROR_NONE) {
00187         /* In case of error, forward the error handling to onBleInitError */
00188         onBleInitError(ble, error);
00189         return;
00190     }
00191 
00192     /* Ensure that it is the default instance of BLE */
00193     if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00194         return;
00195     }
00196 
00197     ble.gap().onDisconnection(disconnectionCallback);
00198     ble.gap().onConnection(connectionCallback);
00199 
00200     ble.gattClient().onDataWritten(writeResponseCallback);
00201 
00202     // scan interval: 400ms and scan window: 400ms.
00203     // Every 400ms the device will scan for 400ms
00204     // This means that the device will scan continuously.
00205     ble.gap().setScanParams(400, 400);
00206     ble.gap().startScan(advertisementCallback);
00207     
00208 }
00209 
00210 
00211 int main(void) {
00212     pc.baud(115200);
00213     
00214     ticker.attach(periodicCallback, 1); /* Blink LED every second */
00215     //button.rise(buttonPressedCallback);
00216     loop.attach(randCallback, 0.01);
00217     srand(time(NULL));
00218 
00219     BLE &ble = BLE::Instance();
00220     ble.init(bleInitComplete);
00221     pc.printf("Initialization complete... \n");
00222 
00223     counter = 0;
00224     //latency.reset();
00225 
00226     while (true) {
00227         ble.waitForEvent();
00228     }
00229 }