2018-10-22: This is a temporary repository to fix issue mbed OS issue 8344. I'm reverting to an earlier mbed revision that isn't messed up. Expect mbed to fix the linker issue in the next release and I'll remove this repository. I havne't tested the code at this revision - sorry!

Dependencies:   BLE_API mbed mbedtls nRF51822

Revision:
8:46c5e0bfab05
Parent:
7:0a8bbb6dea16
Child:
9:1ea51b2048a8
--- 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