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

Files at this revision

API Documentation at this revision

Comitter:
Shaun Nelson
Date:
Tue Aug 23 23:35:00 2016 -0400
Parent:
11:3be85ca325d1
Child:
13:0ed4127ba30f
Child:
14:07ff01da6bbf
Commit message:
Disabled UDK MEMS sensor shield free fall dection because the device appears to get interrupt bound

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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");
-        }
-    }
-}