UDK + Shield

Dependencies:   DOGS102 ISL29011 MMA845x MPL3115A2 NCP5623B libmDot_1012-hotifx mbed-rtos mbed-src Senet_Packet X_NUCLEO_IKS01A1

Fork of MTDOT-EVBDemo_Senet by Dave Kjendal

Revision:
12:ad92bbb6312f
Parent:
10:658720d51610
Child:
14:07ff01da6bbf
--- a/main.cpp	Tue Aug 23 22:10:35 2016 +0000
+++ b/main.cpp	Tue Aug 23 23:35:00 2016 -0400
@@ -30,15 +30,12 @@
  *
  */
 
-// #define MTDOT_EVB
-
-//#define MTDOT_UDK
-
 #include "mbed.h"
 #include "senet_packet.h"
 
 // EVB Sensors
 #ifdef MTDOT_EVB
+
 #include "MMA845x.h"
 #include "MPL3115A2.h"
 #include "ISL29011.h"
@@ -46,8 +43,11 @@
 #include "DOGS102.h"
 #include "font_6x8.h"
 #include "MultiTech_Logo.h"
+
 #elif defined(MTDOT_UDK)
+
 #include "x_nucleo_iks01a1.h"
+
 #endif
 
 #include "mDot.h"
@@ -55,29 +55,9 @@
 #include <string>
 #include <vector>
 
-enum LED1_COLOR {
-    RED = 0,
-    GREEN = 1
-};
-
-/*
- * union for converting from 32-bit to 4 8-bit values
+/* 
+ * Board sensor data
  */
-union convert32 {
-    int32_t f_s;		// convert from signed 32 bit int
-    uint32_t f_u;		// convert from unsigned 32 bit int
-    uint8_t t_u[4];		// convert to 8 bit unsigned array
-};
-
-/*
- * union for converting from 16- bit to 2 8-bit values
- */
-union convert16 {
-    int16_t f_s;		// convert from signed 16 bit int
-    uint16_t f_u;		// convert from unsigned 16 bit int
-    uint8_t t_u[2];		// convert to 8 bit unsigned array
-};
-
 struct BoardSensorData
 {
     float temperature;
@@ -98,92 +78,75 @@
     BoardSensorData() { init(); }
 };
 
-//DigitalIn mDot02(PA_2);          				//  GPIO/UART_TX
-//DigitalOut mDot03(PA_3);         				//  GPIO/UART_RX
-//DigitalIn mDot04(PA_6);          				//  GPIO/SPI_MISO
-//DigitalIn mDot06(PA_8);          				//  GPIO/I2C_SCL
-//DigitalIn mDot07(PC_9);         				//  GPIO/I2C_SDA
+#ifdef MDOT_EVB
 
-#ifdef MDOT_EVB
-InterruptIn mDot08(PA_12);           			//  GPIO/USB       PB S1 on EVB
-InterruptIn mDot09(PA_11);           			//  GPIO/USB       PB S2 on EVB
+//DigitalIn mDot02(PA_2);  //  GPIO/UART_TX
+//DigitalOut mDot03(PA_3); //  GPIO/UART_RX
+//DigitalIn mDot04(PA_6);  //  GPIO/SPI_MISO
+//DigitalIn mDot06(PA_8);  //  GPIO/I2C_SCL
+//DigitalIn mDot07(PC_9);  //  GPIO/I2C_SDA
 
-//DigitalIn mDot11(PA_7);          				//  GPIO/SPI_MOSI
+InterruptIn mDot08(PA_12);  //  GPIO/USB       PB S1 on EVB
+InterruptIn mDot09(PA_11);  //  GPIO/USB       PB S2 on EVB
+
+//DigitalIn mDot11(PA_7);   //  GPIO/SPI_MOSI
 
-InterruptIn mDot12(PA_0);          				//  GPIO/UART_CTS  PRESSURE_INT2 on EVB
-DigitalOut mDot13(PC_13,1);        				//  GPIO           LCD_C/D
-InterruptIn mDot15(PC_1);          				//  GPIO           LIGHT_PROX_INT on EVB
-InterruptIn mDot16(PA_1);          				//  GPIO/UART_RTS  ACCEL_INT2 on EVB
-DigitalOut mDot17(PA_4,1);         				//  GPIO/SPI_NCS   LCD_CS on EVB
+InterruptIn mDot12(PA_0);    //  GPIO/UART_CTS  PRESSURE_INT2 on EVB
+DigitalOut  mDot13(PC_13,1); //  GPIO           LCD_C/D
+InterruptIn mDot15(PC_1);    //  GPIO           LIGHT_PROX_INT on EVB
+InterruptIn mDot16(PA_1);    //  GPIO/UART_RTS  ACCEL_INT2 on EVB
+DigitalOut mDot17(PA_4,1);   //  GPIO/SPI_NCS   LCD_CS on EVB
 
-//DigitalIn mDot18(PA_5);          				//  GPIO/SPI_SCK
+//DigitalIn mDot18(PA_5);    //  GPIO/SPI_SCK
 
 //DigitalInOut mDot19(PB_0,PIN_INPUT,PullNone,0); // GPIO         PushPull LED Low=Red High=Green set MODE=INPUT to turn off
-AnalogIn mDot20(PB_1);             				//  GPIO          Current Sense Analog in on EVB
-
-Serial debugUART(PA_9, PA_10);				// mDot debug UART
+AnalogIn mDot20(PB_1);         //  GPIO          Current Sense Analog in on EVB
+Serial debugUART(PA_9, PA_10); // mDot debug UART
+//Serial mDotUART(PA_2, PA_3); // mDot external UART mDot02 and mDot03
+I2C mDoti2c(PC_9,PA_8);	// mDot External I2C mDot6 and mDot7
 
-//Serial mDotUART(PA_2, PA_3);					// mDot external UART mDot02 and mDot03
-
-I2C mDoti2c(PC_9,PA_8);							// mDot External I2C mDot6 and mDot7
-
-SPI mDotspi(PA_7,PA_6,PA_5);					// mDot external SPI mDot11, mDot4, and mDot18
+SPI mDotspi(PA_7,PA_6,PA_5); // mDot external SPI mDot11, mDot4, and mDot18
 #elif defined(MTDOT_UDK)
 
-Serial debugUART(USBTX, USBRX);				// mDot debug UART
+Serial debugUART(USBTX, USBRX); // mDot debug UART
 
 #endif
 
-/* **** replace these values with the proper public or private network settings ****
- * config_network_nameand config_network_pass are for private networks.
+/* 
+ * LoRaWAN Configuration 
  */
-static std::string config_network_name = "TAB-CubeNet";
-static std::string config_network_pass = "1nt3gral";
-static uint8_t config_frequency_sub_band = 0;
-static bool config_adr_on = true;
+static uint8_t app_id[8]   = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01};
+static uint8_t app_key[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 
-/*  config_app_id and config_app_key are for public networks. */
-static uint8_t app_id[8] = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01};
-std::vector<uint8_t> config_app_id(app_id,app_id+sizeof(app_id)/sizeof(uint8_t));
-static uint8_t app_key[16] = {0xB4,0xAD,0x1A,0x25,0x69,0x7F,0xF6,0x8E,0xD3,0x4B,0x83,0xC4,0xB6,0xC0,0xF2,0x3C}; // 9C49
-							  //{0xA0,0xC8,0x3D,0xD1,0x7B,0x32,0x97,0x1B,0x71,0xDC,0x53,0xB5,0x4D,0x89,0xC6,0x19};
-							  //{0xFC,0xD1,0x8B,0x22,0x9E,0xA0,0xDA,0x4F,0x6B,0x8F,0x39,0x26,0xAF,0x07,0x8A,0x05}; //9CFF
-							  //{0xB3,0x53,0x00,0xDA,0xF6,0x0A,0x6C,0xF9,0x54,0x57,0x79,0x50,0x6F,0x19,0xE1,0x3A}; //9C35
-std::vector<uint8_t> config_app_key(app_key,app_key+sizeof(app_key)/sizeof(uint8_t));
-
-uint8_t result, pckt_time=100;
-char data;
-unsigned char test;
-char txtstr[17];
-int32_t num_whole, mdot_ret;
-uint32_t pressure;
-int16_t num_frac;
-
-uint8_t position_value = 0xFF; // 00 unknown, 01 is flat, 02 is vertical
-uint8_t reflected_value = 0xFE;
-bool    position_changed = true;
-
-bool exit_program = false;
+static std::vector<uint8_t> config_app_id(app_id,app_id+sizeof(app_id)/sizeof(uint8_t));
+static std::vector<uint8_t> config_app_key(app_key,app_key+sizeof(app_key)/sizeof(uint8_t));
+static uint8_t config_frequency_sub_band = 0;
+static bool    config_adr_on = true;
 
 #ifdef  MTDOT_EVB
 MMA845x_DATA accel_data;
 MPL3115A2_DATA baro_data;
 uint16_t  lux_data;
-MMA845x* evbAccel      = NULL;
-MPL3115A2* evbBaro     = NULL;
-ISL29011* evbAmbLight  = NULL;
-NCP5623B* evbBackLight = NULL;
-DOGS102* evbLCD        = NULL;
+MMA845x* evbAccel;     
+MPL3115A2* evbBaro;
+ISL29011* evbAmbLight;
+NCP5623B* evbBackLight;
+DOGS102* evbLCD;
 
-#elif defined(MTDOT_UDK)
-static X_NUCLEO_IKS01A1 *mems_shield; 
-#endif
+/* 
+ * EVB Application state 
+ */
+uint8_t position_value   = 0xFF; // 00 unknown, 01 is flat, 02 is vertical
+uint8_t reflected_value  = 0xFE;
+bool    position_changed = true;
 
-mDot* mdot_radio;
-
-convert32 convertl;
-convert16 converts;
-
+unsigned char test;
+char     txtstr[17];
+int32_t  num_whole;
+uint32_t pressure;
+int16_t  num_frac;
+uint8_t  result, pckt_time=100;
+char     data;
 // flags for pushbutton debounce code
 bool pb1_low = false;
 bool pb2_low = false;
@@ -194,12 +157,46 @@
 void pb2_debounce(void const *args);
 Thread* thread_3;
 
-void log_error(mDot* dot, const char* msg, int32_t retval);
-
 void config_pkt_xmit (void const *args);
 
+#elif defined(MTDOT_UDK)
+
+static X_NUCLEO_IKS01A1 *mems_shield; 
+
+#endif 
+
+mDot* mdot_radio;
+bool  exit_program = false;
+
+/* 
+ * Process downlink
+ */
+static void ReceiveData(std::vector<uint8_t> frame);
+
+static bool checkForExit(bool exit);
+
+/*
+ *  prints of mDot error 
+ */
+void log_error(mDot* dot, const char* msg, int32_t retval)
+{
+    printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str());
+}
+
+/*
+ * Send frame
+ */
 void SendFrame(std::vector<uint8_t> frame)
 {
+#if 0
+    static uint32_t count = 0; 
+    printf("%lu: send data: ",count++);
+    for(uint32_t i = 0;i < frame.size();i++)
+        printf("%02X",frame[i]);
+    printf("\r\n");
+#endif
+
+    int32_t mdot_ret;
     if ((mdot_ret = mdot_radio->send(frame)) != mDot::MDOT_OK) {
         log_error(mdot_radio, "failed to send", mdot_ret);
     } 
@@ -209,44 +206,49 @@
         if ((mdot_ret = mdot_radio->recv(frame)) != mDot::MDOT_OK) {
             log_error(mdot_radio,"failed to recv:", mdot_ret);
         } else {
+
             printf("recv data: ");
             for(uint32_t i = 0;i < frame.size();i++)
                 printf("%02X",frame[i]);
             printf("\r\n");
-            reflected_value = frame[0];
-            if(reflected_value == position_value)
-            {
-#if MTDOT_EVB
-                evbBackLight->setLEDCurrent(16);
-#endif
-                position_changed = false;
-            }
-#if MTDOT_EVB
-            else 
-            {
-                evbBackLight->setLEDCurrent(0);
-            }
-#endif
+
+            ReceiveData(frame);
         }
     }
 }
 
 #ifdef MDOT_EVB
+
+void ReceiveData(std::vector<uint8_t> frame)
+{
+    reflected_value = frame[0];
+
+    if(reflected_value == position_value)
+    {
+        evbBackLight->setLEDCurrent(16);
+        position_changed = false;
+    }
+    else 
+    {
+        evbBackLight->setLEDCurrent(0);
+    }
+}
+
 void BoardInit()
 {
     static Thread thread_1(pb1_debounce);	 // threads for de-bouncing pushbutton switches
     static Thread thread_2(pb2_debounce);
 
     debugUART.baud(115200);
-//  mDotUART.baud(9600);    // mdot UART unused but available on external connector
+    // mDotUART.baud(9600);    // mdot UART unused but available on external connector
 
-    thread_3 = new Thread(config_pkt_xmit);				// start thread that sends LoRa packet when SW2 pressed
+    thread_3 = new Thread(config_pkt_xmit); // start thread that sends LoRa packet when SW2 pressed
 
-    evbAccel = new MMA845x(mDoti2c,MMA845x::SA0_VSS); 	// setup Accelerometer
-    evbBaro = new MPL3115A2(mDoti2c);					// setup Barometric sensor
-    evbAmbLight = new ISL29011(mDoti2c);		 		// Setup Ambient Light Sensor
-    evbBackLight = new NCP5623B(mDoti2c);				// setup backlight and LED 2 driver chip
-    evbLCD = new DOGS102(mDotspi, mDot17, mDot13);		// setup LCD
+    evbAccel = new MMA845x(mDoti2c,MMA845x::SA0_VSS); // setup Accelerometer
+    evbBaro = new MPL3115A2(mDoti2c); // setup Barometric sensor
+    evbAmbLight = new ISL29011(mDoti2c); // Setup Ambient Light Sensor
+    evbBackLight = new NCP5623B(mDoti2c); // setup backlight and LED 2 driver chip
+    evbLCD = new DOGS102(mDotspi, mDot17, mDot13); // setup LCD
 
     /*
      *  Setup SW1 as program stop function
@@ -313,11 +315,11 @@
 
     printf("Start of Test\n\r");
 
-    osDelay (500);			// allows other threads to process
+    osDelay (500); // allows other threads to process
     printf("shutdown LED:\n\r");
     evbBackLight->shutdown();
 
-    osDelay (500);			// allows other threads to process
+    osDelay (500); // allows other threads to process
     printf("Turn on LED2\n\r");
     evbBackLight->setLEDCurrent(16);
 
@@ -385,7 +387,7 @@
      * Test Accelerometer XYZ data ready bit to see if acquisition complete
      */
     do {
-        osDelay(100);			// allows other threads to process
+        osDelay(100); // allows other threads to process
         result = evbAccel->getStatus();
     } while ((result & MMA845x::XYZDR) == 0 );
 
@@ -502,53 +504,166 @@
     printf("finished iteration %d\n\r",(++i));
 }
 
-uint32_t PrepareFrame(std::vector<uint8_t> frame, BoardSensorData &data)
+uint32_t PrepareFrame(std::vector<uint8_t> &frame, BoardSensorData &data)
+{
+    if((reflected_value != position_value)|| position_changed)
+    {
+        frame.clear();
+        // we will send a simple byte descriptor of the current position of the device: 01 is laying flat, 02 is vertically oriented
+        frame.push_back(0x00);
+        frame.push_back(position_value);
+        return 2;
+    }
+
+    return 0;
+}
+
+bool checkForExit(bool _exit)
+{
+    // Check for PB1 press during network join attempt
+    if (exit_program) {
+      printf("Exiting program\n\r");
+
+      evbLCD->clearBuffer();
+      sprintf(txtstr,"Exiting Program");
+      evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+      if(_exit)
+          exit(1);
+    } 
+
+    return false;
+}
+
+void ExitingProgram()
 {
-    if (i % pckt_time != 0) 
-        return 0;
+    evbBaro->triggerOneShot();
+    do {
+        osDelay(200);			// allows other threads to process
+        result = evbBaro->getStatus();
+    } while ((result & MPL3115A2::PTDR) == 0 );
+
+    baro_data = evbBaro->getAllData(true);
+    printf ("minBaro=%ld maxBaro=%ld minTemp=%d maxTemp=%d\n\r", baro_data._minbaro, baro_data._maxbaro,
+            baro_data._mintemp, baro_data._maxtemp);
+    evbLCD->clearBuffer();
+    sprintf(txtstr,"Exiting Program");
+    evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+    printf("End of Test\n\r");
+}
+
 
-    frame.clear();
-    // we will send a simple byte descriptor of the current position of the device: 01 is laying flat, 02 is vertically oriented
-    frame.push_back(0x00);
+void wait()
+{
+    osDelay(1000);
+}
+
+/*
+ * Sets pb1_low flag. Slag is cleared in pb1_debounce thread
+ */
+void pb1ISR(void)
+{
+    if (!pb1_low)
+        pb1_low = true;
+}
+
+/*
+ * Debounces pb1. Also exits program if pushbutton 1 is pressed
+ */
+void pb1_debounce(void const *args)
+{ 
+    static uint8_t count = 0;
 
-    frame.push_back(position_value);
-    /*frame.push_back(0x0E);			// key for Current Acceleration 3-Axis Value
-    converts.f_s = accel_data._x *4;		// shift data 2 bits while retaining sign
-    frame.push_back(converts.t_u[1]);	// get 8 MSB of 14 bit value
-    converts.f_s = accel_data._y * 4;		// shift data 2 bits while retaining sign
-    frame.push_back(converts.t_u[1]);	// get 8 MSB of 14 bit value
-    converts.f_s = accel_data._z * 4;		// shift data 2 bits while retaining sign
-    frame.push_back(converts.t_u[1]);	// get 8 MSB of 14 bit value
-    */
-    /*
-    frame.push_back(0x08);			// key for Current Pressure Value
-    convertl.f_u = pressure;				// pressure data is 20 bits unsigned
-    frame.push_back(convertl.t_u[2]);
-    frame.push_back(convertl.t_u[1]);
-    frame.push_back(convertl.t_u[0]);
-    frame.push_back(0x05);			// key for Current Ambient Light Value
-    converts.f_u = lux_data;				// data is 16 bits unsigned
-    frame.push_back(converts.t_u[1]);
-    frame.push_back(converts.t_u[0]);
-    frame.push_back(0x0B);			// key for Current Temperature Value
-    converts.f_s = baro_data._temp;		// temperature is signed 12 bit
-    frame.push_back(converts.t_u[1]);
-    frame.push_back(converts.t_u[0]);
-*/
+    while (true) { 
+        if (pb1_low && (mDot08 == 0))
+            count++;
+        else {
+            count = 0;
+            pb1_low = false;
+        } 
+
+        if (count == 5) 
+            exit_program = true; 
+
+        Thread::wait(5);
+    }
+}
+
+/*
+ * Sets pb2_low flag. Flag is cleared in pb2_debounce thread
+ */
+void pb2ISR(void)
+{
+    if (!pb2_low)
+        pb2_low = true;
+}
+
+/*
+ * Debounces pb2. Also changes packet transmit time to every other,
+ * every fifth, or every tenth sample when SW2 pushed
+ * Also triggers a thread to transmit a configuration packet
+ */
+void pb2_debounce(void const *args)
+{
+    static uint8_t count = 0;
+
+    while (true) {
 
-    if((reflected_value != position_value)||(position_changed)||(0 == (i%100)))
-    {
+        if (pb2_low && (mDot09 == 0))
+            count++;
+        else {
+            count = 0;
+            pb2_low = false;
+        }
+        
+        if (count == 5){ 
+            if (pckt_time >= 5)
+                pckt_time /= 2;
+            else 
+                pckt_time = 20; 
+            
+            //thread_3->signal_set(0x10);		// signal config_pkt_xmit to send packet
+            position_changed = true;
+        } 
+        Thread::wait(5);
+    }
+ }
+
+/*
+ * Thread that is triggered by SW2 ISR. Sends a packet to the LoRa server with the new Packet Transmission time setting
+ */
+void config_pkt_xmit (void const *args)
+{
+    int32_t mdot_ret;
+
+    std::vector<uint8_t> data;
+
+    while (true) {
+        Thread::signal_wait(0x10);		// wait for pb2ISR to signal send
+        data.clear();
+        data.push_back(0x0F);			// key for Configuration data (packet transmission timer)
+        data.push_back(pckt_time);
+
+        if ((mdot_ret = mdot_radio->send(data)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "failed to send config data", mdot_ret);
+        } else {
+            printf("sent config data to gateway\r\n");
+        }
     }
 }
 
 #elif defined(MTDOT_UDK)
 
+void ReceiveData(std::vector<uint8_t> frame)
+{
+}
+
 void BoardInit()
 { 
     debugUART.baud(115200); 
 
     // ST X-NUCLEO-IKS01A1 MEMS Shield
-    mems_shield = X_NUCLEO_IKS01A1::Instance(); 
+    mems_shield = X_NUCLEO_IKS01A1::Instance(NULL, NC); 
+    // mems_shield = X_NUCLEO_IKS01A1::Instance(); 
 }
 
 void PostJoinInit() { }
@@ -579,14 +694,11 @@
    printf("%s: Temperature=%f, Pressure=%f, x=%ld, y=%ld, z=%ld\r\n",__func__,
            data.temperature, data.pressure, 
            data.accel_x, data.accel_y, data.accel_z);
-
-   osDelay(5000);
-
 }
 
-uint32_t PrepareFrame(std::vector<uint8_t> frame, BoardSensorData &data)
+uint32_t PrepareFrame(std::vector<uint8_t> &frame, BoardSensorData &data)
 {
-    static uint8_t buffer[64];
+    static uint8_t buffer[256];
     uint16_t xyz_mask = 0;
 
     // Sensor packet type serialized to the LMIC frame buffer
@@ -604,6 +716,18 @@
     return frame.size();
 }
 
+bool checkForExit(bool _exit) { return false;}
+
+
+void ExitingProgram()
+{
+    printf("Exiting\n\r");
+}
+
+void wait()
+{
+    osDelay(5000);
+}
 
 
 #else
@@ -612,7 +736,10 @@
 
 void mDotConfigureAndJoin()
 { 
-    bool ok;
+    bool    ok;
+    int32_t mdot_ret;
+
+    printf("Configuring mDot\r\n");
     
     // get mDot handle
     mdot_radio = mDot::getInstance();
@@ -649,15 +776,13 @@
         for (uint8_t i=0; i<mdot_EUI.size(); i++) {
             printf("%02x ", mdot_EUI[i]);
         }
-        printf("\n\r");
-
-
-// Setting up the mDot with network information.
+        printf("\n\r"); 
+        
 
-    /*
-     * This call sets up private or public mode on the MTDOT. Set the function to true if
-     * connecting to a public network
-     */
+      /*
+       * This call sets up private or public mode on the MTDOT. Set the function to true if
+       * connecting to a public network
+       */
        printf("setting Public Network Mode\r\n");
        if ((mdot_ret = mdot_radio->setPublicNetwork(true)) != mDot::MDOT_OK) {
            log_error(mdot_radio, "failed to set Public Network Mode", mdot_ret);
@@ -665,15 +790,15 @@
        mdot_radio->setTxDataRate(mDot::DR0);
        mdot_radio->setTxPower(14);
        mdot_radio->setJoinRetries(1);
-       mdot_radio->setJoinMode(mDot::OTA);
+       mdot_radio->setJoinMode(mDot::OTA); 
 
-    /*
-     * Frequency sub-band is valid for NAM only and for Private networks should be set to a value
-     * between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only.
-     * This function can be commented out for EU networks
-     */
+      /*
+       * Frequency sub-band is valid for NAM only and for Private networks should be set to a value
+       * between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only.
+       * This function can be commented out for EU networks
+       */
        printf("setting frequency sub band\r\n");
-        if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
+       if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
             log_error(mdot_radio, "failed to set frequency sub band", mdot_ret);
             ok = false;
         }
@@ -683,30 +808,34 @@
             log_error(mdot_radio, "failed to set ADR", mdot_ret);
             ok = false;
         }
-    /*
-     * setNetworkName is used for private networks.
-     * Use setNetworkID(AppID) for public networks
-     */ 
+
+       /*
+        * setNetworkName is used for private networks.
+        * Use setNetworkID(AppID) for public networks
+        */ 
         printf("setting network name\r\n");
         if ((mdot_ret = mdot_radio->setNetworkId(config_app_id)) != mDot::MDOT_OK) {
             log_error(mdot_radio, "failed to set network name", mdot_ret);
             ok = false;
         }
 
-    /*
-     * setNetworkPassphrase is used for private networks
-     * Use setNetworkKey for public networks
-     */ 
-        printf("setting network password\r\n");
+       /*
+        * setNetworkPassphrase is used for private networks
+        * Use setNetworkKey for public networks
+        */ 
+        printf("setting network key\r\n");
         if ((mdot_ret = mdot_radio->setNetworkKey(config_app_key)) != mDot::MDOT_OK) {
             log_error(mdot_radio, "failed to set network password", mdot_ret);
             ok = false;
         } 
+
+        checkForExit(true);
+
     }while(ok == false);
-  
+
   // attempt to join the network
   printf("joining network\r\n");
-  while (((mdot_ret = mdot_radio->joinNetwork()) != mDot::MDOT_OK) && (!exit_program)) {
+  while ((mdot_ret = mdot_radio->joinNetwork()) != mDot::MDOT_OK) {
       log_error(mdot_radio,"failed to join network:", mdot_ret);
       if (mdot_radio->getFrequencyBand() == mDot::FB_868){
           mdot_ret = mdot_radio->getNextTxMs();
@@ -715,175 +844,42 @@
           mdot_ret = 0;
       } 
 
+      checkForExit(true);
+
       printf("delay = %lu\n\r",mdot_ret);
       osDelay(mdot_ret + 10000);
   } 
 }
 
+
 int main()
 {
     BoardSensorData sensorData;
+    std::vector<uint8_t> frame;
     
     // Board specific initialization
     BoardInit(); 
 
-    // mDot configuration and join
-    //mDotConfigureAndJoin();
-
-    PostJoinInit();
+    // Configure mDot and join
+    mDotConfigureAndJoin();
 
-  /*
-   * Check for PB1 press during network join attempt
-   */
-  if (exit_program) {
-      printf("Exiting program\n\r");
-
-#ifdef MDOT_EVB
-      evbLCD->clearBuffer();
-      sprintf(txtstr,"Exiting Program");
-      evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
-#endif
-      exit(1);
-  } 
+    // Do board specific post join configuration
+    PostJoinInit();
 
     /*
      * Main data acquisition loop
      */
     do {
-        std::vector<uint8_t> frame;
-        
         // Acquire sensor values
         ReadSensors(sensorData);
-        
+
         // Send sensor packets
         if( PrepareFrame(frame, sensorData) > 0 ){
             SendFrame( frame );
         }
-
-    } while(!exit_program);
-
-
-#ifdef MDOT_EVB
-    evbBaro->triggerOneShot();
-    do {
-        osDelay(200);			// allows other threads to process
-        result = evbBaro->getStatus();
-    } while ((result & MPL3115A2::PTDR) == 0 );
-
-    baro_data = evbBaro->getAllData(true);
-    printf ("minBaro=%ld maxBaro=%ld minTemp=%d maxTemp=%d\n\r", baro_data._minbaro, baro_data._maxbaro,
-            baro_data._mintemp, baro_data._maxtemp);
-    evbLCD->clearBuffer();
-    sprintf(txtstr,"Exiting Program");
-    evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
-#endif
-
-    printf("End of Test\n\r");
-}
-
-#ifdef MDOT_EVB
-/*
- * Sets pb1_low flag. Slag is cleared in pb1_debounce thread
- */
-void pb1ISR(void)
-{
-	if (!pb1_low)
-		pb1_low = true;
-}
+        wait();
 
-/*
- * Debounces pb1. Also exits program if pushbutton 1 is pressed
- */
-void pb1_debounce(void const *args)
-{
-
-    static uint8_t count = 0;
-
-    while (true) {
+    } while(!checkForExit(false));
 
-        if (pb1_low && (mDot08 == 0))
-			count++;
-        else {
-        	count = 0;
-        	pb1_low = false;
-        }
-        
-		if (count == 5) 
-			exit_program = true;
-		
-        Thread::wait(5);
-    }
-}
-
-/*
- * Sets pb2_low flag. Flag is cleared in pb2_debounce thread
- */
-void pb2ISR(void)
-{
-	if (!pb2_low)
-		pb2_low = true;
+    ExitingProgram();
 }
-
-/*
- * Debounces pb2. Also changes packet transmit time to every other,
- * every fifth, or every tenth sample when SW2 pushed
- * Also triggers a thread to transmit a configuration packet
- */
-void pb2_debounce(void const *args)
-{
-
-    static uint8_t count = 0;
-
-    while (true) {
-
-        if (pb2_low && (mDot09 == 0))
-			count++;
-        else {
-        	count = 0;
-        	pb2_low = false;
-        }
-        
-		if (count == 5){
-
-			if (pckt_time >= 5)
-				pckt_time /= 2;
-			else pckt_time = 20;
-
-			//thread_3->signal_set(0x10);		// signal config_pkt_xmit to send packet
-			position_changed = true;
-		}
-		
-        Thread::wait(5);
- 	}
- }
-#endif
-
-/*
- *  Function that print clear text verion of mDot errors
- */
-void log_error(mDot* dot, const char* msg, int32_t retval)
-{
-    printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str());
-}
-
-/*
- * Thread that is triggered by SW2 ISR. Sends a packet to the LoRa server with the new Packet Transmission time setting
- */
-void config_pkt_xmit (void const *args)
-{
-
-    std::vector<uint8_t> data;
-
-    while (true) {
-        Thread::signal_wait(0x10);		// wait for pb2ISR to signal send
-        data.clear();
-        data.push_back(0x0F);			// key for Configuration data (packet transmission timer)
-        data.push_back(pckt_time);
-
-        if ((mdot_ret = mdot_radio->send(data)) != mDot::MDOT_OK) {
-            log_error(mdot_radio, "failed to send config data", mdot_ret);
-        } else {
-            printf("sent config data to gateway\r\n");
-        }
-    }
-}