MTDOT-EVB link check code for site survey
Dependencies: DOGS102 GpsParser MTS-Serial NCP5623B libmDot mbed-rtos mbed
Diff: main.cpp
- Revision:
- 0:dba397ff987f
- Child:
- 1:4e3ee9c860e3
--- /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