Peter Ferland / Mbed OS TelitSensorToCloud

Dependencies:   DOGS102 GpsParser ISL29011 MMA845x MPL3115A2 MTS-Serial NCP5623B mDot_X_NUCLEO_IKS01A1 libmDot-mbed5

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*================================================================================
00002  *
00003  * CLASIFICATION:     **** PUBLIC RELEASE AS-IS APPLICATION EXAMPLE ****
00004  *
00005  * SOURCE FILE NAME:  main.cpp
00006  *
00007  * DESCRIPTIVE NAME:  MBED Source for MultiTech mDot, EVB, and MDOT-BOX Devices
00008  *
00009  * COPYRIGHT:         Copyright 2014-2017, Telit
00010  *
00011  *                    LICENSED MATERIAL - PROGRAM PROPERTY OF TELIT
00012  *                    REFER TO TELIT COPYRIGHT INSTRUCTION
00013  *
00014 ** WEB SITE:          www.telit.com
00015  *
00016  * WRITTEN BY:        Eliott Fersko and John Keever
00017  *
00018  * DATE:              April 17, 2017
00019  *
00020  * VERSION:           1.02
00021  *
00022  * FUNCTION:          Provide working example for LoRa 'Sensor-to-Cloud'
00023  *                    Demonstration using MultiTech LoRa Starter Kit and
00024  *                    Telit Data and Cloud Platform Services Offerings
00025  *
00026  * SOURCE FILE TYPE:  MBED C++
00027  *
00028  * FUNCTIONS/ENTRY POINTS:  main
00029  *
00030  * INPUT  = None.
00031  * OUTPUT = None.
00032  *
00033  * EXIT-NORMAL = N/A
00034  * EXIT-ERROR  = N/A
00035  *
00036  * EXTERNAL REFERENCES = None.
00037  *
00038  * EXTERNAL FUNCTIONS = None.
00039  *
00040  * CONTROL BLOCKS = None.
00041  *
00042  *================================================================================*/
00043 /*                              LEGAL DISCLAIMER                                  */
00044 /*================================================================================
00045 
00046   Redistribution and use in source and binary forms, with or without
00047   modification, are permitted provided that the following conditions
00048   are met:
00049 
00050     Neither the name of ILS Technology nor Telit nor the names of its
00051     contributors may be used to endorse or promote products derived
00052     from this software without specific prior written permission.
00053 
00054   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00055   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00056   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00057   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00058   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00059   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00060   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00061   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00062   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00063   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00064   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00065 
00066  *================================================================================*/
00067 /*                                 CHANGE LOG                                     */
00068 /*================================================================================*/
00069 /*          |Changed |          |                                                 */
00070 /*  Date    |   by   |Version ID| Comments                                        */
00071 /*----------+--------+----------+-------------------------------------------------*/
00072 /*04-12-2017|JEK     |V1.00     |Original Version - mDot, EVB, MDOT-BOX           */
00073 /*04-14-2017|JEK     |V1.01     |Added IRQ Handlers - SW1/SW2 (Threads?)          */
00074 /*04-17-2017|JEK     |V1.02     |Added Binary LoRa Payload Message Framing Type   */
00075 /*04-24-2017|EMF     |V1.03     |Updated Libraries                                */
00076 /*05-10-2017|EMF     |V1.04     |Added support for ST-Micro MEMS Sensor Shield    */
00077 /*================================================================================*/
00078 /*NOTE:  Please keep the change log up to date!!!                                 */
00079 /*================================================================================*/
00080 
00081 #include "mbed.h"
00082 #include "MMA845x.h"
00083 #include "MPL3115A2.h"
00084 #include "ISL29011.h"
00085 #include "NCP5623B.h"
00086 #include "DOGS102.h"
00087 #include "font_6x8.h"
00088 #include "MultiTech_Logo.h"
00089 #include "mDot.h"
00090 #include "rtos.h"
00091 #include "GPSPARSER.h"
00092 #include "MTSSerial.h"
00093 #include "x_nucleo_iks01a1.h"
00094 
00095 #include <cmath>
00096 #include <string>
00097 #include <vector>
00098 #include <ctime>
00099 #include <Ticker.h>
00100 
00101 #define CALL_METH(obj, meth, param, ret) ((obj == NULL) ?       \
00102                       ((*(param) = (ret)), 0) : \
00103                       ((obj)->meth(param))      \
00104                       )
00105 
00106 
00107 enum LED1_COLOR {
00108     RED = 0,
00109     GREEN = 1
00110 };
00111 
00112 namespace {
00113     const int MS_INTERVALS = 1000;
00114 }
00115 
00116 /*
00117  * union for converting from 32-bit to 4 8-bit values
00118  */
00119 union convert32 {
00120     int32_t f_s;        // convert from signed 32 bit int
00121     uint32_t f_u;       // convert from unsigned 32 bit int
00122     uint8_t t_u[4];     // convert to 8 bit unsigned array
00123 };
00124 
00125 typedef struct {
00126     int32_t AXIS_X;
00127     int32_t AXIS_Y;
00128     int32_t AXIS_Z;
00129 } AxesRaw_TypeDef;
00130 
00131 
00132 /*
00133  * union for converting from 16- bit to 2 8-bit values
00134  */
00135 union convert16 {
00136     int16_t f_s;        // convert from signed 16 bit int
00137     uint16_t f_u;       // convert from unsigned 16 bit int
00138     uint8_t t_u[2];     // convert to 8 bit unsigned array
00139 };
00140 
00141 //DigitalIn mDot02(PA_2);                       //  GPIO/UART_TX
00142 //DigitalOut mDot03(PA_3);                      //  GPIO/UART_RX
00143 //DigitalIn mDot04(PA_6);                       //  GPIO/SPI_MISO
00144 //DigitalIn mDot06(PA_8);                       //  GPIO/I2C_SCL
00145 //DigitalIn mDot07(PC_9);                       //  GPIO/I2C_SDA
00146 
00147 InterruptIn mDot08(PA_12);                      //  GPIO/USB       PB S1 on EVB
00148 InterruptIn mDot09(PA_11);                      //  GPIO/USB       PB S2 on EVB
00149 
00150 //DigitalIn mDot11(PA_7);                       //  GPIO/SPI_MOSI
00151 
00152 InterruptIn mDot12(PA_0);                       //  GPIO/UART_CTS  PRESSURE_INT2 on EVB
00153 DigitalOut mDot13(PC_13,1);                     //  GPIO           LCD_C/D
00154 InterruptIn mDot15(PC_1);                       //  GPIO           LIGHT_PROX_INT on EVB
00155 InterruptIn mDot16(PA_1);                       //  GPIO/UART_RTS  ACCEL_INT2 on EVB
00156 DigitalOut mDot17(PA_4,1);                      //  GPIO/SPI_NCS   LCD_CS on EVB
00157 
00158 // DigitalIn mDot18(PA_5);                          //  GPIO/SPI_SCK
00159 // DigitalInOut mDot19(PB_0,PIN_INPUT,PullNone,0);  //  GPIO         PushPull LED Low=Red High=Green set MODE=INPUT to turn off
00160 // AnalogIn mDot20(PB_1);                           //  GPIO         Current Sense Analog in on EVB
00161 
00162 Serial debugUART(PA_9, PA_10);                  // mDot debug UART
00163 MTSSerial mDotUART(PA_2,PA_3);                  // mDot external UART mDot02 and mDot03
00164 I2C mDoti2c(PC_9,PA_8);                         // mDot External I2C mDot6 and mDot7
00165 SPI mDotspi(PA_7,PA_6,PA_5);                    // mDot external SPI mDot11, mDot4, and mDot18
00166 AnalogIn current_sensor(PB_1);                  // EVB - GPIO - Current Sensor Analog Input
00167 
00168 /* **** replace these values with the proper public or private network settings ****
00169  * config_network_nameand config_network_pass are for private networks.
00170  */
00171 
00172 //static std::string config_network_name = "telitlora";
00173 //static std::string config_network_pass = "telitpass";
00174 //static uint8_t config_frequency_sub_band = 7;
00175 
00176 
00177 
00178 static volatile bool timer_irq_triggered = false;
00179 static volatile bool ff_irq_triggered = false;
00180 
00181 static std::string config_network_name = "MTCDT-19186797";
00182 static std::string config_network_pass = "MTCDT-19186797";
00183 static uint8_t config_frequency_sub_band = 1;
00184 
00185 /*  config_app_id and config_app_key are for public networks.
00186 static uint8_t app_id[8] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
00187 std::vector<uint8_t> config_app_id;
00188 static uint8_t app_key[16] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
00189 std::vector<uint8_t> config_app_key;
00190 */
00191 
00192 uint8_t result;
00193 uint8_t data;
00194 uint8_t sf_val = mDot::SF_7;
00195 uint8_t pwr_val = 11; // dBm
00196 uint8_t swp_pwr;
00197 uint8_t swp_sf;
00198 
00199 // max size of text string for 6x8 font. Set to 12 if using 8x8 font
00200 char txtstr[17];
00201 
00202 int32_t mdot_ret;
00203 int32_t join_delay;
00204 
00205 osThreadId mainThreadID;
00206 
00207 // flags for push button debounce code
00208 bool pb1_low = false;
00209 bool pb2_low = false;
00210 bool toggle_text = false;
00211 bool sw1_state = false;
00212 bool sw2_state = false;
00213 
00214 uint32_t num_whole;
00215 uint16_t num_frac;
00216 
00217 uint32_t pressure;
00218 double current;
00219 
00220 bool exit_program = false;
00221 
00222 //EVB sensor variables
00223 MMA845x_DATA accel_data;
00224 MPL3115A2_DATA baro_data;
00225 uint16_t  lux_data;
00226 MMA845x* evbAccel;
00227 MPL3115A2* evbBaro;
00228 ISL29011* evbAmbLight;
00229 NCP5623B* evbBackLight;
00230 DOGS102* evbLCD;
00231 
00232 //MEMS sensor variables
00233 float TEMPERATURE_Value;
00234 float HUMIDITY_Value;
00235 float PRESSURE_Value;
00236 float PRESSURE_Temp_Value;
00237 AxesRaw_TypeDef MAG_Value;
00238 AxesRaw_TypeDef ACC_Value;
00239 AxesRaw_TypeDef GYR_Value;
00240 char buffer1[32];
00241 char buffer2[32];
00242 char buffer3[32];
00243 char buffer4[32];
00244 unsigned int ret = 0;
00245 
00246 mDot* mdot_radio;
00247 Mutex mdot_mutex;
00248 
00249 //MEMS shield sensor variables
00250 //static X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance();
00251 X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(I2C_SDA, I2C_SCL, PC_1);
00252 static Ticker ticker;
00253 
00254 
00255 GyroSensor *memsGyro;
00256 MotionSensor *memsAccel;
00257 MagneticSensor *memsMag;
00258 HumiditySensor *memsHumidity;
00259 PressureSensor *memsPressure;
00260 TempSensor *memsTemp1;
00261 TempSensor *memsTemp2;
00262 
00263 
00264 GPSPARSER* mdot_gps;
00265 
00266 convert32 convertl;
00267 convert16 converts;
00268 
00269 void pb1ISR(void);
00270 void pb2ISR(void);
00271 void pb1_debounce(void const *args);
00272 void pb2_debounce(void const *args);
00273 
00274 MPL3115A2* resetBaro(const MPL3115A2* oldBaro);
00275 void log_error(mDot* dot, const char* msg, int32_t retval);
00276 int32_t sendString(const std::string text);
00277 bool writeValueOrError();
00278 
00279 const int FAIL_MAX=15;
00280 int failtime=FAIL_MAX;
00281 int cycle_cnt = 0;
00282 
00283 char sensor_text[64];
00284 char lora_temp_string[16];
00285 char lora_alt_string[16];
00286 char lora_press_string[16];
00287 char lora_light_string[16];
00288 char lora_current_string[16];
00289 char lora_humid_string[16];
00290 
00291 bool bHasGPS = false;
00292 bool bHasACC = false;
00293 bool bHasLCD = false;
00294 
00295 /*** Helper Functions ------------------------------------------------------------ ***/
00296 /* print floats & doubles */
00297 static char *printDouble(char* str, double v, int decimalDigits=2)
00298 {
00299   int i = 1;
00300   int intPart, fractPart;
00301   int len;
00302   char *ptr;
00303 
00304   /* prepare decimal digits multiplicator */
00305   for (;decimalDigits!=0; i*=10, decimalDigits--);
00306 
00307   /* calculate integer & fractinal parts */
00308   intPart = (int)v;
00309   fractPart = (int)((v-(double)(int)v)*i);
00310 
00311   /* fill in integer part */
00312   sprintf(str, "%i.", intPart);
00313 
00314   /* prepare fill in of fractional part */
00315   len = strlen(str);
00316   ptr = &str[len];
00317 
00318   /* fill in leading fractional zeros */
00319   for (i/=10;i>1; i/=10, ptr++) {
00320       if(fractPart >= i) break;
00321       *ptr = '0';
00322   }
00323 
00324   /* fill in (rest of) fractional part */
00325   sprintf(ptr, "%i", fractPart);
00326 
00327   return str;
00328 }
00329 /*===================================================================================
00330 Main Program Logic - Entry
00331 ===================================================================================*/
00332 int main()
00333 {
00334     std::vector<uint8_t> mdot_data;
00335     std::vector<uint8_t> mdot_EUI;
00336     uint16_t i = 0;
00337     uint8_t id1 = 0;
00338 
00339     debugUART.baud(9600);
00340 
00341     printf ("Starting Application...\r\n");
00342 
00343     mainThreadID = osThreadGetId();
00344 
00345     printf("Begin I2C/SPI Device Initialization...\r\n");
00346 
00347 
00348     // Use Magnetometer As MEMS sensor shield Enumeration...
00349 
00350     memsMag = mems_expansion_board->magnetometer;
00351     CALL_METH(memsMag, ReadID, &id1, 0x0);
00352     printf("Magnetometer ID value = %i \n\r", id1);
00353 
00354     //chcek for default magnetomter ID 61...
00355     if(id1 == 61)
00356     {
00357         printf("Magnetometer Found - MEMS sensor shield detected...\r\n");
00358         bHasACC = true;
00359 
00360         // Initialize Integrated Sensors...
00361         printf("Instantiate Magnetometer...\r\n");
00362         memsMag = mems_expansion_board->magnetometer;
00363 
00364         printf("Instantiate Accelerometer...\r\n");
00365         memsAccel = mems_expansion_board->GetAccelerometer();
00366 
00367         printf("Instantiate Gyroscope...\r\n");
00368         memsGyro = mems_expansion_board->GetGyroscope();
00369 
00370         printf("Instantiate Barometric Pressure Sensor...\r\n");
00371         memsPressure = mems_expansion_board->pt_sensor;
00372 
00373         printf("Instantiate Temperature Pressure Sensor...\r\n");
00374         //memsTemp1 = mems_expansion_board->ht_sensor;
00375         memsTemp2 = mems_expansion_board->pt_sensor;
00376 
00377         printf("Instantiate Humidity Sensor...\r\n");
00378         memsHumidity = mems_expansion_board->ht_sensor;
00379 
00380     }
00381 
00382 
00383     else
00384     {
00385         printf("No Magnetometer Found...\r\n");
00386         // Use Accelerometer As MDOT-BOX/EVB Enumeration...
00387         printf("Instantiate Accelerometer...\r\n");
00388         evbAccel = new MMA845x(mDoti2c,MMA845x::SA0_VSS);
00389 
00390         printf("Accelerometer Status = %d\r\n", evbAccel->getStatus());
00391         printf("Accelerometer who_am_i value = %x \n\r", evbAccel->getWhoAmI());
00392 
00393         if( (evbAccel->getStatus() == 1) && (evbAccel->getWhoAmI() == 0) )
00394         {
00395             printf("No Accelerometer Found - Basic mDot, Not MDOT-BOX or EVB...\r\n");
00396         }
00397 
00398         else
00399         {
00400             printf("Accelerometer Found - Either MDOT-BOX or EVB...\r\n");
00401             bHasACC = true;
00402 
00403         // Initialize Integrated Sensors...
00404             printf("Instantiate Barometric Pressure Sensor...\r\n");
00405             evbBaro = new MPL3115A2(mDoti2c);       // Setup Barometric Sensor
00406             printf("Barometric Sensor Status = %d\r\n", evbBaro->getStatus());
00407             printf("Barometer who_am_i check = %d\r\n", evbBaro->testWhoAmI());
00408             printf("Barometer who_am_i check = %s\r\n", evbBaro->testWhoAmI() ? "TRUE" : "FALSE");
00409 
00410             if( evbBaro->getStatus() == 0 ) printf("No Barometric Sensor...\r\n");
00411 
00412             printf("Instantiate Ambient Light Sensor...\r\n");
00413             evbAmbLight = new ISL29011(mDoti2c);    // Setup Ambient Light Sensor
00414 
00415             // Setup the Accelerometer for 8g range, 14 bit resolution, Noise reduction off, sample rate 1.56 Hz
00416             // Normal oversample mode, High pass filter off
00417             evbAccel->setCommonParameters(MMA845x::RANGE_8g,MMA845x::RES_MAX,MMA845x::LN_OFF, MMA845x::DR_1_56,MMA845x::OS_NORMAL,MMA845x::HPF_OFF );
00418 
00419             // Setup the Barometric sensor for post processed Ambient pressure, 4 samples per data acquisition.
00420             // and a sample taken every second when in active mode
00421             evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
00422 
00423             // Setup the Ambient Light Sensor for continuous Ambient Light Sensing, 16 bit resolution, and 16000 lux range
00424             evbAmbLight->setMode(ISL29011::ALS_CONT);
00425             evbAmbLight->setResolution(ISL29011::ADC_16BIT);
00426             evbAmbLight->setRange(ISL29011::RNG_16000);
00427 
00428             // Set the accelerometer for active mode
00429             evbAccel->activeMode();
00430 
00431             // Clear the min-max registers in the Barometric Sensor
00432             evbBaro->clearMinMaxRegs();
00433 
00434             // Support Integrated LCD Display
00435             bHasLCD = true;
00436 
00437             printf("Instantiate BackLight and LCD Display...\r\n");
00438             evbBackLight = new NCP5623B(mDoti2c);               // setup backlight and LED 2 driver chip
00439 
00440             evbLCD = new DOGS102(mDotspi, mDot17, mDot13);      // setup LCD Display
00441 
00442             printf("Font Table Address:  %p\r\n",&font_6x8);
00443             printf("Bitmap Logo Address:  %p\r\n",&MultiTech_Logo);
00444 
00445             // Setup and display logo on LCD
00446             evbLCD->startUpdate();
00447             evbLCD->writeBitmap(0,0,MultiTech_Logo);
00448 
00449             sprintf(txtstr,"MTDOT-EVB");
00450             evbLCD->writeText(24,3,font_6x8,txtstr,strlen(txtstr));
00451             sprintf(txtstr,"Sensor Demo");
00452             evbLCD->writeText(18,4,font_6x8,txtstr,strlen(txtstr));
00453 
00454             evbLCD->endUpdate();
00455 
00456             printf("Setup PushButton Interface Handlers...\r\n");
00457 
00458             printf("Launching Debounce Threads...\r\n");
00459             Thread thread_1(pb1_debounce);
00460             Thread thread_2(pb2_debounce);
00461             printf("Debounce Threads Launched...\r\n");
00462 
00463             printf("Set SW1/SW2 IRQs...\r\n");
00464             // Setup SW1 as Data rate and power out select
00465             mDot08.disable_irq();
00466             mDot08.fall(&pb1ISR);
00467 
00468             // need to call this function after rise or fall because rise/fall sets mode to PullNone
00469             mDot08.mode(PullUp);
00470             mDot08.enable_irq();
00471 
00472             // Setup SW2 as send PING
00473             mDot09.disable_irq();
00474             mDot09.fall(&pb2ISR);
00475 
00476             // need to call this function after rise or fall because rise/fall sets mode to PullNone
00477             mDot09.mode(PullUp);
00478             mDot09.enable_irq();
00479 
00480             // Setting other InterruptIn pins with Pull Ups
00481             mDot12.mode(PullUp);
00482             mDot15.mode(PullUp);
00483             mDot16.mode(PullUp);
00484 
00485             printf("SW1/SW2 IRQs Set...\r\n");
00486         }
00487     }
00488 
00489     printf("I2C/SPI Device Initialization Complete...\r\n");
00490 
00491     printf("\r\nSetup mDot Radio Communications...\r\n");
00492 
00493     // get a mDot handle
00494     mdot_radio = mDot::getInstance();
00495 
00496     if (mdot_radio)
00497     {
00498         // reset to default config so we know what state we're in
00499         mdot_mutex.lock();  // lock mdot before setting configuration
00500         mdot_radio->resetConfig();
00501 
00502         // Setting up LED1 as activity LED
00503         mdot_radio->setActivityLedPin(PB_0);
00504         mdot_radio->setActivityLedEnable(true);
00505 
00506         // Read node ID
00507         mdot_EUI = mdot_radio->getDeviceId();
00508         printf("mDot EUI = ");
00509 
00510         for(i=0; i<mdot_EUI.size(); i++) {
00511             printf("%02x ", mdot_EUI[i]);
00512         }
00513         printf("\r\n");
00514 
00515         // Setting up the mDot with network information.
00516 
00517         // This call sets up private or public mode on the MTDOT. Set the function to true if
00518         // connecting to a public network
00519         printf("Setting Private Network Mode...\r\n");
00520         if ((mdot_ret = mdot_radio->setPublicNetwork(false)) != mDot::MDOT_OK) {
00521             log_error(mdot_radio, "ERROR: Failed to set Public Network Mode", mdot_ret);
00522         }
00523 
00524         // Frequency sub-band is valid for NAM only and for Private networks should be set to a value
00525         // between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only.
00526         // This function can be commented out for EU networks
00527         printf("Setting Frequency Sub-Band...\r\n");
00528         if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
00529             log_error(mdot_radio, "ERROR: Failed to set Frequency Sub-Band", mdot_ret);
00530         }
00531 
00532         // Setting TX power for radio. Max allowed is +14dBm for EU and +20 dBm for NAM. Default is +11 dBm
00533         printf("Setting TX Power Level to %2d dBm...\r\n", pwr_val);
00534         if ((mdot_ret = mdot_radio->setTxPower(pwr_val)) != mDot::MDOT_OK) {
00535             log_error(mdot_radio, "ERROR: Failed to set TX Power Level", mdot_ret);
00536         }
00537 
00538         // Setting TX data rate for radio. Max allowed is SF_12 for EU and SF10 dBm for NAM. Default is SF_10
00539         printf("Setting TX data rate to SF_7...\r\n");
00540         if ((mdot_ret = mdot_radio->setTxDataRate(sf_val)) != mDot::MDOT_OK) {
00541             log_error(mdot_radio, "ERROR: Failed to set TX Data Rate", mdot_ret);
00542         }
00543 
00544         // Configure Pushbutton Display Labels...
00545         sprintf(txtstr,"SF=%2d PWR=%2d",sf_val,pwr_val);
00546         if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00547         printf("%s\r\n",txtstr);
00548 
00549 
00550         // Setting Packet ACK to 1 try.
00551 
00552         printf("Setting Packet Retry to 1...\r\n");
00553         if ((mdot_ret = mdot_radio->setAck(1)) != mDot::MDOT_OK) {
00554             log_error(mdot_radio, "ERROR: Failed to set Packet Retry\r\n", mdot_ret);
00555         }
00556 
00557 
00558         // setNetworkName is used for private networks.
00559         // Use setNetworkID(AppID) for public networks
00560 
00561         // config_app_id.assign(app_id,app_id+7);
00562 
00563         printf("Setting Network Name...\r\n");
00564         if ((mdot_ret = mdot_radio->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
00565         // if ((mdot_ret = mdot_radio->setNetworkID(config_app_id)) != mDot::MDOT_OK) {
00566             log_error(mdot_radio, "ERROR: Failed to set Network Name", mdot_ret);
00567         }
00568 
00569         // setNetworkPassphrase is used for private networks
00570         // Use setNetworkKey for public networks
00571 
00572         // config_app_key.assign(app_key,app_key+15);
00573 
00574         printf("Setting Network Password...\r\n");
00575         if ((mdot_ret = mdot_radio->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
00576         // if ((mdot_ret = mdot_radio->setNetworkKey(config_app_key)) != mDot::MDOT_OK) {
00577             log_error(mdot_radio, "ERROR: Failed to set Network Password", mdot_ret);
00578         }
00579 
00580         mdot_mutex.unlock();        // unlock mdot mutex before join attempt so SW1 can work
00581 
00582         // attempt to join the network
00583         printf("Joining LoRa Network...\r\n");
00584         do {
00585             mdot_mutex.lock();      // lock mdot mutex before join attempt
00586             mdot_ret = mdot_radio->joinNetwork();
00587             mdot_mutex.unlock();        // unlock mdot mutex after join attempt so SW1 can work
00588 
00589             if (mdot_ret != mDot::MDOT_OK)
00590             {
00591                 log_error(mdot_radio,"ERROR: Failed to Join Network:", mdot_ret);
00592 
00593                 if (toggle_text)
00594                     sprintf(txtstr," > Join Failed <");
00595                 else
00596                     sprintf(txtstr," < Join Failed >");
00597 
00598                 if( bHasLCD ) evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00599 
00600                 if (mdot_radio->getFrequencyBand() == mDot::FB_868)
00601                 {
00602                     join_delay = mdot_radio->getNextTxMs();
00603                 }
00604                 else
00605                 {
00606                     join_delay = 10;
00607                 }
00608                 printf("Join Delay = %lu\r\n",join_delay);
00609                 osDelay(join_delay + 1);
00610                 toggle_text = !toggle_text;
00611             }
00612 
00613             /*
00614              * Setting TX power and Data Rate for radio just in case user requested by SW2
00615              */
00616             mdot_mutex.lock();      // lock mdot mutex before setting change
00617             mdot_radio->setTxPower(pwr_val);
00618             mdot_radio->setTxDataRate(sf_val);
00619             mdot_mutex.unlock();        // unlock mdot mutex after settings change so SW1 can work
00620 
00621         } while (mdot_ret != mDot::MDOT_OK);
00622 
00623         printf("Successfully Joined LoRa Network...\r\n");
00624 
00625         sprintf(txtstr,"*Network Joined*");
00626         if( bHasLCD ) evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00627 
00628     }
00629     else
00630     {
00631         printf("ERROR:  Unable to Join LoRa Network...\r\n");
00632         sprintf(txtstr,"Radio Init Failed!");
00633         if( bHasLCD ) evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00634         printf("%s\r\n",txtstr);
00635         exit(1);
00636     }
00637 
00638     // Check for MDOT-BOX Configuration (GPS)
00639 
00640     if( bHasACC && bHasLCD )
00641     {
00642         printf("Instantiate GPS...\r\n");
00643         mdot_gps = new GPSPARSER(&mDotUART);
00644 
00645         if(!mdot_gps->gpsDetected())
00646         {
00647             printf(">>>> No GPS Detected... Not an MDOT-BOX, EVB Identified\r\n");
00648 
00649             sprintf(txtstr,"*No GPS Detected*");
00650             if( bHasLCD ) evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
00651         }
00652         else
00653         {
00654             // main_single = main_sweep = false;
00655             do
00656             {
00657                 // osSignalWait(0x10, 2000);
00658                 if (mdot_gps->getLockStatus())
00659                 {
00660                     sprintf(txtstr,"!!GPS locked!!");
00661                     if( bHasLCD ) evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
00662                     printf("%s \r\n",txtstr);
00663                 }
00664                 else
00665                 {
00666                     if (toggle_text)
00667                         sprintf(txtstr," > no GPS lock <");
00668                     else
00669                         sprintf(txtstr," < no GPS lock >");
00670 
00671                     if( bHasLCD ) evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
00672                     printf("%s \r\n",txtstr);
00673                     toggle_text = !toggle_text;
00674                 }
00675             } while ( !(mdot_gps->getLockStatus()) );
00676         }
00677     }
00678 
00679     printf("Initialization/Configuration Completed...\r\n");
00680 
00681     osDelay(1500);
00682     if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
00683 
00684     // sets LED2 to 50% max current
00685     if( bHasLCD ) evbBackLight->setLEDCurrent(16);
00686 
00687 
00688     // Check for PB1 press during network join attempt
00689     /*
00690     if (exit_program)
00691     {
00692         printf("PB1 Pressed, Exiting Program...\r\n");
00693         if( bHasLCD ) evbLCD->clearBuffer();
00694         sprintf(txtstr,"Exiting Program");
00695         if( bHasLCD ) evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
00696         exit(1);
00697     }
00698     */
00699 
00700     // Enter Main Data Acquisition Loop...
00701     printf("Processing Data Acquisition Scan Loop...\r\n");
00702 
00703     i = 0;
00704     cycle_cnt = 100;
00705 
00706     if( bHasLCD ) evbLCD->clearBuffer();
00707 
00708     do
00709     {
00710         //EVB
00711         if( bHasACC && bHasLCD )
00712         {
00713             // Check Accelerometer XYZ data ready bit to see if acquisition complete
00714             failtime = FAIL_MAX;
00715             do
00716             {
00717                 osDelay(100);           // allows other threads to process
00718                 result = evbAccel->getStatus();
00719                 failtime--;
00720             } while ((result & MMA845x::XYZDR) == 0 && failtime > 0);
00721 
00722             if (failtime==0)
00723             {
00724                 evbBaro=resetBaro(evbBaro);
00725                 continue;
00726             }
00727 
00728             // Retrieve and print out accelerometer data
00729             accel_data = evbAccel->getXYZ();
00730             sprintf(txtstr, "Accel-X = %d", accel_data._x);
00731             evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr));
00732             sprintf(txtstr, "Accel-Y = %d", accel_data._y);
00733             evbLCD->writeText(0,1,font_6x8,txtstr,strlen(txtstr));
00734             sprintf(txtstr, "Accel-Z = %d", accel_data._z );
00735             evbLCD->writeText(0,2,font_6x8,txtstr,strlen(txtstr));
00736 
00737             // Trigger a Barometric Pressure Reading
00738             evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
00739             evbBaro->triggerOneShot();
00740 
00741             // Test Barometer Device, Check to see if acquisition is complete
00742             failtime=FAIL_MAX;
00743             do
00744             {
00745                 osDelay(100);           // allows other threads to process
00746                 result = evbBaro->getStatus();
00747                 failtime--;
00748             } while ((result & MPL3115A2::PTDR) == 0 && failtime > 0 );
00749 
00750             if(failtime==0)
00751             {
00752                 evbBaro=resetBaro(evbBaro);
00753                 continue;
00754             }
00755 
00756             // Retrieve and Display Barometric Pressure
00757             pressure = evbBaro->getBaroData() >> 12;    // convert 32 bit signed to 20 bit unsigned value
00758             num_whole = pressure >> 2;                  // 18 bit integer significant
00759             num_frac = (pressure & 0x3) * 25;           // 2 bit fractional  0.25 per bit
00760 
00761             // If failtime reached 0 , indicates that the result might be junk.
00762             sprintf(txtstr,"Press=%ld.%01d Pa", num_whole, num_frac/10);
00763 
00764             pressure = evbBaro->getBaroData() >> 12;    // convert 32 bit signed to 20 bit unsigned value
00765             num_whole = pressure >> 2;                  // 18 bit integer significant
00766             num_frac = (pressure & 0x3) * 25;           // 2 bit fractional  0.25 per bit
00767 
00768             writeValueOrError();                        // will write to  lorapresstring and txtstr
00769 
00770             // Trigger a Altitude reading
00771             // evbBaro->setAltitudeCalib(101);
00772             evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_ALTIMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
00773             // evbBaro->setAltitudeCalib(101);
00774             evbBaro->triggerOneShot();
00775 
00776             // Test barometer device status to see if acquisition is complete
00777             failtime=FAIL_MAX;
00778             do
00779             {
00780                 osDelay(100);           // allows other threads to process
00781                 result = evbBaro->getStatus();
00782                 failtime--;
00783             } while ((result & MPL3115A2::PTDR) == 0 && failtime > 0 );
00784 
00785             if (failtime==0)
00786             {
00787                 evbBaro=resetBaro(evbBaro);
00788                 continue;
00789             }
00790 
00791             // Retrieve and Display Altimeter Reading
00792             baro_data = evbBaro->getAllData(false);
00793             baro_data._baro /= 4096;                                    // convert 32 bit signed to 20 bit signed value
00794             num_whole = baro_data._baro / 16;                           // 18 bit signed significant integer (JEK Added 60 as SWAG Offset for Boca)
00795             num_frac = (baro_data._baro & 0xF) * 625 / 100;             // 4 bit fractional .0625 per bit
00796             sprintf(txtstr,"Alti=%ld.%03d m", num_whole, num_frac);
00797             sprintf(lora_alt_string,"%ld.%03d", num_whole, num_frac);
00798             evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
00799 
00800             // Retrieve and Display Temperature Reading
00801             num_whole = baro_data._temp / 16;                           // 8 bit signed significant integer
00802             num_frac = (baro_data._temp & 0x0F) * 625 / 100;            // 4 bit fractional .0625 per bit
00803             sprintf(txtstr,"Temp=%ld.%03d C", num_whole, num_frac);
00804             sprintf(lora_temp_string,"%ld.%03d", num_whole, num_frac);
00805             evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00806 
00807             // Retrieve and Display Ambient Light Level
00808             lux_data = evbAmbLight->getData();
00809             num_whole = lux_data * 24 / 100;        // 16000 lux full scale .24 lux per bit
00810             num_frac = lux_data * 24 % 100;
00811             sprintf(txtstr, "Light=%ld.%02d lux", num_whole, num_frac );
00812             sprintf(lora_light_string, "%ld.%02d", num_whole, num_frac );
00813             evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
00814 
00815             // Retrieve and Display Current Sensor Level (EVB Analog Input)
00816             current = (double) current_sensor * 65535.0;
00817             sprintf(lora_current_string, "%d", (int) current);
00818 
00819             // Handle Pushbutton #1 (SW1) - This should be handled by the 'pb1_debounce' thread.
00820             if( pb1_low )
00821             {
00822                 sw1_state = !sw1_state;
00823                 if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,0);  // enable LED2 on EVB and set to 0% PWM
00824 
00825                 sprintf(txtstr,"PB1 Press-SW1: %d", sw1_state);
00826                 if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00827                 printf("%s \r\n",txtstr);
00828 
00829                 pb1_low = false;
00830             }
00831 
00832             // Handle Pushbutton #2 (SW2) - This should be handled by the 'pb2_debounce' thread.
00833              if( pb2_low )
00834             {
00835                 sw2_state = !sw2_state;
00836                 if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
00837 
00838                 sprintf(txtstr,"PB2 Press-SW2: %d", sw2_state);
00839                 if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00840                 printf("%s \r\n",txtstr);
00841 
00842                 pb2_low = false;
00843             }
00844         }
00845         //MEMS
00846         else if(!bHasLCD && bHasACC)
00847         {
00848 
00849             std::vector<uint8_t> tx_data;
00850 
00851 
00852             // Payload structure for mydevices cayenne:
00853             // 1 byte Data1 ID
00854             // 1 Byte Data1 Type
00855             // N Bytes Data1
00856             // 1 byte data 2 ID
00857             // 1 byte data 2 type
00858             // n Bytes data 2
00859             // ...
00860 
00861             // formats:
00862             // Temperature sensor:
00863             /*
00864              * IPSO: 3303
00865              * LPP 103
00866              * HEX: 67
00867              * Data size: 2
00868              * Resolution: 0.1 degres C
00869 
00870              * Humidity sensor
00871              * IPSO: 3304
00872              * LPP: 104
00873              * Hex: 68
00874              * Datasize: 1
00875              * Resolution: 0.5% unsigned
00876 
00877              * Barometer/pressure sensor
00878              * IPSO: 3315
00879              * LPP: 115
00880              * Hex: 73
00881              * Datasize: 2
00882              * Resolution 0.1hPa unsigned MSB
00883 
00884              * Accelerometer
00885              * IPSO: 3313
00886              * LPP: 113
00887              * Hex: 71
00888              * Data size: 6
00889              * Resolution: 0.001G signed MSB per axis
00890 
00891              * Gyrometer
00892              * IPSO: 3334
00893              * LPP: 134
00894              * Hex: 86
00895              * Data size: 6
00896              * Resolution: 0.01 degrees/s signed msb per axis
00897             */
00898 
00899             //temp floats
00900             float temp_value, humid_value, pressure_value;
00901             int16_t int_temp_value, int_humid_value, int_pressure_value;
00902 
00903             // HTS221 Humidity sensor
00904 
00905             ret |= (!CALL_METH(memsTemp1, GetTemperature, &temp_value, 0.0f) ? 0x0 : 0x1);
00906             ret |= (!CALL_METH(memsHumidity, GetHumidity, &humid_value, 0.0f) ? 0x0 : 0x2);;
00907 
00908             /*
00909             //serialize data and append to packet
00910             // Cayenne data: temperature; tag is 0x67, 2 bytes signed, 0.1 C/bit
00911             tx_data.push_back(uint8_t(1)); // data id
00912             tx_data.push_back(uint8_t(0x67)); // data type - temp
00913             int_temp_value = floor(temp_value*10 + 0.5f);
00914             tx_data.push_back(uint8_t( 0xFF & (int_temp_value >> 8)));
00915             tx_data.push_back(uint8_t(0xFF & int_temp_value));
00916 
00917 
00918             tx_data.push_back(uint8_t(2)); // data id
00919             tx_data.push_back(uint8_t(0x68)); // data type - humidity
00920             int_humid_value = floor(humid_value * 2.0f + 0.5f);
00921             tx_data.push_back(uint8_t(0xFF & int_humid_value ));
00922             */
00923 
00924             ret |= (!CALL_METH(memsPressure, GetPressure, &pressure_value, 0.0f) ? 0x0 : 0x4);;
00925 
00926             /*
00927             // pressure is reported in mbar, cayenne wants it in 0.1 hPa
00928             // 1mbar = 1 hPa
00929             int_pressure_value = floor(pressure_value * 100.0f + 0.5f);
00930 
00931             tx_data.push_back(uint8_t(3)); // data id
00932             tx_data.push_back(uint8_t(0x73)); // data type - pressure
00933             int_pressure_value = floor(pressure_value / 0.1f + 0.5f);
00934             tx_data.push_back(uint8_t(0xFF & (int_pressure_value >> 8)));
00935             tx_data.push_back(uint8_t(0xFF & int_pressure_value));
00936             */
00937 
00938             // Get accelerometer data
00939             int32_t accel_vector[3];
00940             // returns in mG
00941             memsAccel->Get_X_Axes(accel_vector);
00942 
00943             /*
00944             tx_data.push_back(uint8_t(4)); // data id
00945             tx_data.push_back(uint8_t(0x71)); // data type - accelerometer
00946             for(int i=0; i<3; i++) {
00947                 tx_data.push_back(uint8_t(0xFF & accel_vector[i]) >> 8);
00948                 tx_data.push_back(uint8_t(0xFF & accel_vector[i]));
00949             }
00950             */
00951 
00952             // Get gyro data
00953             int32_t gyro_vector[3];
00954             memsGyro->Get_G_Axes(gyro_vector);
00955 
00956             /*
00957             // gyro reports in milidegrees/sec, cayenne wants centidegrees/sec
00958             tx_data.push_back(uint8_t(5)); //data id
00959             tx_data.push_back(uint8_t(0x86)); // data type - gyrometer
00960             for(int i=0; i<3; i++) {
00961                 gyro_vector[i] /= 10;
00962                 tx_data.push_back(uint8_t(0xFF & (gyro_vector[i] >> 8)));
00963                 tx_data.push_back(uint8_t(0xFF & gyro_vector[i]));
00964             }
00965             */
00966 
00967             // Get magnetometer data
00968             int32_t mag_vector[3];
00969             memsMag->Get_M_Axes(mag_vector);
00970             // gyro reports in milidegrees/sec, cayenne wants centidegrees/sec
00971 
00972            /*
00973             tx_data.push_back(uint8_t(5)); //data id
00974             tx_data.push_back(uint8_t(0x99)); // data type - mangetometer
00975             for(int i=0; i<3; i++) {
00976                 mag_vector[i] /= 10;
00977                 tx_data.push_back(uint8_t(0xFF & (mag_vector[i] >> 8)));
00978                 tx_data.push_back(uint8_t(0xFF & mag_vector[i]));
00979             }
00980             */
00981 
00982 
00983             //send_data(tx_data);
00984 
00985             //---------------------------------------------------------------------------
00986             // Verbose Text Format:  Least Data Payload, Most Human Readible
00987             //---------------------------------------------------------------------------
00988 
00989             /*
00990             if(!bHasLCD && bHasACC)
00991             {
00992 
00993                 sprintf(sensor_text, "accel-x:%d|accel-y:%d|accel-z:%d|gyro-x:%d|gyro-y:%d|gyro-z:%d|mag-x:%d|mag-y:%d|mag-x:%d|press:%s|temp:%s|humid:%s",
00994                     accel_vector[0],
00995                     accel_vector[1],
00996                     accel_vector[2],
00997                     gyro_vector[0],
00998                     gyro_vector[1],
00999                     gyro_vector[2],
01000                     mag_vector[0],
01001                     mag_vector[1],
01002                     mag_vector[2],
01003                     printDouble(buffer3, pressure_value),
01004                     printDouble(buffer1, temp_value),
01005                     printDouble(buffer2, humid_value));
01006             }
01007             else
01008             {
01009                 sprintf(sensor_text, "accel-x:%d|accel-y:%d|accel-z:%d|press:%s|alti:%s|temp:%s|light:%s|moist:%s",
01010                     accel_data._x,
01011                     accel_data._y,
01012                     accel_data._z,
01013                     lora_press_string,
01014                     lora_alt_string,
01015                     lora_temp_string,
01016                     lora_light_string,
01017                     lora_current_string);
01018 
01019             }
01020 
01021 
01022              if ((mdot_ret = sendString((const std::string)sensor_text)) != mDot::MDOT_OK) {
01023                 log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret);
01024             } else {
01025                 printf("Ok, Successfully Sent Data to Gateway...\r\n");
01026             }
01027             */
01028 
01029             if( cycle_cnt > 30 )
01030             {              
01031                 sprintf(txtstr,"Transmitting... ");
01032                 if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
01033 
01034 
01035                 //---------------------------------------------------------------------------
01036                 // Byte Vector Format:  More Data Payload, Less Human Readible
01037                 //---------------------------------------------------------------------------
01038     
01039                 if(!bHasLCD && bHasACC)
01040                 {
01041     
01042                     sprintf(sensor_text, "ax:%d,ay:%d,az:%d,gx:%d,gy:%d,gz:%d,mx:%d,my:%d,mz:%d,p:%s,t:%s,h:%s",
01043                         accel_vector[0],
01044                         accel_vector[1],
01045                         accel_vector[2],
01046                         gyro_vector[0],
01047                         gyro_vector[1],
01048                         gyro_vector[2],
01049                         mag_vector[0],
01050                         mag_vector[1],
01051                         mag_vector[2],
01052                         printDouble(buffer3, pressure_value),
01053                         printDouble(buffer1, temp_value),
01054                         printDouble(buffer2, humid_value));
01055                 }
01056     
01057                 else
01058                 {
01059                     sprintf(sensor_text, "x:%d,y:%d,z:%d,p:%s,al:%s,t:%s,l:%s,c:%s",
01060                         accel_data._x,
01061                         accel_data._y,
01062                         accel_data._z,
01063                         lora_press_string,
01064                         lora_alt_string,
01065                         lora_temp_string,
01066                         lora_light_string,
01067                         lora_current_string);
01068                 }
01069     
01070                 if ((mdot_ret = sendString((const std::string)sensor_text)) != mDot::MDOT_OK) {
01071                     log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret);
01072                 } else {
01073                     printf("Ok, Successfully Sent Data to Gateway...\r\n");
01074                 }
01075     
01076                 /*
01077                 //---------------------------------------------------------------------------
01078                 // Binary Encoded Format:  Most Data Payload, Not Human Readible
01079                 //---------------------------------------------------------------------------
01080                 mdot_data.clear();
01081                 mdot_data.push_back(0x0E);              // key for Current Acceleration 3-Axis Value
01082                 converts.f_s = accel_data._x *4;        // shift data 2 bits while retaining sign
01083                 mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
01084                 converts.f_s = accel_data._y * 4;       // shift data 2 bits while retaining sign
01085                 mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
01086                 converts.f_s = accel_data._z * 4;       // shift data 2 bits while retaining sign
01087                 mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
01088                 mdot_data.push_back(0x08);              // key for Current Pressure Value
01089                 convertl.f_u = pressure;                // pressure data is 20 bits unsigned
01090                 mdot_data.push_back(convertl.t_u[2]);
01091                 mdot_data.push_back(convertl.t_u[1]);
01092                 mdot_data.push_back(convertl.t_u[0]);
01093                 mdot_data.push_back(0x05);              // key for Current Ambient Light Value
01094                 converts.f_u = lux_data;                // data is 16 bits unsigned
01095                 mdot_data.push_back(converts.t_u[1]);
01096                 mdot_data.push_back(converts.t_u[0]);
01097                 mdot_data.push_back(0x0B);              // key for Current Temperature Value
01098                 converts.f_s = baro_data._temp;         // temperature is signed 12 bit
01099                 mdot_data.push_back(converts.t_u[1]);
01100                 mdot_data.push_back(converts.t_u[0]);
01101     
01102                 if ((mdot_ret = mdot_radio->send(mdot_data)) != mDot::MDOT_OK) {
01103                     log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret);
01104                 } else {
01105                     printf("Ok, Successfully Sent Data to Gateway...\r\n");
01106                 }
01107     
01108                 */
01109     
01110                 osDelay(500);
01111                 sprintf(txtstr,"Scanning...     ");
01112                 if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
01113                 cycle_cnt = 0;
01114             }
01115         }
01116 
01117         osDelay(1000);
01118         cycle_cnt++;
01119 
01120         // Put Thread to Sleep for 30 Seconds...
01121         // osDelay(30000);
01122 
01123     } while(i < 86400);
01124 
01125     printf("End of Data Collection Cycle (24 Hours) - Ending Application, GoodBye...\r\n");
01126 
01127     if( bHasLCD ) evbLCD->clearBuffer();
01128     sprintf(txtstr,"Exiting Program");
01129     if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
01130 }
01131 
01132 /*** Interrupt Handler Top-Halves ------------------------------------------------------ ***/
01133 /* Called in interrupt context, therefore just set a trigger variable */
01134 static void timer_irq(void) {
01135     timer_irq_triggered = true;
01136 }
01137 
01138 /* Called in interrupt context, therefore just set a trigger variable */
01139 static void ff_irq(void) {
01140     ff_irq_triggered = true;
01141 
01142     /* Disable IRQ until handled */
01143     mems_expansion_board->gyro_lsm6ds3->Disable_Free_Fall_Detection_IRQ();
01144 }
01145 
01146 
01147 /*** Interrupt Handler Bottom-Halves ------------------------------------------------- ***/
01148 /* Handle Free Fall Interrupt
01149    (here we are in "normal" context, i.e. not in IRQ context)
01150 */
01151 static void handle_ff_irq(void) {
01152     printf("\nFree Fall Detected!\n\n");
01153 
01154     /* Re-enable IRQ */
01155     mems_expansion_board->gyro_lsm6ds3->Enable_Free_Fall_Detection_IRQ();
01156 }
01157 
01158 /*===================================================================================
01159 Send String Payload to Conduit Gateway
01160 ===================================================================================*/
01161 int32_t sendString(const std::string text)
01162 {
01163     int32_t ret;
01164     if (mdot_radio->getNextTxMs() != 0)
01165     {
01166         printf("Sending in %lu ms...\r\n", mdot_radio->getNextTxMs());
01167         return false;
01168     }
01169 
01170     printf("Sending: '%s'\r\n", text.c_str());
01171     std::vector<uint8_t> data(text.begin(), text.end());
01172     if ((ret = mdot_radio->send(data, 1)) != mDot::MDOT_OK)
01173     {
01174         log_error(mdot_radio, "ERROR: Failed to Send Data", ret);
01175     }
01176 
01177     return ret;
01178 }
01179 
01180 /*===================================================================================
01181 Interrupt Service Request Handler - Sets pb1_low flag. Flag is cleared in pb1_debounce thread
01182 ===================================================================================*/
01183 void pb1ISR(void)
01184 {
01185     pb1_low = true;
01186 }
01187 
01188 /*===================================================================================
01189 Pushbutton Debounce - Debounces pb1 PB1 changes SW1 State Value (Sets LED Off)
01190 ===================================================================================*/
01191 void pb1_debounce(void const *args)
01192 {
01193     printf("Thread pb1_debounce started...\r\n");
01194 
01195     while(true)
01196     {
01197         // if( pb1_low && (mDot08 == 0))
01198         if( pb1_low )
01199         {
01200             sprintf(txtstr,"PB1 Pressed...");
01201             if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
01202             printf("%s\r\n",txtstr);
01203 
01204             pb1_low = false;
01205         }
01206 
01207         Thread::wait(50);
01208     }
01209 }
01210 
01211 /*===================================================================================
01212 Interrupt Service Request Handler - Sets pb1_low flag. Flag is cleared in pb1_debounce thread
01213 ===================================================================================*/
01214 void pb2ISR(void)
01215 {
01216     pb2_low = true;
01217 }
01218 
01219 /*===================================================================================
01220 Pushbutton Debounce - Debounces pb2 PB2 changes SW2 State Value (Sets LED On)
01221 ===================================================================================*/
01222 void pb2_debounce(void const *args)
01223 {
01224     printf("Thread pb2_debounce started...\r\n");
01225 
01226     while(true)
01227     {
01228         // if( pb2_low && (mDot09 == 1))
01229         if( pb2_low )
01230         {
01231             sprintf(txtstr,"PB2 Pressed...");
01232             if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
01233             printf("%s \r\n",txtstr);
01234 
01235             pb2_low = false;
01236         }
01237 
01238         Thread::wait(50);
01239     }
01240 }
01241 
01242 /*===================================================================================
01243 Display Value/Error String of Barometric Pressure Sensor
01244 ===================================================================================*/
01245 bool writeValueOrError()
01246 {
01247     bool res;
01248 
01249     if (failtime==0)
01250     {
01251         sprintf(lora_press_string, "%s", "--.--");
01252         sprintf(txtstr, "%s", "--.--");
01253         if( bHasLCD ) evbLCD->writeText(0,4,font_6x8,txtstr, strlen(txtstr));
01254         res=false;
01255     }
01256     else
01257     {
01258         sprintf(lora_press_string, "%ld.%02d", num_whole, num_frac);
01259         if( bHasLCD ) evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
01260         res=true;
01261     }
01262 
01263     return res;
01264 }
01265 
01266 /*===================================================================================
01267 Resets Barometric Pressure Sensor
01268 ===================================================================================*/
01269 MPL3115A2* resetBaro(const MPL3115A2* oldBaro)
01270 {
01271     delete oldBaro;
01272     MPL3115A2* baro = new MPL3115A2(mDoti2c);
01273     baro->testWhoAmI();
01274 
01275     printf("Resetting barometer.. %x \n\r", baro->getStatus() );
01276     baro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
01277     evbBaro->clearMinMaxRegs();
01278 
01279     return baro;
01280 }
01281 
01282 /*===================================================================================
01283 Print clear text verion of mDot/EVB errors
01284 ===================================================================================*/
01285 void log_error(mDot* dot, const char* msg, int32_t retval)
01286 {
01287     printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str());
01288 }