![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
Demonstration program for Multitech System MTDOT-EVB an evaluation board for the mDot LoRa module
Dependencies: DOGS102 ISL29011 MMA845x MPL3115A2 NCP5623B libmDot mbed-rtos mbed
main.cpp
- Committer:
- falingtrea
- Date:
- 2015-11-23
- Revision:
- 9:ed86d5ae29cc
- Parent:
- 7:85445a8cc189
File content as of revision 9:ed86d5ae29cc:
/** * @file main.cpp * @brief Main application for mDot-EVB demo * @author Tim Barr MultiTech Systems Inc. * @version 1.05 * @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.01 TAB 7/6/15 Removed NULL pointer from evbAmbientLight creation call. * * 1.02 TAB 7/8/15 Send logo to LCD before attempting connection to LoRa network. Added * information on setting up for public LoRa network. Moved SW setup to * beginning of main. Removed printf call from ISR functions. Added * additional checks for exit_program. * * 1.03 TAB 7/15/15 Added threads for push button switch debounce. * * 1.04 TAB 10/22/15 Fixed format error in temperature print to LCD. Corrected error in * public netework setup. Swapped \n and \r in prinf calls because * Windows seems to be picky about the order * * 1.05 TAB 11/17/15 Changed baud rate for debug from 921k to 115k. Added code to support * 868 MHz band operation. Added mutex around certain mDot radio commands. * Changed network name and passphrase. Changed pb references to sw to * match MTDOT-BOX overlay. Changed function of SW1 from end program to * cycle through power levels and data rates. */ #include "mbed.h" #include "MMA845x.h" #include "MPL3115A2.h" #include "ISL29011.h" #include "NCP5623B.h" #include "DOGS102.h" #include "font_6x8.h" #include "MultiTech_Logo.h" #include "mDot.h" #include "rtos.h" #include <string> #include <vector> 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 SW1 on EVB InterruptIn mDot09(PA_11); // GPIO/USB PB SW2 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 //Serial 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_name and config_network_pass are for private networks. */ //Default network server settings static std::string config_network_name = "Multitech"; static std::string config_network_pass = "Multitech"; static uint8_t config_frequency_sub_band = 3; /* config_app_id and config_app_key are for public networks. static uint8_t app_id[8] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D}; 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, mdot_freq; uint8_t pckt_time = 8; uint16_t xmit_delay = 8; char data; unsigned char test; char txtstr[17]; int32_t num_whole, mdot_ret, join_delay; uint32_t pressure; int16_t num_frac; uint8_t sf_val = mDot::SF_7; uint8_t pwr_val = 11; // dBm MMA845x_DATA accel_data; MPL3115A2_DATA baro_data; uint16_t lux_data; MMA845x* evbAccel; MPL3115A2* evbBaro; ISL29011* evbAmbLight; NCP5623B* evbBackLight; DOGS102* evbLCD; mDot* mdot_radio; Mutex mdot_mutex; convert32 convertl; convert16 converts; // flags for pushbutton debounce code bool sw1_low = false; bool sw2_low = false; bool toggle_text = false; void sw1ISR(void); void sw2ISR(void); void sw1_debounce(void const *args); void sw2_debounce(void const *args); Thread* thread_3; void log_error(mDot* dot, const char* msg, int32_t retval); void config_pkt_xmit (void const *args); int main() { std::vector<uint8_t> mdot_data; std::vector<uint8_t> mdot_EUI; uint16_t i = 0; uint8_t j =0; debugUART.baud(115200); // mDotUART.baud(9600); // mdot UART unused but available on external connector Thread thread_1(sw1_debounce); // threads for de-bouncing pushbutton switches Thread thread_2(sw2_debounce); thread_3 = new Thread(config_pkt_xmit); // start thread that sends LoRa packet when SW2 pressed evbAccel = new MMA845x(mDoti2c,MMA845x::SA0_VSS); // setup Accelerometer evbBaro = new MPL3115A2(mDoti2c); // setup Barometric sensor evbAmbLight = new ISL29011(mDoti2c); // Setup Ambient Light Sensor evbBackLight = new NCP5623B(mDoti2c); // setup backlight and LED 2 driver chip evbLCD = new DOGS102(mDotspi, mDot17, mDot13); // setup LCD /* * Setup SW1 as program stop function */ mDot08.disable_irq(); mDot08.fall(&sw1ISR); /* * 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 packet time change */ mDot09.disable_irq(); mDot09.fall(&sw2ISR); /* * need to call this function after rise or fall because rise/fall sets * mode to PullNone */ mDot09.mode(PullUp); mDot09.enable_irq(); /* * Setting other InterruptIn pins with Pull Ups */ mDot12.mode(PullUp); mDot15.mode(PullUp); mDot16.mode(PullUp); 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); printf("\r\n setup mdot\r\n"); // get a mDot handle mdot_radio = mDot::getInstance(); if (mdot_radio) { mdot_mutex.lock(); // lock mdot before setting configuration // reset to default config so we know what state we're in mdot_radio->resetConfig(); // Setting up LED1 as activity LED mdot_radio->setActivityLedPin(PB_0); mdot_radio->setActivityLedEnable(true); // Read node ID and frequency band mdot_EUI = mdot_radio->getDeviceId(); mdot_freq = mdot_radio->getFrequencyBand(); printf("mDot EUI = "); for (i=0; i<mdot_EUI.size(); i++) { printf("%02x ", mdot_EUI[i]); } printf("\r\n"); sprintf(txtstr,"MTDOT EVB"); printf("mDot Frequency = "); if (mdot_freq == mDot::FB_868) { printf( "868 MHz\r\n"); sprintf(txtstr,"%s 868 MHz",txtstr); } else { printf("915 MHz\r\n"); sprintf(txtstr,"%s 915 MHz",txtstr); } evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr)); sprintf(txtstr,"Sensor Demo"); evbLCD->writeText(24,4,font_6x8,txtstr,strlen(txtstr)); evbLCD->endUpdate(); // Setting up the mDot with network information. /* * This call sets up private or public mode on the MTDOT. Set the function to true if * connecting to a public network */ printf("setting Private Network Mode\r\n"); if ((mdot_ret = mdot_radio->setPublicNetwork(false)) != mDot::MDOT_OK) { log_error(mdot_radio, "failed to set Public Network Mode", mdot_ret); } /* * Frequency sub-band is valid for NAM only and for Private networks should be set to a value * between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only. * This function can be commented out for EU networks */ if (mdot_freq == mDot::FB_915) { printf("setting frequency sub band\r\n"); if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) { log_error(mdot_radio, "failed to set frequency sub band", mdot_ret); } } /* * setNetworkName is used for private networks. * Use setNetworkID(AppID) for public networks */ // config_app_id.assign(app_id,app_id+7); 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); } /* * 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_9 */ printf("setting TX data rate to SF_7\r\n"); if ((mdot_ret = mdot_radio->setTxDataRate(sf_val)) != mDot::MDOT_OK) { log_error(mdot_radio, "failed to set TX data rate", mdot_ret); } mdot_mutex.unlock(); // unlock mdot mutex before join attempt so SW1 can work // attempt to join the network printf("joining network\r\n"); do { mdot_mutex.lock(); // lock mdot mutex before join attempt mdot_ret = mdot_radio->joinNetwork(); mdot_mutex.unlock(); // unlock mdot mutex after join attempt so SW1 can work if (mdot_ret != mDot::MDOT_OK) { log_error(mdot_radio,"failed to join network:", mdot_ret); if (toggle_text) sprintf(txtstr," > Join Failed <"); else sprintf(txtstr," < Join Failed >"); evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); if (mdot_radio->getFrequencyBand() == mDot::FB_868) { join_delay = mdot_radio->getNextTxMs(); } else { join_delay = 10; } printf("delay = %lu\r\n",join_delay); osDelay(join_delay + 1); toggle_text = !toggle_text; } /* * Setting TX power and Data Rate for radio just in case user requested by SW2 */ mdot_mutex.lock(); // lock mdot mutex before setting change mdot_radio->setTxPower(pwr_val); mdot_radio->setTxDataRate(sf_val); mdot_mutex.unlock(); // unlock mdot mutex after settings change } while (mdot_ret != mDot::MDOT_OK); sprintf(txtstr,"*Network Joined*"); evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); } else { sprintf(txtstr,"Radio Init Failed!"); evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); printf("%s\r\n",txtstr); exit(1); } 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); printf("Start of Test\r\n"); osDelay (500); // allows other threads to process printf("shutdown LED:\r\n"); evbBackLight->shutdown(); osDelay (500); // allows other threads to process printf("Turn on LED2\r\n"); evbBackLight->setLEDCurrent(16); data = evbAccel->getWhoAmI(); printf("Accelerometer who_am_i value = %x \r\n", data); result = evbAccel->getStatus(); printf("status byte = %x \r\n", result); printf("Barometer who_am_i check = %s \r\n", evbBaro->testWhoAmI() ? "TRUE" : "FALSE"); result = evbBaro->getStatus(); printf("status byte = %x \r\n", result); /* * Setup the Accelerometer for 8g range, 14 bit resolution, Noise reduction off, sample rate 1.56 Hz * normal oversample mode, High pass filter off */ evbAccel->setCommonParameters(MMA845x::RANGE_8g,MMA845x::RES_MAX,MMA845x::LN_OFF, MMA845x::DR_1_56,MMA845x::OS_NORMAL,MMA845x::HPF_OFF ); /* * Setup the Barometric sensor for post processed Ambient pressure, 4 samples per data acquisition. * and a sample taken every second when in active mode */ evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1); /* * Setup the Ambient Light Sensor for continuous Ambient Light Sensing, 16 bit resolution, * and 16000 lux range */ evbAmbLight->setMode(ISL29011::ALS_CONT); evbAmbLight->setResolution(ISL29011::ADC_16BIT); evbAmbLight->setRange(ISL29011::RNG_16000); /* * Set the accelerometer for active mode */ evbAccel->activeMode(); /* * Clear the min-max registers in the Barometric Sensor */ evbBaro->clearMinMaxRegs(); evbBackLight->setLEDCurrent(0); /* * Main data acquisition loop */ i = 0; do { evbLCD->startUpdate(); // clear LCD line 0-6 only sprintf(txtstr, " "); for (j=0; j<6; j++) evbLCD->writeText(0,j,font_6x8,txtstr,strlen(txtstr)); /* * Test Accelerometer XYZ data ready bit to see if acquisition complete */ do { osDelay(100); // allows other threads to process result = evbAccel->getStatus(); } while ((result & MMA845x::XYZDR) == 0 ); /* * Retrieve and print out accelerometer data */ accel_data = evbAccel->getXYZ(); sprintf(txtstr, "Accel: x = %d", accel_data._x); evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr)); sprintf(txtstr, "y = %d", accel_data._y); evbLCD->writeText(42,1,font_6x8,txtstr,strlen(txtstr)); sprintf(txtstr, "z = %d", accel_data._z ); evbLCD->writeText(42,2,font_6x8,txtstr,strlen(txtstr)); /* * Trigger a Pressure reading */ evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1); evbBaro->triggerOneShot(); /* * Test barometer device status to see if acquisition is complete */ do { osDelay(100); // allows other threads to process result = evbBaro->getStatus(); } while ((result & MPL3115A2::PTDR) == 0 ); /* * Retrieve and print out barometric pressure */ pressure = evbBaro->getBaroData() >> 12; // convert 32 bit signed to 20 bit unsigned value num_whole = pressure >> 2; // 18 bit integer significant num_frac = (pressure & 0x3) * 25; // 2 bit fractional 0.25 per bit sprintf(txtstr,"Press=%ld.%02d Pa", num_whole, num_frac); evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr)); /* * Trigger a Altitude reading */ evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_ALTIMETER, MPL3115A2::OR_16, MPL3115A2::AT_1); evbBaro->triggerOneShot(); /* * Test barometer device status to see if acquisition is complete */ do { osDelay(100); // allows other threads to process result = evbBaro->getStatus(); } while ((result & MPL3115A2::PTDR) == 0 ); /* * Retrieve and print out altitude and temperature */ baro_data = evbBaro->getAllData(false); baro_data._baro /= 4096; // convert 32 bit signed to 20 bit signed value num_whole = baro_data._baro / 16; // 18 bit signed significant integer num_frac = (baro_data._baro & 0xF) * 625 / 100; // 4 bit fractional .0625 per bit sprintf(txtstr,"Alti=%ld.%02d m", num_whole, num_frac); evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); num_whole = baro_data._temp / 16; // 8 bit signed significant integer num_frac = (baro_data._temp & 0x0F) * 625 / 100; // 4 bit fractional .0625 per bit sprintf(txtstr,"Temp=%ld.%03d C", num_whole, num_frac); evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); /* * retrieve and print out Ambient Light level */ lux_data = evbAmbLight->getData(); num_whole = lux_data * 24 / 100; // 16000 lux full scale .24 lux per bit num_frac = lux_data * 24 % 100; sprintf(txtstr, "Light=%ld.%02d lux", num_whole, num_frac ); evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr)); evbLCD->endUpdate(); printf("finished iteration %d\r\n",(++i)); /* Transmit data packet based on pckt_time setting and result of * mdot_radio->getNextTxMs() function and mutex available. The getNextTxMs() * function returns the number of millisecond before another packet can be * sent in 868 MHz band. This can vary depending on wther the 10%, 1% or 0.1% * channel is used and the time on air for a specific setup of the radio */ if ((xmit_delay <= i) && (mdot_radio->getNextTxMs() == 0) && (mdot_mutex.trylock())) { /* * Setting TX power and Data Rate for radio just in case user requested by SW2 */ mdot_radio->setTxPower(pwr_val); mdot_radio->setTxDataRate(sf_val); mdot_data.clear(); mdot_data.push_back(0x1D); // key for start of data mdot_data.push_back(0x0E); // key for Current Acceleration 3-Axis Value converts.f_s = accel_data._x *4; // shift data 2 bits while retaining sign mdot_data.push_back(converts.t_u[1]); // get 8 MSB of 14 bit value converts.f_s = accel_data._y * 4; // shift data 2 bits while retaining sign mdot_data.push_back(converts.t_u[1]); // get 8 MSB of 14 bit value converts.f_s = accel_data._z * 4; // shift data 2 bits while retaining sign mdot_data.push_back(converts.t_u[1]); // get 8 MSB of 14 bit value mdot_data.push_back(0x08); // key for Current Pressure Value convertl.f_u = pressure; // pressure data is 20 bits unsigned mdot_data.push_back(convertl.t_u[2]); mdot_data.push_back(convertl.t_u[1]); mdot_data.push_back(convertl.t_u[0]); /* for 915 MHz band and SF_10 max packet size is 11 bytes. * so the payload gets split in two packets here. */ if ((mdot_freq == mDot::FB_915) && (sf_val == mDot::SF_10)) { mdot_ret = mdot_radio->send(mdot_data); if ( mdot_ret != mDot::MDOT_OK) { sprintf(txtstr,"mDot Send failed"); evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); log_error(mdot_radio, txtstr, mdot_ret); continue; } else { printf("successfully sent packet 1 to gateway\r\n"); } mdot_data.clear(); // clear data for next "chunk" } mdot_data.push_back(0x05); // key for Current Ambient Light Value converts.f_u = lux_data; // data is 16 bits unsigned mdot_data.push_back(converts.t_u[1]); mdot_data.push_back(converts.t_u[0]); mdot_data.push_back(0x0B); // key for Current Temperature Value converts.f_s = baro_data._temp; // temperature is signed 12 bit mdot_data.push_back(converts.t_u[1]); mdot_data.push_back(converts.t_u[0]); mdot_data.push_back(0x1D); // key for end of data mdot_ret = mdot_radio->send(mdot_data); if (mdot_ret != mDot::MDOT_OK) { log_error(mdot_radio, "failed to send", mdot_ret); sprintf(txtstr,"PKT Send Failed"); evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); } else { sprintf(txtstr,"SENT DR=%2d Pwr=%2d",(12 - sf_val),pwr_val); evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); printf("%s \r\n",txtstr); } mdot_mutex.unlock(); // unlock mutex after all data transmitted xmit_delay = i + pckt_time; if (mdot_freq == mDot::FB_868) printf("Next transmit time = %d milliseconds \r\n",mdot_radio->getNextTxMs()); } else { sprintf(txtstr," DR=%2d Pwr=%2d ",(12 - sf_val),pwr_val); evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); } } while(i < 65000); evbBaro->triggerOneShot(); do { osDelay(200); // allows other threads to process result = evbBaro->getStatus(); } while ((result & MPL3115A2::PTDR) == 0 ); baro_data = evbBaro->getAllData(true); printf ("minBaro=%ld maxBaro=%ld minTemp=%d maxTemp=%d\r\n", baro_data._minbaro, baro_data._maxbaro, baro_data._mintemp, baro_data._maxtemp); printf("End of Test\r\n"); evbLCD->clearBuffer(); sprintf(txtstr,"Exiting Program"); evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); } /* * Sets sw1_low flag. Slag is cleared in sw1_debounce thread */ void sw1ISR(void) { if (!sw1_low) sw1_low = true; } /* * Debounces sw1 changes spreading factor and output power * Cycles through SF_7-SF_9 for 4 power levels for 915 MHz band * Cycles through SF_7-SF_12 for 4 power levels for 868 MHz band */ void sw1_debounce(void const *args) { static uint8_t count = 0; static uint8_t test_sf = 0; static uint8_t test_pwr = 0; while (true) { if (sw1_low && (mDot08 == 0)) count++; else { count = 0; sw1_low = false; } if (count == 5) { test_sf++; if (((test_sf > 3) && (mdot_freq == mDot::FB_915)) || ((test_sf > 5) && (mdot_freq == mDot::FB_868))) { test_sf = 0; test_pwr ++; if (test_pwr > 3) test_pwr = 0; } // selects power output level using upper bits for select switch(test_pwr) { case 0: pwr_val = 11; break; case 1: pwr_val = 14; break; case 2: pwr_val = 18; break; case 3: pwr_val = 20; } // sets data rate based on lower bits sf_val = mDot::SF_7 - (test_sf & 0x07); sprintf(txtstr," DR=%2d Pwr=%2d ",(12 - sf_val),pwr_val); evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); printf("%s \r\n",txtstr); } Thread::wait(5); } } /* * Sets sw2_low flag. Flag is cleared in sw2_debounce thread */ void sw2ISR(void) { if (!sw2_low) sw2_low = true; } /* * Debounces sw2. Changes packet transmit time to every 2nd, * 4th, 8th, or 16th sample when SW2 pushed. For 868 MHz mode * the time for next packet value is also tested. * Also triggers a thread to transmit a configuration packet */ void sw2_debounce(void const *args) { static uint8_t count = 0; while (true) { if (sw2_low && (mDot09 == 0)) count++; else { count = 0; sw2_low = false; } if (count == 5) { if (pckt_time >= 4) pckt_time /= 2; else pckt_time = 16; thread_3->signal_set(0x10); // signal config_pkt_xmit to send packet } Thread::wait(5); } } /* * Function that prints 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()); } /* * Thread that is triggered by SW2 ISR. Sends a packet to the LoRa server with the new Packet Transmission time setting */ void config_pkt_xmit (void const *args) { std::vector<uint8_t> data; uint16_t wait_time; while (true) { Thread::signal_wait(0x10); // wait for sw2ISR to signal send data.clear(); data.push_back(0x0F); // key for Configuration data (packet transmission timer) data.push_back(pckt_time); mdot_mutex.lock(); // lock mdot mutex before packet send if ((wait_time = mdot_radio->getNextTxMs()) > 0) // wait for next xmit time osDelay(wait_time); if ((mdot_ret = mdot_radio->send(data)) != mDot::MDOT_OK) { log_error(mdot_radio, "failed to send config data", mdot_ret); } else { printf("sent config data to gateway\r\n"); } mdot_mutex.unlock(); // unlock mdot mutex after packet send } }