Florian Fida / Mbed 2 deprecated opentrigger-nRF51

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_Button by Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* nRF51 mbed opentrigger example
00002  * Copyright (c) 2016 Florian Fida
00003  *
00004  * based on 'Demo for an Input Service'
00005  * https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_Button/
00006  * 
00007  *
00008  * Licensed under the Apache License, Version 2.0 (the "License");
00009  * you may not use this file except in compliance with the License.
00010  * You may obtain a copy of the License at
00011  *
00012  *     http://www.apache.org/licenses/LICENSE-2.0
00013  *
00014  * Unless required by applicable law or agreed to in writing, software
00015  * distributed under the License is distributed on an "AS IS" BASIS,
00016  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00017  * See the License for the specific language governing permissions and
00018  * limitations under the License.
00019  */
00020 
00021 #include "mbed.h"
00022 #include "ble/BLE.h"
00023 
00024 DigitalOut  led1(LED1); /* RED   : Indicating a pressed button */
00025 DigitalOut  led2(LED2); /* GREEN : Blinking to indicate that the device is running */
00026 DigitalOut  led3(LED3); /* BLUE  : Only on when advertising */
00027 
00028 InterruptIn button0(P0_15);
00029 InterruptIn button1(P0_16);
00030 InterruptIn button2(P0_17);
00031 InterruptIn button3(P0_18);
00032 InterruptIn button4(P0_19);
00033 InterruptIn button5(P0_20);
00034 
00035 const uint16_t        MIN_ADVERT_INTERVAL = 50; /* msec */
00036 static uint8_t        gpio_states[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; /* initial state is up */
00037 static uint8_t        event_id = 0;
00038 
00039 enum {
00040     RELEASED = 0,
00041     PRESSED,
00042     IDLE
00043 };
00044 static uint8_t buttonState = IDLE;
00045 
00046 void blinkLed(void){
00047     led2 = !led2;
00048 }
00049 
00050 void button0PressedCallback(void)
00051 {
00052     /* Note that the buttonPressedCallback() executes in interrupt context, so it is safer to access
00053      * BLE device API from the main thread. */
00054     buttonState = PRESSED;
00055     gpio_states[0]=0x00;
00056     event_id++;
00057 }
00058 
00059 void button0ReleasedCallback(void)
00060 {
00061     /* Note that the buttonReleasedCallback() executes in interrupt context, so it is safer to access
00062      * BLE device API from the main thread. */
00063     buttonState = RELEASED;
00064     gpio_states[0]=0x01;
00065     event_id++;
00066 }
00067 
00068 
00069 // Callbacks for the other 5 Buttons
00070 void button1PressedCallback(void) { buttonState = PRESSED;  gpio_states[1]=0x00; event_id++; }
00071 void button1ReleasedCallback(void){ buttonState = RELEASED; gpio_states[1]=0x01; event_id++; }
00072 void button2PressedCallback(void) { buttonState = PRESSED;  gpio_states[2]=0x00; event_id++; }
00073 void button2ReleasedCallback(void){ buttonState = RELEASED; gpio_states[2]=0x01; event_id++; }
00074 void button3PressedCallback(void) { buttonState = PRESSED;  gpio_states[3]=0x00; event_id++; }
00075 void button3ReleasedCallback(void){ buttonState = RELEASED; gpio_states[3]=0x01; event_id++; }
00076 void button4PressedCallback(void) { buttonState = PRESSED;  gpio_states[4]=0x00; event_id++; }
00077 void button4ReleasedCallback(void){ buttonState = RELEASED; gpio_states[4]=0x01; event_id++; }
00078 void button5PressedCallback(void) { buttonState = PRESSED;  gpio_states[5]=0x00; event_id++; }
00079 void button5ReleasedCallback(void){ buttonState = RELEASED; gpio_states[5]=0x01; event_id++; }
00080 
00081 // Just in case
00082 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00083 {
00084     BLE::Instance().gap().startAdvertising();
00085 }
00086 
00087 void periodicCallback(void)
00088 {
00089     blinkLed();
00090 }
00091 
00092 /**
00093  * This function is called when the ble initialization process has failled
00094  */
00095 void onBleInitError(BLE &ble, ble_error_t bt_error)
00096 {
00097     /* Initialization error handling should go here */
00098     
00099     printf("bt_error=%i\n\r",bt_error);
00100     error("Panic!");
00101 }
00102 
00103 bool gpioSet(void){
00104     return
00105         gpio_states[0] == 0x00 ||
00106         gpio_states[1] == 0x00 ||
00107         gpio_states[2] == 0x00 ||
00108         gpio_states[3] == 0x00 ||
00109         gpio_states[4] == 0x00 ||
00110         gpio_states[5] == 0x00
00111     ;
00112 }
00113 
00114 void updateManufacturerData(void){
00115     
00116     // disable interrupts while building the package to avoid a race condition
00117     __disable_irq();  
00118     
00119     // http://tokencube.com/bluetooth-sensor.html
00120     uint8_t data[] = { 
00121         0xee, 0xff,                         // Tokencube Manufacturer ID
00122         0x04,                               // Token Module Version
00123         0x01,                               // Firmware Version
00124         0x11,                               // Page 1 of 1
00125         0x07, gpioSet() ? 0x01 : 0x00,      // PIR value (0x00 = off, 0x01 = on)
00126         0x0F, event_id,                     // EventId (0x00 - 0xFF, every time a button gets pressed, the EventId changes)
00127         gpio_states[0], gpio_states[1],     // 6 GPIO Values (0x00 = down, 0x01 = up)
00128         gpio_states[2], gpio_states[3], 
00129         gpio_states[4], gpio_states[5],
00130     };
00131     
00132     __enable_irq();
00133     BLE::Instance().gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data, sizeof(data));
00134 }
00135 
00136 /**
00137  * Callback triggered when the ble initialization process has finished
00138  */
00139 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00140 {
00141     BLE&        ble   = params->ble;
00142     ble_error_t error = params->error;
00143 
00144     if (error != BLE_ERROR_NONE) {
00145         /* In case of error, forward the error handling to onBleInitError */
00146         onBleInitError(ble, error);
00147         return;
00148     }
00149 
00150     /* Ensure that it is the default instance of BLE */
00151     if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00152         return;
00153     }
00154     
00155     uint8_t macAddress[6] = {0x00};
00156     BLEProtocol::AddressType_t pubAddr = BLEProtocol::AddressType::PUBLIC;
00157     ble.gap().getAddress(&pubAddr, macAddress);
00158     
00159     /* change device MAC address */
00160     //const uint8_t address1[] = {0xe7,0xAA,0xAA,0xAA,0xAA,0xAA}; 
00161     //ble.gap().setAddress(pubAddr, address1);
00162 
00163     ble.gap().onDisconnection(disconnectionCallback);
00164 
00165     /* setup advertising */
00166     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00167     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00168     
00169     ble.gap().setAdvertisingInterval(MIN_ADVERT_INTERVAL);
00170     updateManufacturerData();
00171     error = ble.gap().startAdvertising();
00172     if (error != BLE_ERROR_NONE) onBleInitError(ble, error);
00173     
00174     // Print Interval and MAC Address
00175     uint16_t minInterval = ble.gap().getMinAdvertisingInterval();
00176     printf("MinAdvertisingInterval = %i\n\r", minInterval);
00177     printf("MAC Address = %02X:%02X:%02X:%02X:%02X:%02X\n\r", macAddress[5], macAddress[4], macAddress[3], macAddress[2], macAddress[1], macAddress[0]);
00178 
00179 }
00180 
00181 int main(void)
00182 {  
00183     // Turn off all LED's
00184     led1 = !0; led2 = !0; led3 = !0;
00185     
00186     // Put all GPIO's in PullUp mode, so we do not need pullup resistors.
00187     button0.mode(PullUp);
00188     button1.mode(PullUp);
00189     button2.mode(PullUp);
00190     button3.mode(PullUp);
00191     button4.mode(PullUp);
00192     button5.mode(PullUp);
00193     
00194     // Setup handler for all buttons
00195     button0.fall(button0PressedCallback);
00196     button0.rise(button0ReleasedCallback);
00197     button1.fall(button1PressedCallback);
00198     button1.rise(button1ReleasedCallback);
00199     button2.fall(button2PressedCallback);
00200     button2.rise(button2ReleasedCallback);
00201     button3.fall(button3PressedCallback);
00202     button3.rise(button3ReleasedCallback);
00203     button4.fall(button4PressedCallback);
00204     button4.rise(button4ReleasedCallback);
00205     button5.fall(button5PressedCallback);
00206     button5.rise(button5ReleasedCallback);
00207     
00208     // This will make our green led blink
00209     Ticker ticker;
00210     ticker.attach(periodicCallback, 1);
00211 
00212     BLE &ble = BLE::Instance();
00213     ble.init(bleInitComplete);
00214     
00215     /* SpinWait for initialization to complete. This is necessary because the BLE object is used in the main loop below. */
00216     while (ble.hasInitialized()  == false) { /* spin loop */ }
00217     
00218     uint8_t cnt = 0;
00219     while (true) {
00220         
00221         // we only care about situations where a button was pressed
00222         if (buttonState != IDLE) {
00223             if(buttonState == PRESSED)  led1=!1; 
00224             if(buttonState == RELEASED) led1=!0; 
00225             ticker.attach(periodicCallback, 1);
00226             updateManufacturerData();
00227             cnt = 0;
00228             buttonState = IDLE;
00229         }
00230 
00231         
00232         // start advertising
00233         if(cnt < 1){
00234             ble.gap().startAdvertising();
00235             led3 = !1;
00236         }else if(cnt == 1){
00237             updateManufacturerData();
00238         }
00239         
00240         // stop advertising after 3 cycles
00241         if(cnt > 3){
00242             ble.gap().stopAdvertising();
00243             led3 = !0;
00244             led2 = !0;
00245             ticker.detach();
00246             deepsleep();
00247         }else{
00248             if(!gpioSet()) cnt++;
00249         }
00250         
00251         ble.waitForEvent();
00252         //printf("cnt=%i\n\r",cnt);
00253     }
00254 }