MTDOT-EVB link check code for site survey

Dependencies:   DOGS102 GpsParser MTS-Serial NCP5623B libmDot mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
falingtrea
Date:
Thu Oct 22 19:45:01 2015 +0000
Child:
1:4e3ee9c860e3
Commit message:
Copied from MDOT-EVB-LinkCheck. Added mutex around certain mDot radio commands. Moved ping check code to callable function. Added sweep mode, re-wrote join code, and modified button operation. Fixed error in Downlink QOS SNR display.

Changed in this revision

DOGS102.lib Show annotated file Show diff for this revision Revisions of this file
GpsParser.lib Show annotated file Show diff for this revision Revisions of this file
MTS-Serial.lib Show annotated file Show diff for this revision Revisions of this file
NCP5623B.lib Show annotated file Show diff for this revision Revisions of this file
libmDot.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed-src.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DOGS102.lib	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Multi-Hackers/code/DOGS102/#3b02b7fb79c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GpsParser.lib	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/Multi-Hackers/code/GpsParser/#662aa99c5266
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MTS-Serial.lib	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/MultiTech/code/MTS-Serial/#4afbbafcd6b3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NCP5623B.lib	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Multi-Hackers/code/NCP5623B/#b28a2dfe05fd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmDot.lib	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/MultiTech/code/libmDot/#0b4eb17d07ae
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,775 @@
+/**
+ * @file    main.cpp
+ * @brief   Main application for mDot-EVB Automated Link Check demo
+ * @author  Tim Barr  MultiTech Systems Inc.
+ * @version 1.02
+ * @see
+ *
+ * Copyright (c) 2015
+ *
+ * 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.
+ *
+ * 1.00 TAB 10/22/15  Copied from MDOT-EVB-LinkCheck version 1.02. 
+ *					Added mutex around certain mDot radio commands.
+ *					Moved ping check code to callable function. Added sweep
+ *					mode, re-wrote join code, and modified button operation
+ *					Fixed error in Downlink QOS SNR display.
+ */
+
+#include "mbed.h"
+#include "NCP5623B.h"
+#include "DOGS102.h"
+#include "font_6x8.h"
+#include "MultiTech_Logo.h"
+#include "mDot.h"
+#include "rtos.h"
+#include "GPSPARSER.h"
+#include "MTSSerial.h"
+#include <string>
+#include <vector>
+#include <ctime>
+
+enum LED1_COLOR {
+    RED = 0,
+    GREEN = 1
+};
+
+/*
+ * union for converting from 32-bit to 4 8-bit values
+ */
+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
+};
+
+//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
+
+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
+
+//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
+
+MTSSerial 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
+
+/* **** replace these values with the proper public or private network settings ****
+ * config_network_nameand config_network_pass are for private networks.
+ */
+static std::string config_network_name = "TAB-CubeNet";
+static std::string config_network_pass = "1nt3gral";
+//static std::string config_network_name = "Arclight";
+//static std::string config_network_pass = "default1";
+static uint8_t config_frequency_sub_band = 5;
+
+//static std::string config_network_name = "GregCDT8";
+//static std::string config_network_pass = "myAEP8chars";
+//static uint8_t config_frequency_sub_band = 1;
+
+/*  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};
+std::vector<uint8_t> config_app_id;
+static uint8_t app_key[16] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
+std::vector<uint8_t> config_app_key;
+*/
+
+uint8_t result;
+uint8_t data;
+uint8_t sf_val = mDot::SF_7;
+uint8_t pwr_val = 11; // dBm
+uint8_t swp_pwr;
+uint8_t swp_sf;
+
+const uint8_t sweep_table [2][4] = {
+	{ 11, 14, 18, 20},
+	{mDot::SF_7, mDot::SF_8, mDot::SF_9, mDot::SF_10}
+	};
+
+// max size of text string for 6x8 font. Set to 12 if using 8x8 font
+char txtstr[17];
+
+int32_t mdot_ret;
+int32_t join_delay;
+
+osThreadId mainThreadID;
+
+// flags for push button debounce code
+bool pb1_low = false;
+bool pb2_low = false;
+bool toggle_text = false;
+bool main_single = false;
+bool main_sweep = false;
+
+NCP5623B* evbBackLight;
+DOGS102* evbLCD;
+
+mDot* mdot_radio;
+Mutex mdot_mutex;
+
+GPSPARSER* mdot_gps;
+
+convert32 convertL;
+convert16 convertS;
+
+void pb1ISR(void);
+void pb2ISR(void);
+void pb1_debounce(void const *args);
+void pb2_debounce(void const *args);
+
+void log_error(mDot* dot, const char* msg, int32_t retval);
+
+uint8_t ping_check(uint8_t set_pwr, uint8_t set_sf, uint8_t pings_per_check = 1);
+
+int main()
+{
+    std::vector<uint8_t> mdot_EUI;
+    uint16_t i = 0;
+
+//  Number of ping attempts per Radio setting set here
+    uint8_t number_of_pings = 5;
+
+    debugUART.baud(115200);
+
+	printf ("Start program \r\n");
+
+    Thread thread_1(pb1_debounce);
+    Thread thread_2(pb2_debounce);
+
+	printf("Thread init done\r\n");
+
+    mainThreadID = osThreadGetId();
+
+	printf("Device init start\r\n");
+
+    evbBackLight = new NCP5623B(mDoti2c);				// setup backlight and LED 2 driver chip
+    evbLCD = new DOGS102(mDotspi, mDot17, mDot13);		// setup LCD
+
+    printf ("Devices init done\r\n");
+    /*
+     *  Setup SW1 as Data rate and power out select
+     */
+    mDot08.disable_irq();
+    mDot08.fall(&pb1ISR);
+
+    /*
+     *  need to call this function after rise or fall because rise/fall sets
+     *  mode to PullNone
+     */
+    mDot08.mode(PullUp);
+
+    mDot08.enable_irq();
+
+    /*
+     *  Setup SW2 as send PING
+     */
+    mDot09.disable_irq();
+    mDot09.fall(&pb2ISR);
+
+    /*
+     *  need to call this function after rise or fall because rise/fall sets
+     *  mode to PullNone
+     */
+    mDot09.mode(PullUp);
+
+    mDot09.enable_irq();
+
+    /*
+    * Setting other InterruptIn pins with Pull Ups
+    */
+    mDot12.mode(PullUp);
+    mDot15.mode(PullUp);
+    mDot16.mode(PullUp);
+
+	printf("Switch IRQs set\r\n");
+	 
+    printf("font table address %p\r\n",&font_6x8);
+    printf("bitmap address %p\r\n",&MultiTech_Logo);
+
+// Setup and display logo on LCD
+    evbLCD->startUpdate();
+
+    evbLCD->writeBitmap(0,0,MultiTech_Logo);
+
+    sprintf(txtstr,"MTDOT-EVB");
+    evbLCD->writeText(24,3,font_6x8,txtstr,strlen(txtstr));
+    sprintf(txtstr,"Link Check Demo");
+    evbLCD->writeText(6,4,font_6x8,txtstr,strlen(txtstr));
+
+    evbLCD->endUpdate();
+
+    printf("\r\n setup mdot\r\n");
+
+    // get a mDot handle
+    mdot_radio = mDot::getInstance();
+
+    if (mdot_radio) {
+        // reset to default config so we know what state we're in
+        mdot_mutex.lock(); 	// lock mdot before setting configuration 
+        mdot_radio->resetConfig();
+
+        // Setting up LED1 as activity LED
+        mdot_radio->setActivityLedPin(PB_0);
+        mdot_radio->setActivityLedEnable(true);
+
+        // Read node ID
+        mdot_EUI = mdot_radio->getDeviceId();
+        printf("mDot EUI = ");
+
+        for (i=0; i<mdot_EUI.size(); i++) {
+            printf("%02x ", mdot_EUI[i]);
+        }
+        printf("\r\n");
+
+// 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);
+        }
+
+        /*
+         * 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);
+        }
+
+        /*
+         * Setting TX data rate for radio. Max allowed is SF_12 for EU and SF10 dBm for NAM. Default is SF_10
+         */
+        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);
+        }
+
+		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);
+
+        /*
+         * Setting packet ACK to 1 try.
+         */
+        printf("setting Packet retry to 1\r\n");
+        if ((mdot_ret = mdot_radio->setAck(1)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "failed to set packet retry\r\n", mdot_ret);
+        }
+
+        /*
+         * setNetworkName is used for private networks.
+         * Use setNetworkID(AppID) for public networks
+         */
+
+// 		config_app_id.assign(app_id,app_id+7);
+
+        printf("setting network name\r\n");
+        if ((mdot_ret = mdot_radio->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
+//      if ((mdot_ret = mdot_radio->setNetworkID(config_app_id)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "failed to set network name", mdot_ret);
+        }
+
+        /*
+         * setNetworkPassphrase is used for private networks
+         * Use setNetworkKey for public networks
+         */
+
+// 		config_app_key.assign(app_key,app_key+15);
+
+        printf("setting network password\r\n");
+        if ((mdot_ret = mdot_radio->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
+//      if ((mdot_ret = mdot_radio->setNetworkKey(config_app_key)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "failed to set network password", 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 so SW1 can work
+
+        } while (mdot_ret != mDot::MDOT_OK);
+        
+	    sprintf(txtstr,"*Network Joined*");
+    	evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
+    } else {
+	    sprintf(txtstr,"Radio Init Failed!");
+    	evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+        printf("%s\r\n",txtstr);
+        exit(1);
+    }
+
+ 	mdot_gps = new GPSPARSER(&mDotUART);
+ 
+    if (!mdot_gps->gpsDetected()){
+   		sprintf(txtstr,"*No GPS Detected*");
+   		evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+    	printf ("%s\r\n", txtstr);
+    }
+    else {
+ 		main_single = main_sweep = false;
+    	do {
+	        osSignalWait(0x10, 2000);
+			if (mdot_gps->getLockStatus()){
+	    		sprintf(txtstr,"!!GPS locked!!");
+        		evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+				printf("%s \r\n",txtstr);
+			}
+			else {
+       			if (toggle_text)
+       				sprintf(txtstr," > no GPS lock <");
+       			else
+      				sprintf(txtstr," < no GPS lock >");
+
+           		evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+				printf("%s \r\n",txtstr);
+				toggle_text = !toggle_text;
+			}
+   		} while ( !(mdot_gps->getLockStatus()) && (!main_single && !main_sweep));
+   	}	
+    osDelay(200);
+    evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
+
+    // sets LED2 to 50% max current
+    evbBackLight->setLEDCurrent(16);
+
+    osDelay (500);			// allows other threads to process
+    printf("shutdown LED:\r\n");
+    evbBackLight->shutdown();
+	osDelay(500);
+	/*
+     * Main data acquisition loop
+     */
+    i = 0;
+
+    do {
+
+        // Main program waits until SW2 is pressed.
+ 		main_single = main_sweep = false;
+
+		sprintf(txtstr,"Ready for Trigger");
+		evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+ 	 	printf ("%s\r\n", txtstr);
+
+        osSignalWait(0x10, osWaitForever);
+        
+		if (main_single) {
+			evbLCD->clearBuffer();
+			sprintf(txtstr,"**Single Ping**");
+			evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+
+			result = ping_check(pwr_val, sf_val);
+
+			if (result != 0)
+				printf("Ping check completed\r\n");
+			else
+				printf("Ping check failed \r\n");
+		}
+		else if (main_sweep) {
+
+				evbLCD->clearBuffer();
+				sprintf(txtstr,"**Ping Sweep**");
+				evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+
+		   		printf("start sweep and shutdown LED:\r\n");
+    			evbBackLight->shutdown();
+
+				for (swp_pwr = 0; swp_pwr < 4; swp_pwr++)
+				{
+					for (swp_sf = 0; swp_sf < 4; swp_sf++)
+					{	        
+						result = ping_check(sweep_table[0][swp_pwr], sweep_table[1][swp_sf], number_of_pings);
+
+						if (result != 0)
+							printf("Ping check completed %d attempts\r\n", result);
+						else
+							printf("Ping check failed all attempts\r\n");
+
+						osDelay(1000);
+					}
+				}
+			}
+			else {
+				printf("Got here because of code error.\r\n");
+				osDelay(1000);
+			}
+
+    } while(i < 1000);
+
+	printf("End of Test\r\n");
+	
+	evbLCD->clearBuffer();
+	sprintf(txtstr,"Exiting Program");
+	evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+}
+
+/*
+ * Sets pb1_low flag. Flag is cleared in pb1_debounce thread
+ */
+void pb1ISR(void)
+{
+	if (!pb1_low)
+		pb1_low = true;
+}
+
+/*
+ * Debounces pb1 PB1 changes spreading factor and output power
+ * Cycles through SF_7-SF_10 for 4 power levels
+ */
+void pb1_debounce(void const *args)
+{
+    static uint8_t count = 0;
+    static uint8_t test_now = 0;
+
+    while (true) {
+
+        if (pb1_low && (mDot08 == 0))
+			count++;
+        else {
+        	count = 0;
+        	pb1_low = false;
+        }
+        
+		if (count == 5) {
+			test_now++;
+			
+			if (test_now > 15)   // resets test_now
+				test_now = 0;
+
+			// selects power output level using upper bits for select
+			switch(test_now >> 2){
+				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_now & 0x03);
+			
+			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 pb2_low flag. Flag is cleared in pb2_debounce thread
+ */
+void pb2ISR(void)
+{
+	if (!pb2_low)
+		pb2_low = true;
+}
+
+/*
+ * Debounces pb2 PB2 forces main program out of thread wait mode
+ */
+void pb2_debounce(void const *args)
+{
+
+    static uint8_t count = 0;
+
+    while (true) {
+
+        if (pb2_low && (mDot09 == 0)){
+			count++;
+			if (count == 100){
+		    // sets LED2 to 50% max current
+				evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
+			    evbBackLight->setLEDCurrent(16);
+			}
+		}
+        else {
+			if ((count > 5) && (count <= 100)) {
+				main_single = true;
+				osSignalSet(mainThreadID, 0x10);
+			} else if (count > 100) {
+				main_sweep = true;
+				osSignalSet(mainThreadID, 0x10);
+			}
+
+        	count = 0;
+        	pb2_low = false;
+        }
+        
+        Thread::wait(5);
+ 	}
+ }
+
+/*
+ *  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());
+}
+
+// return = number of ping checks that passed
+uint8_t ping_check(uint8_t set_pwr, uint8_t set_sf, uint8_t pings_per_check) 
+{
+
+	uint8_t result = 0;
+	uint8_t ping_cnt;
+	mDot::ping_response ping_data;
+	mDot::rssi_stats rssi_data;
+	mDot::snr_stats snr_data;
+	struct tm gps_timestamp;
+	GPSPARSER::longitude evb_longitude;
+	GPSPARSER::latitude evb_latitude;
+	GPSPARSER::satellite_prn gps_sat_prn;
+	uint8_t gps_fix_quality;
+	int16_t evb_altitude;
+	uint8_t gps_num_satellites;
+	uint8_t gps_fix_status;
+    std::vector<uint8_t> mdot_data;
+
+	mdot_mutex.lock();		// lock mdot mutex before changing radio parameters
+    if ((mdot_ret = mdot_radio->setTxPower(set_pwr)) != mDot::MDOT_OK) {
+    	log_error(mdot_radio, "failed to set TX power level", mdot_ret);
+    }
+	if ((mdot_ret = mdot_radio->setTxDataRate(set_sf)) != mDot::MDOT_OK) {
+       	log_error(mdot_radio, "failed to set DataRate value", mdot_ret);
+    }
+	mdot_mutex.unlock();		// unlock mdot mutex after changing radio parameters
+
+	for (ping_cnt = 0; ping_cnt < pings_per_check; ping_cnt++) {
+		evbLCD->startUpdate();
+	    evbLCD->clearBuffer();
+
+	    mdot_mutex.lock();		// lock mdot mutex before ping
+		ping_data = mdot_radio->ping();
+		mdot_mutex.unlock();		// unlock mdot mutex after ping
+
+		if (ping_data.status == mDot::MDOT_OK) {
+    		rssi_data = mdot_radio->getRssiStats();
+    		snr_data = mdot_radio->getSnrStats();
+			gps_fix_status = mdot_gps->getFixStatus();
+			gps_fix_quality = mdot_gps->getFixQuality();
+			gps_num_satellites = mdot_gps->getNumSatellites();
+			
+			printf ("\r\n GPS Fix Status= %d num of sats = %d\r\n", gps_fix_status, gps_num_satellites);
+
+        	sprintf(txtstr,"PGOOD DR=%2d P=%2d",(12 - set_sf),set_pwr);
+        	evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr));
+			printf("%s \r\n",txtstr);
+
+        	sprintf(txtstr,"UP  %3d dBm %2d.%1d",ping_data.rssi, ping_data.snr/10, abs(ping_data.snr)%10);
+        	evbLCD->writeText(0,1,font_6x8,txtstr,strlen(txtstr));
+			printf("Link Quality %s \r\n",txtstr);
+
+        	sprintf(txtstr,"DWN %3d dBm %2d.%02d",rssi_data.last, snr_data.last/4, abs(snr_data.last)%4*25);
+        	evbLCD->writeText(0,2,font_6x8,txtstr,strlen(txtstr));
+			printf("Link Quality %s \r\n",txtstr);
+
+			mdot_data.clear();
+			mdot_data.push_back(0x1D);			// key for start of data structure
+			mdot_data.push_back(0x1A);			// key for uplink QOS + RF Pwr
+			convertS.f_s = ping_data.rssi;
+			mdot_data.push_back(convertS.t_u[1]);
+			mdot_data.push_back(convertS.t_u[0]);
+			mdot_data.push_back((ping_data.snr/10) & 0xFF);
+			mdot_data.push_back(set_pwr);
+
+			mdot_data.push_back(0x1B);			// key for downlink QOS
+			convertS.f_s=rssi_data.last;
+			mdot_data.push_back(convertS.t_u[1]);
+			mdot_data.push_back(convertS.t_u[0]);
+			mdot_data.push_back(snr_data.last);
+
+	// collect GPS data if GPS device detected
+			if (mdot_gps->gpsDetected() && (set_sf != mDot::SF_10)){
+
+					mdot_data.push_back(0x19);			// key for GPS Lock Status
+					data = ( gps_num_satellites << 4 ) | ( gps_fix_status & 0x0F );
+					mdot_data.push_back(data);
+
+				if (mdot_gps->getLockStatus()){			// if gps has a lock
+					evb_longitude = mdot_gps->getLongitude();
+					evb_latitude = mdot_gps->getLatitude();
+					evb_altitude = mdot_gps->getAltitude();
+					gps_timestamp = mdot_gps->getTimestamp();
+
+	    			sprintf(txtstr,"%3d %2d %2d.%03d",abs(evb_longitude.degrees),evb_longitude.minutes,(evb_longitude.seconds*6)/1000,(evb_longitude.seconds*6)%1000);
+
+	   	 			if (evb_longitude.degrees < 0)
+	    				strncat(txtstr," W",2);
+	    			else
+	    				strncat(txtstr," E",2);
+    				
+	           		evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
+					printf("Longitude: %s \r\n",txtstr);
+
+	    			sprintf(txtstr,"%3d %2d %2d.%03d",abs(evb_latitude.degrees),evb_latitude.minutes,(evb_latitude.seconds*6)/1000,(evb_latitude.seconds*6)%1000);
+
+	    			if (evb_latitude.degrees < 0)
+	    				strncat(txtstr," S",2);
+	    			else
+	    				strncat(txtstr," N",2);
+
+	            	evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+					printf("Latitude:  %s \r\n",txtstr);
+
+	    			sprintf(txtstr,"Time %02d:%02d:%02d ",gps_timestamp.tm_hour,gps_timestamp.tm_min,gps_timestamp.tm_sec);
+	            	evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+					printf("%s \r\n",txtstr);
+
+	    			sprintf(txtstr,"Date %02d/%02d/%04d",gps_timestamp.tm_mon + 1,gps_timestamp.tm_mday,gps_timestamp.tm_year +1900);
+	            	evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+					printf("%s \r\n\r\n",txtstr);
+
+			// Send GPS data if GSP device locked
+					mdot_data.push_back(0x15);			// key for GPS Latitude
+					mdot_data.push_back(evb_latitude.degrees);
+					mdot_data.push_back(evb_latitude.minutes);
+					convertS.f_s = evb_latitude.seconds;
+					mdot_data.push_back(convertS.t_u[1]);
+					mdot_data.push_back(convertS.t_u[0]);
+
+					mdot_data.push_back(0x16);			// key for GPS Longitude
+					convertS.f_s = evb_longitude.degrees;
+					mdot_data.push_back(convertS.t_u[1]);
+					mdot_data.push_back(convertS.t_u[0]);
+
+					mdot_data.push_back(evb_longitude.minutes);
+					convertS.f_s = evb_longitude.seconds;
+					mdot_data.push_back(convertS.t_u[1]);
+					mdot_data.push_back(convertS.t_u[0]);
+		    	}
+		    	else {
+		    		sprintf(txtstr,"no GPS lock");
+	   	    	   	evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+					printf("%s \r\n",txtstr);
+		    	}
+			}
+	// key for end of data structure		
+			mdot_data.push_back(0x1D);
+		
+	// if SF_10 this sends 11 bytes of data, otherwise sends full data packet
+	        mdot_mutex.lock();		// lock mdot mutex before packet send
+			mdot_ret = mdot_radio->send(mdot_data);
+	        mdot_mutex.unlock();		// unlock mdot mutex after packet send
+
+			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);
+			}
+			else {
+		       	sprintf(txtstr,"mDot Send success");
+	            evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+				printf("successfully sent data to gateway\r\n");
+				result++;
+			}
+	    }
+	    else {
+			sprintf(txtstr,"Ping Check Failed");
+	        evbLCD->writeText(0,2,font_6x8,txtstr,strlen(txtstr));
+			printf("%s \r\n",txtstr);
+	        sprintf(txtstr,"DR=%2d P=%2d",(12 - set_sf),set_pwr);
+	        evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
+			printf("%s \r\n",txtstr);
+			strncpy(txtstr,mDot::getReturnCodeString(ping_data.status).c_str(),17);
+	        evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+			printf("%s \r\n",txtstr);
+	    }
+
+		evbLCD->endUpdate();
+		osDelay(1000);
+	}
+	return result;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#21b438192b0f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-src.lib	Thu Oct 22 19:45:01 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-src/#9c82b0f79f3d