BLE ADV Gateway, converts advertisement to proper JSON serial output

Dependencies:   BLE_API mbed mbedtls nRF51822

Revision:
8:46c5e0bfab05
Parent:
7:0a8bbb6dea16
Child:
9:1ea51b2048a8
diff -r 0a8bbb6dea16 -r 46c5e0bfab05 main.cpp
--- a/main.cpp	Tue Jan 12 10:12:43 2016 +0000
+++ b/main.cpp	Mon Jul 10 03:57:10 2017 +0000
@@ -1,51 +1,192 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2006-2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+/*
+
+ Eric Tsai
+ todo:  hash mac to create unqiue identifier for "my" sensors.
+
+
  */
 
+//required to call the ecb functions
+extern "C"
+{
+   #include "nrf_ecb.h"
+}
+ 
 #include "mbed.h"
 #include "toolchain.h"
 #include "ble/BLE.h"
 #include "TMP_nrf51/TMP_nrf51.h"
 
-static Ticker     ticker;
-static TMP_nrf51  tempSensor;
-static bool       triggerTempValueUpdate = false;
-static DigitalOut alivenessLED(LED1, 1);
+//comment out when done with debug uart, else eats batteries
+#define MyDebugEnb 1
+
+//Pin "P0.4" on nRF51822 = mbed "p4".
+//InterruptIn is pulled-up.  GND the pin to activate.
+
+// waveshare board ******
+//InterruptIn button1(p10);
+//InterruptIn button2(p11);
+
+// purple board ******
+InterruptIn button1(p23);
+InterruptIn button2(p24);
+
+
+//Serial device(p9, p11);  // tx, rx, purple board and Rigado
+#if MyDebugEnb
+// if you see ~1mA consumption during sleep, that's because uart is enabled.
+Serial device(p9, p11);  //nRF51822 uart :  TX=p9.  RX=p11
+#endif
+
+//InterruptIn button(p4);     //Pin P0.4 on  = mbed "p3"; 
+
+
+static Ticker tic_adv;   //stop adv
+static Ticker tic_debounce; //debounce I/O
+static Ticker tic_periodic; //regular updates
+//static TMP_nrf51  tempSensor;
+static bool flag_update_io = false;
+static bool flag_periodic_call = false;
+static bool flag_detach_adv_tic = false;
+static bool flag_set_debounce_tic = false;  //not used
+
+//static DigitalOut alivenessLED(LED1, 1);
+float mySensor = 2.0f;
+
+
+/* Optional: Device Name, add for human read-ability */
+const static char     DEVICE_NAME[] = "CUU";
 
+/* You have up to 26 bytes of advertising data to use. */
+/*
+Advertisement
+
+DECvolt:3.11111111,mag:1
+AdvData[0-2] = Look for DEC on observer
+AdvData[3] = beginning of data
+*/
+//full with nullls
+static uint8_t AdvData[] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};   /* Example of hex data */
+char buffer[10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //battery analog reading
+uint8_t magnet_near=0;
+
+
+
+static uint8_t key[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
+//26 bytes adv data
+static uint8_t encrypted[26] = {0x0,0x0,0x0,0x1,0x1,0x1,0x2,0x2,0x2,0x3,0x3,0x3,0x4,0x4,0x4,0x5,0x5,0x5,0x6,0x6,0x6,0x7,0x7,0x7,0x8,0x8};   /* Example of hex data */
+//static uint8_t key_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
+static uint8_t key_buf[16] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1, 0x2};
+static uint8_t src_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
+static uint8_t des_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
+
+//const static uint8_t AdvData[] = {"ChangeThisData"};         /* Example of character data */
+
+
+
+/* **** NOT USED **** */
+//16byte UUID loading happens here
+//Look at <GapAdvertisingData.h> for rest of definition
 struct ApplicationData_t {
-    uint16_t                     applicationSpecificId; /* An ID used to identify temperature value in the manufacture specific AD data field */
-    TMP_nrf51::TempSensorValue_t tmpSensorValue;        /* User defined application data */
+    //Byte 0:  AppID High Byte
+    //Byte 1:  AppID Low Byte
+    //Byte 2:  sensor High Word
+    //Byte 3:
+    //Byte 4:
+    //Byte 5:  sensor Low Byte
+    
+    
+    //app ID is 16 bit, (0xFEFE)
+    uint16_t    applicationSpecificId; /* An ID used to identify temperature value in the manufacture specific AD data field */
+    
+    //float = 32-bit.  
+    //tsai: change this to uint32_t!!!
+    TMP_nrf51::TempSensorValue_t tmpSensorValue;        /* this is a float (32-bit), user data */
 } PACKED;
 
-void periodicCallback(void)
+
+
+void debounce_Callback(void)
+{
+    tic_debounce.detach();
+    flag_set_debounce_tic = false;      //not used
+    flag_update_io = true;  //start advertising
+    /* Note that the buttonPressedCallback() executes in interrupt context, so it is safer to access
+     * BLE device API from the main thread. */
+    //buttonState = PRESSED;
+}
+
+//----- button rising ---
+void buttonPressedCallback(void)
 {
-    alivenessLED = !alivenessLED;  /* Do blinky on LED1 while we're waiting for BLE events. */
+
+
+    //flag_update_io = true;
+    
+    tic_debounce.attach(debounce_Callback, 1); //ok to attach multiple times, first one wins
+    
+
+    //buttonState = PRESSED;
+    
+    /*
+    if (flag_set_debounce_tic == false)
+    {
+        flag_set_debounce_tic = true;
+        
+    }
+    */
+}
 
-    /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
+//----- button falling ---
+void buttonReleasedCallback(void)
+{
+    
+
+    //flag_update_io = true;
+    
+    tic_debounce.attach(debounce_Callback, 1);
+    
+    
+  
+}
+
+
+void stop_adv_Callback(void)
+{
+    //stops advertising after X seconds
+    /* Note that the Callback() executes in interrupt context, so it is safer to do
      * heavy-weight sensor polling from the main thread (where we should be able to block safely, if needed). */
-    triggerTempValueUpdate = true;
+    
+    //tic_adv.detach();
+    
+    flag_detach_adv_tic = true;
+    //ble.gap().stopAdvertising();
+    
+
+}
+
+
+
+
+
+void periodic_Callback(void)
+{
+    flag_update_io = true;
+    flag_periodic_call = true;
 }
 
 void setupApplicationData(ApplicationData_t &appData)
 {
-    static const uint16_t APP_SPECIFIC_ID_TEST = 0xFEFE;
+    // two byte ID:  0xFEFE
+    static const uint16_t APP_SPECIFIC_ID_TEST = 0xFEFE;        //2 byte application ID
 
     appData.applicationSpecificId = APP_SPECIFIC_ID_TEST;
-    appData.tmpSensorValue        = tempSensor.get();
+    //appData.tmpSensorValue        = tempSensor.get();
+    appData.tmpSensorValue        = mySensor;
 }
 
+
+
 /**
  * This function is called when the ble initialization process has failled
  */
@@ -72,43 +213,416 @@
     if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
         return;
     }
+    
+    /* Set device name characteristic data */
+    ble.gap().setDeviceName((const uint8_t *) DEVICE_NAME);
 
     /* Setup advertising payload */
+    //set modes "no EDR", "discoverable" for beacon type advertisements
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
-    ApplicationData_t appData;
-    setupApplicationData(appData);
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t));
+    
+    //set device profile in ADV/GATT
+    //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
+    
+    //set advertising data (ADV data)
+    //ApplicationData_t appData;
+    //setupApplicationData(appData);
+    //in /BLE_API/ble/GapAdvertisingData.h:  sets payload (uuid)
+    //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t));
+
+    //from GAP example
+    /* Sacrifice 2B of 31B to AdvType overhead, rest goes to AdvData array you define */
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, AdvData, sizeof(AdvData));
+
+    /* Setup advertising parameters:  not connectable */
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
+    ble.gap().setAdvertisingInterval(300);  //one advertisment every 300ms.  Self tickers, so you don't have to worry.
+
+
+
+    //don't start advertising on init.  Only advertise on pin interrupt.
+    //ble.gap().startAdvertising();
+}
+
 
-    /* Setup advertising parameters */
-    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
-    ble.gap().setAdvertisingInterval(500);
+//https://developer.mbed.org/users/MarceloSalazar/notebook/measuring-battery-voltage-with-nordic-nrf51x/
+void my_analogin_init(void)
+{
+    NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
+    NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
+                      (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
+                      (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
+                      (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) |
+                      (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
+}
 
-    ble.gap().startAdvertising();
+uint16_t my_analogin_read_u16(void)
+{
+    NRF_ADC->CONFIG     &= ~ADC_CONFIG_PSEL_Msk;
+    NRF_ADC->CONFIG     |= ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos;
+    NRF_ADC->TASKS_START = 1;
+    
+    
+    //while loop doesn't actually loop until reading comlete, use a wait.
+    while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {};
+    wait_ms(2);
+
+    //save off RESULT before disabling.
+    //uint16_t myresult = (uint16_t)NRF_ADC->RESULT;
+    
+    //disable ADC to lower bat consumption
+    //NRF_ADC->TASKS_STOP = 1;
+    //NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled;    //disable to shutdown ADC & lower bat consumption
+    
+    return (uint16_t)NRF_ADC->RESULT; // 10 bit
+    //return myresult;
 }
 
 int main(void)
 {
-    ticker.attach(periodicCallback, 2); /* trigger sensor polling every 2 seconds */
+
+#if MyDebugEnb
+    device.baud(9600);
+    device.printf("started sensor node 36 ");
+    device.printf("\r\n");
+#endif
+
+    
+    
+    Timer myTimer;  //timed advertising
+    myTimer.start();
+
+
+    AdvData[0] = 0x44;          //D
+    AdvData[1] = 0x45;          //E
+    AdvData[2] = 0x43;          //C
+    AdvData[3] = 0x22;          //"
+    AdvData[4] = 0x76;          //V volt
+    AdvData[5] = 0x6f;          //o
+    AdvData[6] = 0x22;          //"
+    AdvData[7] = 0x3a;          //:
+    AdvData[8] = 0x24;          //3     #
+    AdvData[9] = 0x24;          //.     #
+    AdvData[10] = 0x24;         //1     #
+    AdvData[11] = 0x24;         //1     #
+    AdvData[12] = 0x2c;         //,     
+    AdvData[13] = 0x22;         //" mag
+    AdvData[14] = 0x6d;         //a
+    AdvData[15] = 0x22;         //"
+    AdvData[16] = 0x3a;         //:
+    AdvData[17] = 0x24;         //0 or 1, 30 or 31
+
+    button1.fall(buttonPressedCallback);
+    button1.rise(buttonReleasedCallback);
+    button1.mode(PullNone);
+    button1.fall(NULL);
+    button1.rise(NULL); 
 
     BLE &ble = BLE::Instance();
     ble.init(bleInitComplete);
+    
+    //debug uart
+    //device.baud(115200);
+    float bat_reading;  //hold battery voltage reading (Vbg/Vcc)
+    
+    my_analogin_init();//routes band-gap to analog input
 
     /* SpinWait for initialization to complete. This is necessary because the
      * BLE object is used in the main loop below. */
-    while (ble.hasInitialized()  == false) { /* spin loop */ }
+    while (ble.hasInitialized() == false) { /* spin loop */ }
+    
+    //every X seconds, sends period update, up to 1800 (30 minutes)
+    tic_periodic.attach(periodic_Callback, 10);
 
     while (true) {
-        if (triggerTempValueUpdate) {
+        
+        uint16_t mySeconds =(uint16_t)(myTimer.read_ms()/1000); //problem:  mySeconds is only 2 byte
+        //reading the ADV value, only goes up to 0-255;
+        //reading the uart:  current time in seconds: -1782, goes negative.
+        //need to be able to count 1800 seconds since that's the length of timer.
+        
+#if MyDebugEnb
+        device.printf("current time in seconds: %d \r\n", mySeconds);
+#endif
+        //**** set which pin should be interrupt, set pullups ***
+        
+        //set both pins to pull-up, so they're not floating when we read state
+        button1.mode(PullUp);
+        button2.mode(PullUp);
+        
+        //wait_ms(300);   //contact settle
+        
+
+        //AdvData[12] is automatically CR?  why?
+        
+        //0x33 0x2E 0x33 0x32 0x13
+        //   3    .    3    2   CR
+        
+        //expect either button1 or button2 is grounded, b/c using SPDT reed switch
+        //the "common" pin on the reed switch should be on GND
+        uint8_t button1_state = button1.read();
+        uint8_t button2_state = button2.read();
+        
+        
+        //let's just update the pins on every wake.  Insurance against const drain.
+        //if state == 0, pin is grounded.  Unset interrupt and float pin
+        //set the other input
+        if ( (button1_state == 0) && (button2_state == 1) )
+        {
+            magnet_near = 1;
+            //AdvData[4] = 0x11;  //dont' set ADV data directly.  Using json now, need spacing
+            //button1.disable_irq() //don't know if disables IRQ on port or pin
+            button1.fall(NULL);     //disable interrupt
+            button1.rise(NULL);     //disable interrupt
+            button1.mode(PullNone); //float pin to save battery
+            
+            //button2.disable_irq() //don't know if disables IRQ on port or pin
+            button2.fall(buttonReleasedCallback);     //disable interrupt
+            button2.rise(buttonReleasedCallback);     //disable interrupt
+            button2.mode(PullUp); //float pin to save battery
+        }
+        else if ( (button1_state == 1) && (button2_state == 0) )       //assume other pin is open circuit
+        {
+            magnet_near = 0;
+            //AdvData[4] = 0x22;    //dont' set ADV data directly.  Using json now, need spacing
+            //button1.disable_irq() //don't know if disables IRQ on port or pin
+            button1.fall(buttonReleasedCallback);     //disable interrupt
+            button1.rise(buttonReleasedCallback);     //disable interrupt
+            button1.mode(PullUp); //float pin to save battery
+            
+            //button2.disable_irq() //don't know if disables IRQ on port or pin
+            button2.fall(NULL);     //disable interrupt
+            button2.rise(NULL);     //disable interrupt
+            button2.mode(PullNone); //float pin to save battery
+        }    
+        else    //odd state, shouldn't happen, suck battery and pullup both pins
+        {
+            magnet_near = 2;
+            //AdvData[4] = 0x33;
+            //button1.disable_irq() //don't know if disables IRQ on port or pin
+            button1.fall(buttonReleasedCallback);     //disable interrupt
+            button1.rise(buttonReleasedCallback);     //disable interrupt
+            button1.mode(PullUp); //float pin to save battery
+            
+            //button2.disable_irq() //don't know if disables IRQ on port or pin
+            button2.fall(buttonReleasedCallback);     //disable interrupt
+            button2.rise(buttonReleasedCallback);     //disable interrupt
+            button2.mode(PullUp); //float pin to save battery
+        }         
+        
+        
+        if (flag_update_io) {
             /* Do blocking calls or whatever hardware-specific action is
              * necessary to poll the sensor. */
+
+            //analog reading consumes 940uA if not disabled
+            bat_reading = (float)my_analogin_read_u16();    
+            bat_reading = (bat_reading * 3.6) / 1024.0;
+#if MyDebugEnb
+            device.printf("bat reading: %f \r\n", bat_reading);
+#endif
+
+            //memset(&buffer[0], 0, sizeof(buffer));      //clear out buffer
+            //sprintf (buffer, "%f.2", bat_reading);    //don't know what i'm doing
+            //sprintf (buffer, "%.2f", bat_reading);
+            //AdvData[8] = buffer[0]; //"3"=0x33
+            //AdvData[9] = buffer[1]; //"."=0x2E
+            //AdvData[10] = buffer[2];//"3"=0x33
+            //AdvData[11] = buffer[3];//"2"=0x32
+            
+            //disable ADC
+            NRF_ADC->TASKS_STOP = 1;
+            NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled;    //disable to shutdown ADC & lower bat consumption
+
+            //***********************************
+            //form JSON string in ADV_DATA
+            //1)  volts starts at AdvData[8]
+            
+
+            memset(&AdvData[0], 0, sizeof(AdvData));
+            uint8_t JSON_loc=0; //DEC"vo": <---
+
+            AdvData[JSON_loc] = 0x44;          //D
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x45;          //E
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x43;          //C
+            JSON_loc++;
+            AdvData[JSON_loc] = mySeconds & 0xFF;           //reserved for timer
+            JSON_loc++;
+            AdvData[JSON_loc] = (mySeconds >> 8) & 0xFF;;           //reserved for timer
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x22;          //"
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x76;          //V volt
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x6f;          //o
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x6C;          //l
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x74;          //t
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x22;          //"
+            JSON_loc++;
+            AdvData[JSON_loc] = 0x3a;          //:
+            JSON_loc++;
+    
+    
+            
+            //write battery voltage
+            uint8_t total_chars;
+            memset(&buffer[0], 0, sizeof(buffer));      //clear out buffer
+            total_chars = sprintf (buffer, "%.2f", bat_reading);    //returns total number of characters
+
+#if MyDebugEnb
+            device.printf("char buff: %c%c%c%c \r\n", buffer[0], buffer[1], buffer[2], buffer[3]);
+            device.printf("num chars: %d \r\n", total_chars);
+#endif
+
+            for (int i=0; i < total_chars; i++)
+            {
+                AdvData[JSON_loc] = buffer[i];
+                JSON_loc++;
+#if MyDebugEnb
+                device.printf("JSON_loc: %d     buf[]:%c \r\n", JSON_loc, buffer[i]);
+#endif
+            } //JSON_loc left at location of next character
+            
+            //DEC"vo":3.11,"
+            AdvData[JSON_loc] = 0x2c;       //,
+            JSON_loc++;
+            
+            AdvData[JSON_loc] = 0x22;       //" start mag
+            JSON_loc++;
+            
+            AdvData[JSON_loc] = 0x6d;       //m
+            JSON_loc++;
+            
+            AdvData[JSON_loc] = 0x61;       //a
+            JSON_loc++;
+            
+            AdvData[JSON_loc] = 0x67;       //g
+            JSON_loc++;
+            
+            if (flag_periodic_call)
+            {
+                //AdvData[JSON_loc] = 0x2f;       // "/"
+                //JSON_loc++;
+                AdvData[JSON_loc] = 0x2f;       // "/"
+                JSON_loc++;
+                AdvData[JSON_loc] = 0x70;       // "p"
+                JSON_loc++;
+            }//end if period call
+            
+            AdvData[JSON_loc] = 0x22;       //"
+            JSON_loc++;
+
+            AdvData[JSON_loc] = 0x3a;       //:
+            JSON_loc++;
+            
+            //prep magnet location (1 or 0) for char[]
+            memset(&buffer[0], 0, sizeof(buffer));      //clear out buffer
+            //magnet_near is an integer
+            total_chars = sprintf (buffer, "%d", magnet_near);    //returns total number of characters
+            for (int i=0; i < total_chars; i++)
+            {
+                AdvData[JSON_loc] = buffer[i];
+                JSON_loc++;
+            } //JSON_loc left at location of next character
+            
+            //MUST null terminate for JSON to read correctly, else get intermittent JSON parse errors at gateway
+            //happens when string is shorter than last string, get trash left overs
+            //not really needed after clearning AdvData at start.
+            
+            
+            //AdvData[JSON_loc] = 0x0;    //null terminate here
+
             ApplicationData_t appData;
             setupApplicationData(appData);
-            ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *) &appData, sizeof(ApplicationData_t));
+            
+
+            for (int i=0; i<16; i++)
+            {
+                src_buf[i] = AdvData[i+3];
+            }
 
-            triggerTempValueUpdate = false;
+            //nrf_ecb_set_key(key_buf);
+            nrf_ecb_init();
+            nrf_ecb_set_key(key_buf);
+            bool successful_ecb = nrf_ecb_crypt(des_buf, src_buf);
+#if MyDebugEnb
+            device.printf("success ecb = %d \r\n", successful_ecb);
+            device.printf("src_buf: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \r\n", src_buf[0], src_buf[1], src_buf[2], src_buf[3], src_buf[4], src_buf[5], src_buf[6], src_buf[7], src_buf[8], src_buf[9], src_buf[10], src_buf[11], src_buf[12], src_buf[13], src_buf[14], src_buf[15]);
+            device.printf("des_buf: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \r\n", des_buf[0], des_buf[1], des_buf[2], des_buf[3], des_buf[4], des_buf[5], des_buf[6], des_buf[7], des_buf[8], des_buf[9], des_buf[10], des_buf[11], des_buf[12], des_buf[13], des_buf[14], des_buf[15]);
+#endif
+            for (int i=0; i<16; i++)
+            {
+                AdvData[i+3] = des_buf[i];
+            }
+            
+            //ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *) &appData, sizeof(ApplicationData_t));
+            ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, AdvData, sizeof(AdvData));
+            
+            flag_update_io = false;
+            flag_periodic_call = false;
+            
+            //GAP::AddressType_t *myType;
+            //GAP::Address_t myAddress
+            //ble_error_t getAddress(Gap::AddressType_t *typeP, Gap::Address_t address)
+            //ble.gap().getAddress(myType, myAddress);
+            //ble.gap().getAddress(Gap::AddressType_t *typeP, Gap::Address_t address);
+            uint8_t mac[6] = {0x0,0x0,0x0,0x0,0x0,0x0};
+            ble.getAddress(0,mac);  //NOTE:  last byte of MAC (as shown on phone app) is at mac[0], not mac[6];
+#if MyDebugEnb
+            device.printf("mac = ");
+            for (int i=0; i<6; i++)
+            {
+                device.printf("%x:", mac[i]);
+            }
+            device.printf("\r\n");
+#endif
+            ble.gap().startAdvertising();
+            tic_adv.attach(stop_adv_Callback, 2); /* trigger turn off advertisement after X seconds */
+
+            /*
+            Timer myTimer;  //timed advertising
+            myTimer.start();
+            uint32_t duration = myTimer.read_ms();
+            
+            //do this as a ticker instead of keeping processor on
+            while (duration < 15000)            //advertise for 1000 ms
+            {
+                duration = myTimer.read_ms();   //read miliseconds
+            }
+            myTimer.stop();
+            ble.gap().stopAdvertising();
+            */
+        
+        }//end flag_update_io
+        
+        
+        /*
+        if (flag_set_debounce_tic == true)
+        {
+            tic_debounce.attach();
+            //flag_set_debounce_tic = false;
+            
         }
+        */
+        
+        //if (trigger_Detach_ADV_Tick == false)
+        //{  
+        //}
+        if (flag_detach_adv_tic == true)    //Stop Advertising
+        {
+            ble.gap().stopAdvertising();    //may be safer to execute BLE operations in main
+            tic_adv.detach();
+            flag_detach_adv_tic = false;
+        }
+        //device.printf("Input Voltage: %f\n\r",bat_reading);
+        
+        ble.waitForEvent(); //sleeps until interrupt
+        
 
-        ble.waitForEvent();
-    }
-}
+    }//end forever while
+}//end main