Demonstration program for Multitech System MTDOT-EVB an evaluation board for the mDot LoRa module

Dependencies:   DOGS102 ISL29011 MMA845x MPL3115A2 NCP5623B libmDot mbed-rtos mbed

Revision:
8:6bf4d69651b7
Parent:
4:49d19abdfd04
--- a/main.cpp	Thu Oct 22 19:36:34 2015 +0000
+++ b/main.cpp	Thu Nov 19 22:51:01 2015 +0000
@@ -2,7 +2,7 @@
  * @file    main.cpp
  * @brief   Main application for mDot-EVB demo
  * @author  Tim Barr  MultiTech Systems Inc.
- * @version 1.03
+ * @version 1.05
  * @see
  *
  * Copyright (c) 2015
@@ -32,6 +32,11 @@
  *					public netework setup. Swapped \n and \r in prinf calls because
  *					Windows seems to be picky about the order
  *
+ * 1.05 TAB 11/17/15 Changed baud rate for debug from 921k to 115k. Added code to support
+ *					 868 MHz band operation. Added mutex around certain mDot radio commands.
+ *					 Changed network name and passphrase. Changed pb references to sw to
+ *					 match MTDOT-BOX overlay. Changed function of SW1 from end program to
+ *					 cycle through power levels and data rates.
  */
 
 #include "mbed.h"
@@ -76,8 +81,8 @@
 //DigitalIn mDot06(PA_8);          				//  GPIO/I2C_SCL
 //DigitalIn mDot07(PC_9);         				//  GPIO/I2C_SDA
 
-InterruptIn mDot08(PA_12);           			//  GPIO/USB       PB S1 on EVB
-InterruptIn mDot09(PA_11);           			//  GPIO/USB       PB S2 on EVB
+InterruptIn mDot08(PA_12);           			//  GPIO/USB       PB SW1 on EVB
+InterruptIn mDot09(PA_11);           			//  GPIO/USB       PB SW2 on EVB
 
 //DigitalIn mDot11(PA_7);          				//  GPIO/SPI_MOSI
 
@@ -101,17 +106,13 @@
 SPI mDotspi(PA_7,PA_6,PA_5);					// mDot external SPI mDot11, mDot4, and mDot18
 
 /* **** replace these values with the proper public or private network settings ****
- * config_network_nameand config_network_pass are for private networks.
+ * config_network_name and config_network_pass are for private networks.
  */
-//settings for my bench
-static std::string config_network_name = "TAB-CubeNet";
-static std::string config_network_pass = "1nt3gral";
-static uint8_t config_frequency_sub_band = 5;
 
 //Default network server settings
-//static std::string config_network_name = "YOUR-NETWORK-NAME";
-//static std::string config_network_pass = "YOUR-NETWORK-PASSPHRASE";
-//static uint8_t config_frequency_sub_band = 3;
+static std::string config_network_name = "Multitech";
+static std::string config_network_pass = "Multitech";
+static uint8_t config_frequency_sub_band = 3;
 
 /*  config_app_id and config_app_key are for public networks.
 static uint8_t app_id[8] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
@@ -120,15 +121,17 @@
 std::vector<uint8_t> config_app_key;
 */
 
-uint8_t result, pckt_time=10;
+uint8_t result, mdot_freq;
+uint8_t  pckt_time = 8;
+uint16_t xmit_delay = 8;
 char data;
 unsigned char test;
 char txtstr[17];
-int32_t num_whole, mdot_ret;
+int32_t num_whole, mdot_ret, join_delay;
 uint32_t pressure;
 int16_t num_frac;
-
-bool exit_program = false;
+uint8_t sf_val = mDot::SF_7;
+uint8_t pwr_val = 11; // dBm
 
 MMA845x_DATA accel_data;
 MPL3115A2_DATA baro_data;
@@ -139,18 +142,20 @@
 NCP5623B* evbBackLight;
 DOGS102* evbLCD;
 mDot* mdot_radio;
+Mutex mdot_mutex;
 
 convert32 convertl;
 convert16 converts;
 
 // flags for pushbutton debounce code
-bool pb1_low = false;
-bool pb2_low = false;
+bool sw1_low = false;
+bool sw2_low = false;
+bool toggle_text = false;
 
-void pb1ISR(void);
-void pb2ISR(void);
-void pb1_debounce(void const *args);
-void pb2_debounce(void const *args);
+void sw1ISR(void);
+void sw2ISR(void);
+void sw1_debounce(void const *args);
+void sw2_debounce(void const *args);
 Thread* thread_3;
 
 void log_error(mDot* dot, const char* msg, int32_t retval);
@@ -163,12 +168,13 @@
     std::vector<uint8_t> mdot_data;
     std::vector<uint8_t> mdot_EUI;
     uint16_t i = 0;
+    uint8_t j =0;
 
-    debugUART.baud(921600);
+    debugUART.baud(115200);
 //  mDotUART.baud(9600);    // mdot UART unused but available on external connector
 
-    Thread thread_1(pb1_debounce);						// threads for de-bouncing pushbutton switches
-    Thread thread_2(pb2_debounce);
+    Thread thread_1(sw1_debounce);						// threads for de-bouncing pushbutton switches
+    Thread thread_2(sw2_debounce);
 
     thread_3 = new Thread(config_pkt_xmit);				// start thread that sends LoRa packet when SW2 pressed
 
@@ -182,7 +188,7 @@
      *  Setup SW1 as program stop function
      */
     mDot08.disable_irq();
-    mDot08.fall(&pb1ISR);
+    mDot08.fall(&sw1ISR);
 
     /*
      *  need to call this function after rise or fall because rise/fall sets
@@ -196,14 +202,14 @@
      *  Setup SW2 as packet time change
      */
     mDot09.disable_irq();
-    mDot09.fall(&pb2ISR);
+    mDot09.fall(&sw2ISR);
 
     /*
      *  need to call this function after rise or fall because rise/fall sets
      *  mode to PullNone
      */
     mDot09.mode(PullUp);
- 
+
     mDot09.enable_irq();
 
     /*
@@ -221,21 +227,14 @@
 
     evbLCD->writeBitmap(0,0,MultiTech_Logo);
 
-    sprintf(txtstr,"MTDOT");
-    evbLCD->writeText(24,3,font_6x8,txtstr,strlen(txtstr));
-    sprintf(txtstr,"Evaluation");
-    evbLCD->writeText(24,4,font_6x8,txtstr,strlen(txtstr));
-    sprintf(txtstr,"Board");
-    evbLCD->writeText(24,5,font_6x8,txtstr,strlen(txtstr));
-
-    evbLCD->endUpdate();
-
-   printf("\r\n setup mdot\r\n");
+    printf("\r\n setup mdot\r\n");
 
     // get a mDot handle
     mdot_radio = mDot::getInstance();
 
     if (mdot_radio) {
+        mdot_mutex.lock(); 	// lock mdot before setting configuration
+
         // reset to default config so we know what state we're in
         mdot_radio->resetConfig();
 
@@ -243,41 +242,60 @@
         mdot_radio->setActivityLedPin(PB_0);
         mdot_radio->setActivityLedEnable(true);
 
-        // Read node ID
+        // Read node ID and frequency band
         mdot_EUI = mdot_radio->getDeviceId();
+        mdot_freq = mdot_radio->getFrequencyBand();
+
         printf("mDot EUI = ");
 
         for (i=0; i<mdot_EUI.size(); i++) {
             printf("%02x ", mdot_EUI[i]);
         }
         printf("\r\n");
+        sprintf(txtstr,"MTDOT EVB");
+        printf("mDot Frequency = ");
+        if (mdot_freq == mDot::FB_868) {
+            printf( "868 MHz\r\n");
+            sprintf(txtstr,"%s 868 MHz",txtstr);
+        } else {
+            printf("915 MHz\r\n");
+            sprintf(txtstr,"%s 915 MHz",txtstr);
+        }
+
+        evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
+        sprintf(txtstr,"Sensor Demo");
+        evbLCD->writeText(24,4,font_6x8,txtstr,strlen(txtstr));
+
+        evbLCD->endUpdate();
 
 
 // Setting up the mDot with network information.
 
-/*
- * This call sets up private or public mode on the MTDOT. Set the function to true if
- * connecting to a public network
- */
-       printf("setting Private Network Mode\r\n");
-       if ((mdot_ret = mdot_radio->setPublicNetwork(false)) != mDot::MDOT_OK) {
-           log_error(mdot_radio, "failed to set Public Network Mode", mdot_ret);
-       }
-
-/*
- * 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) {
-            log_error(mdot_radio, "failed to set frequency sub band", mdot_ret);
+        /*
+         * This call sets up private or public mode on the MTDOT. Set the function to true if
+         * connecting to a public network
+         */
+        printf("setting Private Network Mode\r\n");
+        if ((mdot_ret = mdot_radio->setPublicNetwork(false)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "failed to set Public Network Mode", mdot_ret);
         }
 
-/*
- * setNetworkName is used for private networks.
- * Use setNetworkID(AppID) for public 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
+         */
+        if (mdot_freq == mDot::FB_915) {
+            printf("setting frequency sub band\r\n");
+            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);
+            }
+        }
+
+        /*
+         * setNetworkName is used for private networks.
+         * Use setNetworkID(AppID) for public networks
+         */
 
 // 		config_app_id.assign(app_id,app_id+7);
 
@@ -287,10 +305,10 @@
             log_error(mdot_radio, "failed to set network name", mdot_ret);
         }
 
-/*
- * setNetworkPassphrase is used for private networks
- * Use setNetworkKey for public networks
- */
+        /*
+         * setNetworkPassphrase is used for private networks
+         * Use setNetworkKey for public networks
+         */
 
 // 		config_app_key.assign(app_key,app_key+15);
 
@@ -300,35 +318,68 @@
             log_error(mdot_radio, "failed to set network password", mdot_ret);
         }
 
-        // attempt to join the network
-        printf("joining network\r\n");
-        while (((mdot_ret = mdot_radio->joinNetwork()) != mDot::MDOT_OK) && (!exit_program)) {
-            log_error(mdot_radio,"failed to join network:", mdot_ret);
-            if (mdot_radio->getFrequencyBand() == mDot::FB_868){
-            	mdot_ret = mdot_radio->getNextTxMs();
-            }
-        	else {
-        		mdot_ret = 0;
-         	}
-        		
-            printf("delay = %lu\r\n",mdot_ret);
-            osDelay(mdot_ret + 1);
+        /*
+          * Setting TX power for radio. Max allowed is +14dBm for EU and +20 dBm for NAM. Default is +11 dBm
+          */
+        printf("setting TX Power Level to %2d dBm\r\n", pwr_val);
+        if ((mdot_ret = mdot_radio->setTxPower(pwr_val)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "failed to set TX power level", mdot_ret);
         }
 
         /*
-         * Check for PB1 press during network join attempt
+         * Setting TX data rate for radio. Max allowed is SF_12 for EU and SF10 dBm for NAM. Default is SF_9
          */
-        if (exit_program) {
-            printf("Exiting program\r\n");
-            evbLCD->clearBuffer();
-            sprintf(txtstr,"Exiting Program");
-            evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
-            exit(1);
+        printf("setting TX data rate to SF_7\r\n");
+        if ((mdot_ret = mdot_radio->setTxDataRate(sf_val)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "failed to set TX data rate", mdot_ret);
         }
 
+        mdot_mutex.unlock();		// unlock mdot mutex before join attempt so SW1 can work
+
+        // attempt to join the network
+        printf("joining network\r\n");
+        do {
+            mdot_mutex.lock();		// lock mdot mutex before join attempt
+            mdot_ret = mdot_radio->joinNetwork();
+            mdot_mutex.unlock();		// unlock mdot mutex after join attempt so SW1 can work
+
+            if (mdot_ret != mDot::MDOT_OK) {
+                log_error(mdot_radio,"failed to join network:", mdot_ret);
+
+                if (toggle_text)
+                    sprintf(txtstr," > Join Failed <");
+                else
+                    sprintf(txtstr," < Join Failed >");
+
+                evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
+                if (mdot_radio->getFrequencyBand() == mDot::FB_868) {
+                    join_delay = mdot_radio->getNextTxMs();
+                } else {
+                    join_delay = 10;
+                }
+                printf("delay = %lu\r\n",join_delay);
+                osDelay(join_delay + 1);
+                toggle_text = !toggle_text;
+            }
+            /*
+             * Setting TX power and Data Rate for radio just in case user requested by SW2
+             */
+            mdot_mutex.lock();		// lock mdot mutex before setting change
+            mdot_radio->setTxPower(pwr_val);
+            mdot_radio->setTxDataRate(sf_val);
+            mdot_mutex.unlock();		// unlock mdot mutex after settings change
+
+        } while (mdot_ret != mDot::MDOT_OK);
+
+        sprintf(txtstr,"*Network Joined*");
+        evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
     } else {
-        printf("radio setup failed\r\n");
-        //exit(1);
+        sprintf(txtstr,"Radio Init Failed!");
+        evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+        printf("%s\r\n",txtstr);
+        exit(1);
     }
 
     osDelay(200);
@@ -393,25 +444,17 @@
     evbBackLight->setLEDCurrent(0);
 
     /*
-     * Check for PB1 press during network join attempt
-     */
-    if (exit_program) {
-        printf("Exiting program\r\n");
-        evbLCD->clearBuffer();
-        sprintf(txtstr,"Exiting Program");
-        evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
-        exit(1);
-    }
-
-    /*
      * Main data acquisition loop
      */
-    pckt_time = 10;
-    i = 0;
 
+	i = 0;
+	
     do {
         evbLCD->startUpdate();
-        evbLCD->clearBuffer();
+        // clear LCD line 0-6 only
+        sprintf(txtstr, "                 ");
+        for (j=0; j<6; j++)
+            evbLCD->writeText(0,j,font_6x8,txtstr,strlen(txtstr));
 
         /*
          * Test Accelerometer XYZ data ready bit to see if acquisition complete
@@ -426,14 +469,12 @@
          */
         accel_data = evbAccel->getXYZ();
 
-        sprintf(txtstr,"Accelerometer");
+        sprintf(txtstr, "Accel: x = %d", accel_data._x);
         evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr));
-        sprintf(txtstr, "x = %d", accel_data._x);
-        evbLCD->writeText(20,1,font_6x8,txtstr,strlen(txtstr));
         sprintf(txtstr, "y = %d", accel_data._y);
-        evbLCD->writeText(20,2,font_6x8,txtstr,strlen(txtstr));
+        evbLCD->writeText(42,1,font_6x8,txtstr,strlen(txtstr));
         sprintf(txtstr, "z = %d", accel_data._z );
-        evbLCD->writeText(20,3,font_6x8,txtstr,strlen(txtstr));
+        evbLCD->writeText(42,2,font_6x8,txtstr,strlen(txtstr));
 
         /*
          * Trigger a Pressure reading
@@ -457,7 +498,7 @@
         num_whole = pressure >> 2;			// 18 bit integer significant
         num_frac = (pressure & 0x3) * 25;		// 2 bit fractional  0.25 per bit
         sprintf(txtstr,"Press=%ld.%02d Pa", num_whole, num_frac);
-        evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+        evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
 
         /*
          * Trigger a Altitude reading
@@ -482,11 +523,11 @@
         num_whole = baro_data._baro / 16;		//	18 bit signed significant integer
         num_frac = (baro_data._baro & 0xF) * 625 / 100;		// 4 bit fractional .0625 per bit
         sprintf(txtstr,"Alti=%ld.%02d m", num_whole, num_frac);
-        evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+        evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
         num_whole = baro_data._temp / 16;		// 8 bit signed significant integer
         num_frac = (baro_data._temp & 0x0F) * 625 / 100;		// 4 bit fractional .0625 per bit
         sprintf(txtstr,"Temp=%ld.%03d C", num_whole, num_frac);
-        evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+        evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
 
         /*
          * retrieve and print out Ambient Light level
@@ -495,13 +536,28 @@
         num_whole = lux_data * 24 / 100;		// 16000 lux full scale .24 lux per bit
         num_frac = lux_data * 24 % 100;
         sprintf(txtstr, "Light=%ld.%02d lux", num_whole, num_frac );
-        evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+        evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
 
         evbLCD->endUpdate();
+
         printf("finished iteration %d\r\n",(++i));
 
-        if (i % pckt_time == 0) { // check packet counter will send packet every 2-5-10 data collection loops
+        /* Transmit data packet based on pckt_time setting and result of
+         * mdot_radio->getNextTxMs() function and mutex available. The getNextTxMs()
+         * function returns the number of millisecond before another packet can be
+         * sent in 868 MHz band. This can vary depending on wther the 10%, 1% or 0.1%
+         * channel is used and the time on air for a specific setup of the radio
+         */
+
+        if ((xmit_delay <= i) && (mdot_radio->getNextTxMs() == 0) && (mdot_mutex.trylock())) {
+            /*
+             * Setting TX power and Data Rate for radio just in case user requested by SW2
+             */
+            mdot_radio->setTxPower(pwr_val);
+            mdot_radio->setTxDataRate(sf_val);
+
             mdot_data.clear();
+            mdot_data.push_back(0x1D);			// key for start of data
             mdot_data.push_back(0x0E);			// key for Current Acceleration 3-Axis Value
             converts.f_s = accel_data._x *4;		// shift data 2 bits while retaining sign
             mdot_data.push_back(converts.t_u[1]);	// get 8 MSB of 14 bit value
@@ -514,6 +570,24 @@
             mdot_data.push_back(convertl.t_u[2]);
             mdot_data.push_back(convertl.t_u[1]);
             mdot_data.push_back(convertl.t_u[0]);
+
+            /* for 915 MHz band and SF_10 max packet size is 11 bytes.
+             * so the payload gets split in two packets here.
+             */
+            if ((mdot_freq == mDot::FB_915) && (sf_val == mDot::SF_10)) {
+            	mdot_ret = mdot_radio->send(mdot_data);
+                if ( mdot_ret != mDot::MDOT_OK) {
+                    sprintf(txtstr,"mDot Send failed");
+                    evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+                    log_error(mdot_radio, txtstr, mdot_ret);
+                    continue;
+                } else {
+                    printf("successfully sent packet 1 to gateway\r\n");
+                }
+                mdot_data.clear();		// clear data for next "chunk"
+            }
+
+
             mdot_data.push_back(0x05);			// key for Current Ambient Light Value
             converts.f_u = lux_data;				// data is 16 bits unsigned
             mdot_data.push_back(converts.t_u[1]);
@@ -522,14 +596,28 @@
             converts.f_s = baro_data._temp;		// temperature is signed 12 bit
             mdot_data.push_back(converts.t_u[1]);
             mdot_data.push_back(converts.t_u[0]);
+            mdot_data.push_back(0x1D);			// key for end of data
 
-            if ((mdot_ret = mdot_radio->send(mdot_data)) != mDot::MDOT_OK) {
+            mdot_ret = mdot_radio->send(mdot_data);
+            if (mdot_ret != mDot::MDOT_OK) {
                 log_error(mdot_radio, "failed to send", mdot_ret);
+                sprintf(txtstr,"PKT Send Failed");
+                evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
             } else {
-                printf("successfully sent data to gateway\r\n");
+                sprintf(txtstr,"SENT DR=%2d Pwr=%2d",(12 - sf_val),pwr_val);
+                evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+                printf("%s \r\n",txtstr);
             }
+            mdot_mutex.unlock(); // unlock mutex after all data transmitted
+            xmit_delay = i + pckt_time;
+            if (mdot_freq == mDot::FB_868)
+            	printf("Next transmit time = %d milliseconds \r\n",mdot_radio->getNextTxMs());
+
+        } else {
+            sprintf(txtstr,"     DR=%2d Pwr=%2d     ",(12 - sf_val),pwr_val);
+            evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
         }
-    } while(!exit_program && (i < 65000));
+    } while(i < 65000);
 
     evbBaro->triggerOneShot();
 
@@ -551,81 +639,115 @@
 }
 
 /*
- * Sets pb1_low flag. Slag is cleared in pb1_debounce thread
+ * Sets sw1_low flag. Slag is cleared in sw1_debounce thread
  */
-void pb1ISR(void)
+void sw1ISR(void)
 {
-	if (!pb1_low)
-		pb1_low = true;
+    if (!sw1_low)
+        sw1_low = true;
 }
 
 /*
- * Debounces pb1. Also exits program if pushbutton 1 is pressed
+ * Debounces sw1 changes spreading factor and output power
+ * Cycles through SF_7-SF_9 for 4 power levels for 915 MHz band
+ * Cycles through SF_7-SF_12 for 4 power levels for 868 MHz band
  */
-void pb1_debounce(void const *args)
+void sw1_debounce(void const *args)
+{
+    static uint8_t count = 0;
+    static uint8_t test_sf = 0;
+    static uint8_t test_pwr = 0;
+
+    while (true) {
+
+        if (sw1_low && (mDot08 == 0))
+            count++;
+        else {
+            count = 0;
+            sw1_low = false;
+        }
+
+        if (count == 5) {
+            test_sf++;
+
+            if (((test_sf > 3) && (mdot_freq == mDot::FB_915)) || ((test_sf > 5) && (mdot_freq == mDot::FB_868))) {
+                test_sf = 0;
+                test_pwr ++;
+                if (test_pwr > 3)
+                    test_pwr = 0;
+            }
+
+            // selects power output level using upper bits for select
+            switch(test_pwr) {
+                case 0:
+                    pwr_val = 11;
+                    break;
+                case 1:
+                    pwr_val = 14;
+                    break;
+                case 2:
+                    pwr_val = 18;
+                    break;
+                case 3:
+                    pwr_val = 20;
+            }
+
+            // sets data rate based on lower bits
+            sf_val = mDot::SF_7 - (test_sf & 0x07);
+
+            sprintf(txtstr,"     DR=%2d Pwr=%2d     ",(12 - sf_val),pwr_val);
+            evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+            printf("%s \r\n",txtstr);
+        }
+
+        Thread::wait(5);
+    }
+}
+
+/*
+ * Sets sw2_low flag. Flag is cleared in sw2_debounce thread
+ */
+void sw2ISR(void)
+{
+    if (!sw2_low)
+        sw2_low = true;
+}
+
+/*
+ * Debounces sw2. Changes packet transmit time to every 2nd,
+ * 4th, 8th, or 16th sample when SW2 pushed. For 868 MHz mode
+ * the time for next packet value is also tested.
+ * Also triggers a thread to transmit a configuration packet
+ */
+void sw2_debounce(void const *args)
 {
 
     static uint8_t count = 0;
 
     while (true) {
 
-        if (pb1_low && (mDot08 == 0))
-			count++;
+        if (sw2_low && (mDot09 == 0))
+            count++;
         else {
-        	count = 0;
-        	pb1_low = false;
+            count = 0;
+            sw2_low = false;
         }
-        
-		if (count == 5) 
-			exit_program = true;
-		
+
+        if (count == 5) {
+
+            if (pckt_time >= 4)
+                pckt_time /= 2;
+            else pckt_time = 16;
+
+            thread_3->signal_set(0x10);		// signal config_pkt_xmit to send packet
+        }
+
         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 (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
-		}
-		
-        Thread::wait(5);
- 	}
- }
-
-/*
- *  Function that print clear text verion of mDot errors
+ *  Function that prints clear text verion of mDot errors
  */
 void log_error(mDot* dot, const char* msg, int32_t retval)
 {
@@ -639,17 +761,24 @@
 {
 
     std::vector<uint8_t> data;
+    uint16_t wait_time;
 
     while (true) {
-        Thread::signal_wait(0x10);		// wait for pb2ISR to signal send
+        Thread::signal_wait(0x10);		// wait for sw2ISR to signal send
         data.clear();
         data.push_back(0x0F);			// key for Configuration data (packet transmission timer)
         data.push_back(pckt_time);
+        
+        mdot_mutex.lock();		// lock mdot mutex before packet send
+
+        if ((wait_time = mdot_radio->getNextTxMs()) > 0) // wait for next xmit time
+        	osDelay(wait_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");
         }
+        mdot_mutex.unlock();		// unlock mdot mutex after packet send
     }
 }