Multi-Hackers / Mbed 2 deprecated MTDOT-EVBDemo

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

Go to the documentation of this file.
00001 /**
00002  * @file    main.cpp
00003  * @brief   Main application for mDot-EVB demo
00004  * @author  Tim Barr  MultiTech Systems Inc.
00005  * @version 1.05
00006  * @see
00007  *
00008  * Copyright (c) 2015
00009  *
00010  * Licensed under the Apache License, Version 2.0 (the "License");
00011  * you may not use this file except in compliance with the License.
00012  * You may obtain a copy of the License at
00013  *
00014  *     http://www.apache.org/licenses/LICENSE-2.0
00015  *
00016  * Unless required by applicable law or agreed to in writing, software
00017  * distributed under the License is distributed on an "AS IS" BASIS,
00018  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019  * See the License for the specific language governing permissions and
00020  * limitations under the License.
00021  *
00022  * 1.01 TAB 7/6/15 Removed NULL pointer from evbAmbientLight creation call.
00023  *
00024  * 1.02 TAB 7/8/15 Send logo to LCD before attempting connection to LoRa network. Added
00025  *                  information on setting up for public LoRa network. Moved SW setup to
00026  *                  beginning of main. Removed printf call from ISR functions. Added
00027  *                  additional checks for exit_program.
00028  *
00029  * 1.03 TAB 7/15/15 Added threads for push button switch debounce.
00030  *
00031  * 1.04 TAB 10/22/15 Fixed format error in temperature print to LCD. Corrected error in
00032  *                  public netework setup. Swapped \n and \r in prinf calls because
00033  *                  Windows seems to be picky about the order
00034  *
00035  * 1.05 TAB 11/17/15 Changed baud rate for debug from 921k to 115k. Added code to support
00036  *                   868 MHz band operation. Added mutex around certain mDot radio commands.
00037  *                   Changed network name and passphrase. Changed pb references to sw to
00038  *                   match MTDOT-BOX overlay. Changed function of SW1 from end program to
00039  *                   cycle through power levels and data rates.
00040  */
00041 
00042 #include "mbed.h"
00043 #include "MMA845x.h"
00044 #include "MPL3115A2.h"
00045 #include "ISL29011.h"
00046 #include "NCP5623B.h"
00047 #include "DOGS102.h"
00048 #include "font_6x8.h"
00049 #include "MultiTech_Logo.h"
00050 #include "mDot.h"
00051 #include "rtos.h"
00052 #include <string>
00053 #include <vector>
00054 
00055 enum LED1_COLOR {
00056     RED = 0,
00057     GREEN = 1
00058 };
00059 
00060 /*
00061  * union for converting from 32-bit to 4 8-bit values
00062  */
00063 union convert32 {
00064     int32_t f_s;        // convert from signed 32 bit int
00065     uint32_t f_u;       // convert from unsigned 32 bit int
00066     uint8_t t_u[4];     // convert to 8 bit unsigned array
00067 };
00068 
00069 /*
00070  * union for converting from 16- bit to 2 8-bit values
00071  */
00072 union convert16 {
00073     int16_t f_s;        // convert from signed 16 bit int
00074     uint16_t f_u;       // convert from unsigned 16 bit int
00075     uint8_t t_u[2];     // convert to 8 bit unsigned array
00076 };
00077 
00078 //DigitalIn mDot02(PA_2);                       //  GPIO/UART_TX
00079 //DigitalOut mDot03(PA_3);                      //  GPIO/UART_RX
00080 //DigitalIn mDot04(PA_6);                       //  GPIO/SPI_MISO
00081 //DigitalIn mDot06(PA_8);                       //  GPIO/I2C_SCL
00082 //DigitalIn mDot07(PC_9);                       //  GPIO/I2C_SDA
00083 
00084 InterruptIn mDot08(PA_12);                      //  GPIO/USB       PB SW1 on EVB
00085 InterruptIn mDot09(PA_11);                      //  GPIO/USB       PB SW2 on EVB
00086 
00087 //DigitalIn mDot11(PA_7);                       //  GPIO/SPI_MOSI
00088 
00089 InterruptIn mDot12(PA_0);                       //  GPIO/UART_CTS  PRESSURE_INT2 on EVB
00090 DigitalOut mDot13(PC_13,1);                     //  GPIO           LCD_C/D
00091 InterruptIn mDot15(PC_1);                       //  GPIO           LIGHT_PROX_INT on EVB
00092 InterruptIn mDot16(PA_1);                       //  GPIO/UART_RTS  ACCEL_INT2 on EVB
00093 DigitalOut mDot17(PA_4,1);                      //  GPIO/SPI_NCS   LCD_CS on EVB
00094 
00095 //DigitalIn mDot18(PA_5);                       //  GPIO/SPI_SCK
00096 
00097 //DigitalInOut mDot19(PB_0,PIN_INPUT,PullNone,0); // GPIO         PushPull LED Low=Red High=Green set MODE=INPUT to turn off
00098 AnalogIn mDot20(PB_1);                          //  GPIO          Current Sense Analog in on EVB
00099 
00100 Serial debugUART(PA_9, PA_10);              // mDot debug UART
00101 
00102 //Serial mDotUART(PA_2, PA_3);                  // mDot external UART mDot02 and mDot03
00103 
00104 I2C mDoti2c(PC_9,PA_8);                         // mDot External I2C mDot6 and mDot7
00105 
00106 SPI mDotspi(PA_7,PA_6,PA_5);                    // mDot external SPI mDot11, mDot4, and mDot18
00107 
00108 /* **** replace these values with the proper public or private network settings ****
00109  * config_network_name and config_network_pass are for private networks.
00110  */
00111 
00112 //Default network server settings
00113 static std::string config_network_name = "Multitech";
00114 static std::string config_network_pass = "Multitech";
00115 static uint8_t config_frequency_sub_band = 3;
00116 
00117 /*  config_app_id and config_app_key are for public networks.
00118 static uint8_t app_id[8] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
00119 std::vector<uint8_t> config_app_id;
00120 static uint8_t app_key[16] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
00121 std::vector<uint8_t> config_app_key;
00122 */
00123 
00124 uint8_t result, mdot_freq;
00125 uint8_t  pckt_time = 8;
00126 uint16_t xmit_delay = 8;
00127 char data;
00128 unsigned char test;
00129 char txtstr[17];
00130 int32_t num_whole, mdot_ret, join_delay;
00131 uint32_t pressure;
00132 int16_t num_frac;
00133 uint8_t sf_val = mDot::SF_7;
00134 uint8_t pwr_val = 11; // dBm
00135 
00136 MMA845x_DATA accel_data;
00137 MPL3115A2_DATA baro_data;
00138 uint16_t  lux_data;
00139 MMA845x* evbAccel;
00140 MPL3115A2* evbBaro;
00141 ISL29011* evbAmbLight;
00142 NCP5623B* evbBackLight;
00143 DOGS102* evbLCD;
00144 mDot* mdot_radio;
00145 Mutex mdot_mutex;
00146 
00147 convert32 convertl;
00148 convert16 converts;
00149 
00150 // flags for pushbutton debounce code
00151 bool sw1_low = false;
00152 bool sw2_low = false;
00153 bool toggle_text = false;
00154 
00155 void sw1ISR(void);
00156 void sw2ISR(void);
00157 void sw1_debounce(void const *args);
00158 void sw2_debounce(void const *args);
00159 Thread* thread_3;
00160 
00161 void log_error(mDot* dot, const char* msg, int32_t retval);
00162 
00163 void config_pkt_xmit (void const *args);
00164 
00165 int main()
00166 {
00167 
00168     std::vector<uint8_t> mdot_data;
00169     std::vector<uint8_t> mdot_EUI;
00170     uint16_t i = 0;
00171     uint8_t j =0;
00172 
00173     debugUART.baud(115200);
00174 //  mDotUART.baud(9600);    // mdot UART unused but available on external connector
00175 
00176     Thread thread_1(sw1_debounce);                      // threads for de-bouncing pushbutton switches
00177     Thread thread_2(sw2_debounce);
00178 
00179     thread_3 = new Thread(config_pkt_xmit);             // start thread that sends LoRa packet when SW2 pressed
00180 
00181     evbAccel = new MMA845x(mDoti2c,MMA845x::SA0_VSS);   // setup Accelerometer
00182     evbBaro = new MPL3115A2(mDoti2c);                   // setup Barometric sensor
00183     evbAmbLight = new ISL29011(mDoti2c);                // Setup Ambient Light Sensor
00184     evbBackLight = new NCP5623B(mDoti2c);               // setup backlight and LED 2 driver chip
00185     evbLCD = new DOGS102(mDotspi, mDot17, mDot13);      // setup LCD
00186 
00187     /*
00188      *  Setup SW1 as program stop function
00189      */
00190     mDot08.disable_irq();
00191     mDot08.fall(&sw1ISR);
00192 
00193     /*
00194      *  need to call this function after rise or fall because rise/fall sets
00195      *  mode to PullNone
00196      */
00197     mDot08.mode(PullUp);
00198 
00199     mDot08.enable_irq();
00200 
00201     /*
00202      *  Setup SW2 as packet time change
00203      */
00204     mDot09.disable_irq();
00205     mDot09.fall(&sw2ISR);
00206 
00207     /*
00208      *  need to call this function after rise or fall because rise/fall sets
00209      *  mode to PullNone
00210      */
00211     mDot09.mode(PullUp);
00212 
00213     mDot09.enable_irq();
00214 
00215     /*
00216     * Setting other InterruptIn pins with Pull Ups
00217     */
00218     mDot12.mode(PullUp);
00219     mDot15.mode(PullUp);
00220     mDot16.mode(PullUp);
00221 
00222     printf("font table address %p\r\n",&font_6x8);
00223     printf("bitmap address %p\r\n",&MultiTech_Logo);
00224 
00225 // Setup and display logo on LCD
00226     evbLCD->startUpdate();
00227 
00228     evbLCD->writeBitmap(0,0,MultiTech_Logo);
00229 
00230     printf("\r\n setup mdot\r\n");
00231 
00232     // get a mDot handle
00233     mdot_radio = mDot::getInstance();
00234 
00235     if (mdot_radio) {
00236         mdot_mutex.lock();  // lock mdot before setting configuration
00237 
00238         // reset to default config so we know what state we're in
00239         mdot_radio->resetConfig();
00240 
00241         // Setting up LED1 as activity LED
00242         mdot_radio->setActivityLedPin(PB_0);
00243         mdot_radio->setActivityLedEnable(true);
00244 
00245         // Read node ID and frequency band
00246         mdot_EUI = mdot_radio->getDeviceId();
00247         mdot_freq = mdot_radio->getFrequencyBand();
00248 
00249         printf("mDot EUI = ");
00250 
00251         for (i=0; i<mdot_EUI.size(); i++) {
00252             printf("%02x ", mdot_EUI[i]);
00253         }
00254         printf("\r\n");
00255         sprintf(txtstr,"MTDOT EVB");
00256         printf("mDot Frequency = ");
00257         if (mdot_freq == mDot::FB_868) {
00258             printf( "868 MHz\r\n");
00259             sprintf(txtstr,"%s 868 MHz",txtstr);
00260         } else {
00261             printf("915 MHz\r\n");
00262             sprintf(txtstr,"%s 915 MHz",txtstr);
00263         }
00264 
00265         evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
00266         sprintf(txtstr,"Sensor Demo");
00267         evbLCD->writeText(24,4,font_6x8,txtstr,strlen(txtstr));
00268 
00269         evbLCD->endUpdate();
00270 
00271 
00272 // Setting up the mDot with network information.
00273 
00274         /*
00275          * This call sets up private or public mode on the MTDOT. Set the function to true if
00276          * connecting to a public network
00277          */
00278         printf("setting Private Network Mode\r\n");
00279         if ((mdot_ret = mdot_radio->setPublicNetwork(false)) != mDot::MDOT_OK) {
00280             log_error(mdot_radio, "failed to set Public Network Mode", mdot_ret);
00281         }
00282 
00283         /*
00284          * Frequency sub-band is valid for NAM only and for Private networks should be set to a value
00285          * between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only.
00286          * This function can be commented out for EU networks
00287          */
00288         if (mdot_freq == mDot::FB_915) {
00289             printf("setting frequency sub band\r\n");
00290             if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
00291                 log_error(mdot_radio, "failed to set frequency sub band", mdot_ret);
00292             }
00293         }
00294 
00295         /*
00296          * setNetworkName is used for private networks.
00297          * Use setNetworkID(AppID) for public networks
00298          */
00299 
00300 //      config_app_id.assign(app_id,app_id+7);
00301 
00302         printf("setting network name\r\n");
00303         if ((mdot_ret = mdot_radio->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
00304 //      if ((mdot_ret = mdot_radio->setNetworkId(config_app_id)) != mDot::MDOT_OK) {
00305             log_error(mdot_radio, "failed to set network name", mdot_ret);
00306         }
00307 
00308         /*
00309          * setNetworkPassphrase is used for private networks
00310          * Use setNetworkKey for public networks
00311          */
00312 
00313 //      config_app_key.assign(app_key,app_key+15);
00314 
00315         printf("setting network password\r\n");
00316         if ((mdot_ret = mdot_radio->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
00317 //      if ((mdot_ret = mdot_radio->setNetworkKey(config_app_key)) != mDot::MDOT_OK) {
00318             log_error(mdot_radio, "failed to set network password", mdot_ret);
00319         }
00320 
00321         /*
00322           * Setting TX power for radio. Max allowed is +14dBm for EU and +20 dBm for NAM. Default is +11 dBm
00323           */
00324         printf("setting TX Power Level to %2d dBm\r\n", pwr_val);
00325         if ((mdot_ret = mdot_radio->setTxPower(pwr_val)) != mDot::MDOT_OK) {
00326             log_error(mdot_radio, "failed to set TX power level", mdot_ret);
00327         }
00328 
00329         /*
00330          * Setting TX data rate for radio. Max allowed is SF_12 for EU and SF10 dBm for NAM. Default is SF_9
00331          */
00332         printf("setting TX data rate to SF_7\r\n");
00333         if ((mdot_ret = mdot_radio->setTxDataRate(sf_val)) != mDot::MDOT_OK) {
00334             log_error(mdot_radio, "failed to set TX data rate", mdot_ret);
00335         }
00336 
00337         mdot_mutex.unlock();        // unlock mdot mutex before join attempt so SW1 can work
00338 
00339         // attempt to join the network
00340         printf("joining network\r\n");
00341         do {
00342             mdot_mutex.lock();      // lock mdot mutex before join attempt
00343             mdot_ret = mdot_radio->joinNetwork();
00344             mdot_mutex.unlock();        // unlock mdot mutex after join attempt so SW1 can work
00345 
00346             if (mdot_ret != mDot::MDOT_OK) {
00347                 log_error(mdot_radio,"failed to join network:", mdot_ret);
00348 
00349                 if (toggle_text)
00350                     sprintf(txtstr," > Join Failed <");
00351                 else
00352                     sprintf(txtstr," < Join Failed >");
00353 
00354                 evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00355 
00356                 if (mdot_radio->getFrequencyBand() == mDot::FB_868) {
00357                     join_delay = mdot_radio->getNextTxMs();
00358                 } else {
00359                     join_delay = 10;
00360                 }
00361                 printf("delay = %lu\r\n",join_delay);
00362                 osDelay(join_delay + 1);
00363                 toggle_text = !toggle_text;
00364             }
00365             /*
00366              * Setting TX power and Data Rate for radio just in case user requested by SW2
00367              */
00368             mdot_mutex.lock();      // lock mdot mutex before setting change
00369             mdot_radio->setTxPower(pwr_val);
00370             mdot_radio->setTxDataRate(sf_val);
00371             mdot_mutex.unlock();        // unlock mdot mutex after settings change
00372 
00373         } while (mdot_ret != mDot::MDOT_OK);
00374 
00375         sprintf(txtstr,"*Network Joined*");
00376         evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00377 
00378     } else {
00379         sprintf(txtstr,"Radio Init Failed!");
00380         evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00381         printf("%s\r\n",txtstr);
00382         exit(1);
00383     }
00384 
00385     osDelay(200);
00386     evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
00387 
00388     // sets LED2 to 50% max current
00389     evbBackLight->setLEDCurrent(16);
00390 
00391     printf("Start of Test\r\n");
00392 
00393     osDelay (500);          // allows other threads to process
00394     printf("shutdown LED:\r\n");
00395     evbBackLight->shutdown();
00396 
00397     osDelay (500);          // allows other threads to process
00398     printf("Turn on LED2\r\n");
00399     evbBackLight->setLEDCurrent(16);
00400 
00401     data = evbAccel->getWhoAmI();
00402     printf("Accelerometer who_am_i value = %x \r\n", data);
00403 
00404     result = evbAccel->getStatus();
00405     printf("status byte = %x \r\n", result);
00406 
00407     printf("Barometer who_am_i check = %s \r\n", evbBaro->testWhoAmI() ? "TRUE" : "FALSE");
00408 
00409     result = evbBaro->getStatus();
00410     printf("status byte = %x \r\n", result);
00411 
00412     /*
00413      *  Setup the Accelerometer for 8g range, 14 bit resolution, Noise reduction off, sample rate 1.56 Hz
00414      *  normal oversample mode, High pass filter off
00415      */
00416     evbAccel->setCommonParameters(MMA845x::RANGE_8g,MMA845x::RES_MAX,MMA845x::LN_OFF,
00417                                   MMA845x::DR_1_56,MMA845x::OS_NORMAL,MMA845x::HPF_OFF );
00418 
00419     /*
00420      * Setup the Barometric sensor for post processed Ambient pressure, 4 samples per data acquisition.
00421      * and a sample taken every second when in active mode
00422      */
00423     evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16,
00424                            MPL3115A2::AT_1);
00425     /*
00426      * Setup the Ambient Light Sensor for continuous Ambient Light Sensing, 16 bit resolution,
00427      * and 16000 lux range
00428      */
00429 
00430     evbAmbLight->setMode(ISL29011::ALS_CONT);
00431     evbAmbLight->setResolution(ISL29011::ADC_16BIT);
00432     evbAmbLight->setRange(ISL29011::RNG_16000);
00433 
00434     /*
00435      * Set the accelerometer for active mode
00436      */
00437     evbAccel->activeMode();
00438 
00439     /*
00440      * Clear the min-max registers in the Barometric Sensor
00441      */
00442     evbBaro->clearMinMaxRegs();
00443 
00444     evbBackLight->setLEDCurrent(0);
00445 
00446     /*
00447      * Main data acquisition loop
00448      */
00449 
00450     i = 0;
00451     
00452     do {
00453         evbLCD->startUpdate();
00454         // clear LCD line 0-6 only
00455         sprintf(txtstr, "                 ");
00456         for (j=0; j<6; j++)
00457             evbLCD->writeText(0,j,font_6x8,txtstr,strlen(txtstr));
00458 
00459         /*
00460          * Test Accelerometer XYZ data ready bit to see if acquisition complete
00461          */
00462         do {
00463             osDelay(100);           // allows other threads to process
00464             result = evbAccel->getStatus();
00465         } while ((result & MMA845x::XYZDR) == 0 );
00466 
00467         /*
00468          * Retrieve and print out accelerometer data
00469          */
00470         accel_data = evbAccel->getXYZ();
00471 
00472         sprintf(txtstr, "Accel: x = %d", accel_data._x);
00473         evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr));
00474         sprintf(txtstr, "y = %d", accel_data._y);
00475         evbLCD->writeText(42,1,font_6x8,txtstr,strlen(txtstr));
00476         sprintf(txtstr, "z = %d", accel_data._z );
00477         evbLCD->writeText(42,2,font_6x8,txtstr,strlen(txtstr));
00478 
00479         /*
00480          * Trigger a Pressure reading
00481          */
00482         evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16,
00483                                MPL3115A2::AT_1);
00484         evbBaro->triggerOneShot();
00485 
00486         /*
00487          * Test barometer device status to see if acquisition is complete
00488          */
00489         do {
00490             osDelay(100);           // allows other threads to process
00491             result = evbBaro->getStatus();
00492         } while ((result & MPL3115A2::PTDR) == 0 );
00493 
00494         /*
00495          * Retrieve and print out barometric pressure
00496          */
00497         pressure = evbBaro->getBaroData() >> 12; // convert 32 bit signed to 20 bit unsigned value
00498         num_whole = pressure >> 2;          // 18 bit integer significant
00499         num_frac = (pressure & 0x3) * 25;       // 2 bit fractional  0.25 per bit
00500         sprintf(txtstr,"Press=%ld.%02d Pa", num_whole, num_frac);
00501         evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
00502 
00503         /*
00504          * Trigger a Altitude reading
00505          */
00506         evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_ALTIMETER, MPL3115A2::OR_16,
00507                                MPL3115A2::AT_1);
00508         evbBaro->triggerOneShot();
00509 
00510         /*
00511          * Test barometer device status to see if acquisition is complete
00512          */
00513         do {
00514             osDelay(100);           // allows other threads to process
00515             result = evbBaro->getStatus();
00516         } while ((result & MPL3115A2::PTDR) == 0 );
00517 
00518         /*
00519          * Retrieve and print out altitude and temperature
00520          */
00521         baro_data = evbBaro->getAllData(false);
00522         baro_data._baro /= 4096;                // convert 32 bit signed to 20 bit signed value
00523         num_whole = baro_data._baro / 16;       //  18 bit signed significant integer
00524         num_frac = (baro_data._baro & 0xF) * 625 / 100;     // 4 bit fractional .0625 per bit
00525         sprintf(txtstr,"Alti=%ld.%02d m", num_whole, num_frac);
00526         evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
00527         num_whole = baro_data._temp / 16;       // 8 bit signed significant integer
00528         num_frac = (baro_data._temp & 0x0F) * 625 / 100;        // 4 bit fractional .0625 per bit
00529         sprintf(txtstr,"Temp=%ld.%03d C", num_whole, num_frac);
00530         evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
00531 
00532         /*
00533          * retrieve and print out Ambient Light level
00534          */
00535         lux_data = evbAmbLight->getData();
00536         num_whole = lux_data * 24 / 100;        // 16000 lux full scale .24 lux per bit
00537         num_frac = lux_data * 24 % 100;
00538         sprintf(txtstr, "Light=%ld.%02d lux", num_whole, num_frac );
00539         evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
00540 
00541         evbLCD->endUpdate();
00542 
00543         printf("finished iteration %d\r\n",(++i));
00544 
00545         /* Transmit data packet based on pckt_time setting and result of
00546          * mdot_radio->getNextTxMs() function and mutex available. The getNextTxMs()
00547          * function returns the number of millisecond before another packet can be
00548          * sent in 868 MHz band. This can vary depending on wther the 10%, 1% or 0.1%
00549          * channel is used and the time on air for a specific setup of the radio
00550          */
00551 
00552         if ((xmit_delay <= i) && (mdot_radio->getNextTxMs() == 0) && (mdot_mutex.trylock())) {
00553             /*
00554              * Setting TX power and Data Rate for radio just in case user requested by SW2
00555              */
00556             mdot_radio->setTxPower(pwr_val);
00557             mdot_radio->setTxDataRate(sf_val);
00558 
00559             mdot_data.clear();
00560             mdot_data.push_back(0x1D);          // key for start of data
00561             mdot_data.push_back(0x0E);          // key for Current Acceleration 3-Axis Value
00562             converts.f_s = accel_data._x *4;        // shift data 2 bits while retaining sign
00563             mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
00564             converts.f_s = accel_data._y * 4;       // shift data 2 bits while retaining sign
00565             mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
00566             converts.f_s = accel_data._z * 4;       // shift data 2 bits while retaining sign
00567             mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
00568             mdot_data.push_back(0x08);          // key for Current Pressure Value
00569             convertl.f_u = pressure;                // pressure data is 20 bits unsigned
00570             mdot_data.push_back(convertl.t_u[2]);
00571             mdot_data.push_back(convertl.t_u[1]);
00572             mdot_data.push_back(convertl.t_u[0]);
00573 
00574             /* for 915 MHz band and SF_10 max packet size is 11 bytes.
00575              * so the payload gets split in two packets here.
00576              */
00577             if ((mdot_freq == mDot::FB_915) && (sf_val == mDot::SF_10)) {
00578                 mdot_ret = mdot_radio->send(mdot_data);
00579                 if ( mdot_ret != mDot::MDOT_OK) {
00580                     sprintf(txtstr,"mDot Send failed");
00581                     evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00582                     log_error(mdot_radio, txtstr, mdot_ret);
00583                     continue;
00584                 } else {
00585                     printf("successfully sent packet 1 to gateway\r\n");
00586                 }
00587                 mdot_data.clear();      // clear data for next "chunk"
00588             }
00589 
00590 
00591             mdot_data.push_back(0x05);          // key for Current Ambient Light Value
00592             converts.f_u = lux_data;                // data is 16 bits unsigned
00593             mdot_data.push_back(converts.t_u[1]);
00594             mdot_data.push_back(converts.t_u[0]);
00595             mdot_data.push_back(0x0B);          // key for Current Temperature Value
00596             converts.f_s = baro_data._temp;     // temperature is signed 12 bit
00597             mdot_data.push_back(converts.t_u[1]);
00598             mdot_data.push_back(converts.t_u[0]);
00599             mdot_data.push_back(0x1D);          // key for end of data
00600 
00601             mdot_ret = mdot_radio->send(mdot_data);
00602             if (mdot_ret != mDot::MDOT_OK) {
00603                 log_error(mdot_radio, "failed to send", mdot_ret);
00604                 sprintf(txtstr,"PKT Send Failed");
00605                 evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00606             } else {
00607                 sprintf(txtstr,"SENT DR=%2d Pwr=%2d",(12 - sf_val),pwr_val);
00608                 evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00609                 printf("%s \r\n",txtstr);
00610             }
00611             mdot_mutex.unlock(); // unlock mutex after all data transmitted
00612             xmit_delay = i + pckt_time;
00613             if (mdot_freq == mDot::FB_868)
00614                 printf("Next transmit time = %d milliseconds \r\n",mdot_radio->getNextTxMs());
00615 
00616         } else {
00617             sprintf(txtstr,"     DR=%2d Pwr=%2d     ",(12 - sf_val),pwr_val);
00618             evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00619         }
00620     } while(i < 65000);
00621 
00622     evbBaro->triggerOneShot();
00623 
00624     do {
00625         osDelay(200);           // allows other threads to process
00626         result = evbBaro->getStatus();
00627     } while ((result & MPL3115A2::PTDR) == 0 );
00628 
00629     baro_data = evbBaro->getAllData(true);
00630     printf ("minBaro=%ld maxBaro=%ld minTemp=%d maxTemp=%d\r\n", baro_data._minbaro, baro_data._maxbaro,
00631             baro_data._mintemp, baro_data._maxtemp);
00632 
00633     printf("End of Test\r\n");
00634 
00635     evbLCD->clearBuffer();
00636     sprintf(txtstr,"Exiting Program");
00637     evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
00638 
00639 }
00640 
00641 /*
00642  * Sets sw1_low flag. Slag is cleared in sw1_debounce thread
00643  */
00644 void sw1ISR(void)
00645 {
00646     if (!sw1_low)
00647         sw1_low = true;
00648 }
00649 
00650 /*
00651  * Debounces sw1 changes spreading factor and output power
00652  * Cycles through SF_7-SF_9 for 4 power levels for 915 MHz band
00653  * Cycles through SF_7-SF_12 for 4 power levels for 868 MHz band
00654  */
00655 void sw1_debounce(void const *args)
00656 {
00657     static uint8_t count = 0;
00658     static uint8_t test_sf = 0;
00659     static uint8_t test_pwr = 0;
00660 
00661     while (true) {
00662 
00663         if (sw1_low && (mDot08 == 0))
00664             count++;
00665         else {
00666             count = 0;
00667             sw1_low = false;
00668         }
00669 
00670         if (count == 5) {
00671             test_sf++;
00672 
00673             if (((test_sf > 3) && (mdot_freq == mDot::FB_915)) || ((test_sf > 5) && (mdot_freq == mDot::FB_868))) {
00674                 test_sf = 0;
00675                 test_pwr ++;
00676                 if (test_pwr > 3)
00677                     test_pwr = 0;
00678             }
00679 
00680             // selects power output level using upper bits for select
00681             switch(test_pwr) {
00682                 case 0:
00683                     pwr_val = 11;
00684                     break;
00685                 case 1:
00686                     pwr_val = 14;
00687                     break;
00688                 case 2:
00689                     pwr_val = 18;
00690                     break;
00691                 case 3:
00692                     pwr_val = 20;
00693             }
00694 
00695             // sets data rate based on lower bits
00696             sf_val = mDot::SF_7 - (test_sf & 0x07);
00697 
00698             sprintf(txtstr,"     DR=%2d Pwr=%2d     ",(12 - sf_val),pwr_val);
00699             evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
00700             printf("%s \r\n",txtstr);
00701         }
00702 
00703         Thread::wait(5);
00704     }
00705 }
00706 
00707 /*
00708  * Sets sw2_low flag. Flag is cleared in sw2_debounce thread
00709  */
00710 void sw2ISR(void)
00711 {
00712     if (!sw2_low)
00713         sw2_low = true;
00714 }
00715 
00716 /*
00717  * Debounces sw2. Changes packet transmit time to every 2nd,
00718  * 4th, 8th, or 16th sample when SW2 pushed. For 868 MHz mode
00719  * the time for next packet value is also tested.
00720  * Also triggers a thread to transmit a configuration packet
00721  */
00722 void sw2_debounce(void const *args)
00723 {
00724 
00725     static uint8_t count = 0;
00726 
00727     while (true) {
00728 
00729         if (sw2_low && (mDot09 == 0))
00730             count++;
00731         else {
00732             count = 0;
00733             sw2_low = false;
00734         }
00735 
00736         if (count == 5) {
00737 
00738             if (pckt_time >= 4)
00739                 pckt_time /= 2;
00740             else pckt_time = 16;
00741 
00742             thread_3->signal_set(0x10);     // signal config_pkt_xmit to send packet
00743         }
00744 
00745         Thread::wait(5);
00746     }
00747 }
00748 
00749 /*
00750  *  Function that prints clear text verion of mDot errors
00751  */
00752 void log_error(mDot* dot, const char* msg, int32_t retval)
00753 {
00754     printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str());
00755 }
00756 
00757 /*
00758  * Thread that is triggered by SW2 ISR. Sends a packet to the LoRa server with the new Packet Transmission time setting
00759  */
00760 void config_pkt_xmit (void const *args)
00761 {
00762 
00763     std::vector<uint8_t> data;
00764     uint16_t wait_time;
00765 
00766     while (true) {
00767         Thread::signal_wait(0x10);      // wait for sw2ISR to signal send
00768         data.clear();
00769         data.push_back(0x0F);           // key for Configuration data (packet transmission timer)
00770         data.push_back(pckt_time);
00771         
00772         mdot_mutex.lock();      // lock mdot mutex before packet send
00773 
00774         if ((wait_time = mdot_radio->getNextTxMs()) > 0) // wait for next xmit time
00775             osDelay(wait_time);
00776 
00777         if ((mdot_ret = mdot_radio->send(data)) != mDot::MDOT_OK) {
00778             log_error(mdot_radio, "failed to send config data", mdot_ret);
00779         } else {
00780             printf("sent config data to gateway\r\n");
00781         }
00782         mdot_mutex.unlock();        // unlock mdot mutex after packet send
00783     }
00784 }