Factory firmware for the MultiTech Dotbox (MTDOT-BOX) and EVB (MTDOT-EVB) products.

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* Copyright (c) <2016> <MultiTech Systems>, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction, 
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or 
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 
00019 // mbed headers
00020 #include "mbed.h"
00021 #include "rtos.h"
00022 // MTS headers
00023 #include "mDot.h"
00024 #include "MTSLog.h"
00025 // display headers
00026 #include "DOGS102.h"
00027 #include "NCP5623B.h"
00028 #include "LayoutStartup.h"
00029 #include "LayoutScrollSelect.h"
00030 #include "LayoutConfig.h"
00031 #include "LayoutHelp.h"
00032 // button header
00033 #include "ButtonHandler.h"
00034 // LoRa header
00035 #include "LoRaHandler.h"
00036 // Sensor header
00037 #include "SensorHandler.h"
00038 // mode objects
00039 #include "ModeJoin.h"
00040 #include "ModeSingle.h"
00041 #include "ModeSweep.h"
00042 #include "ModeDemo.h"
00043 #include "ModeConfig.h"
00044 #include "ModeGps.h"
00045 #include "ModeData.h"
00046 #include "ModeRegion.h"
00047 // misc heders
00048 #include "FileName.h"
00049 #include <string>
00050 
00051 #ifndef CHANNEL_PLAN
00052 #define CHANNEL_PLAN  CP_US915
00053 #endif
00054 
00055 #define DISABLE_DUTY_CYCLE true
00056 
00057 // LCD and LED controllers
00058 SPI lcd_spi(SPI1_MOSI, SPI1_MISO, SPI1_SCK);
00059 DigitalOut lcd_spi_cs(SPI1_CS, 1);
00060 DigitalOut lcd_cd(XBEE_ON_SLEEP, 1);
00061 DOGS102* lcd;
00062 
00063 I2C i2c(I2C_SDA, I2C_SCL);
00064 static const int i2c_freq = 400000;  // i2c bus frequency in Hz
00065 
00066 NCP5623B* led_cont;
00067 
00068 // Thread informaiton
00069 osThreadId main_id;
00070 
00071 // Button controller
00072 ButtonHandler* buttons;
00073 
00074 // LoRa controller
00075 LoRaHandler* lora_handler;
00076 
00077 lora::ChannelPlan* plan;
00078 mDot* dot;
00079 
00080 // GPS
00081 GPSPARSER* gps;
00082 MTSSerial  gps_serial(XBEE_DOUT, XBEE_DIN, 256, 2048);
00083 
00084 // Sensors
00085 SensorHandler* sensors;
00086 
00087 // Modes
00088 ModeJoin* modeJoin;
00089 ModeSingle* modeSingle;
00090 ModeSweep* modeSweep;
00091 ModeDemo* modeDemo;
00092 ModeConfig* modeConfig;
00093 ModeGps* modeGps;
00094 ModeData* modeData;
00095 ModeRegion* modeRegion;
00096 
00097 // Serial debug port
00098 Serial debug_port(USBTX, USBRX);
00099 
00100 // Survey Data File
00101 char file_name[] = "SurveyData.txt";
00102 
00103 // Channel plan file
00104 char file_cp[] = "ChannelPlan";
00105 
00106 // Prototypes
00107 void mainMenu();
00108 
00109 int main() {
00110     debug_port.baud(115200);
00111 
00112     i2c.frequency(i2c_freq);
00113 
00114     lcd = new DOGS102(lcd_spi, lcd_spi_cs, lcd_cd);
00115     // NCP5623B::LEDs 1 & 2 are the screen backlight - not used on default build
00116     // NCP5623B::LED3 is EVB LED2
00117     led_cont = new NCP5623B(i2c);
00118     gps = new GPSPARSER(&gps_serial, led_cont);
00119     sensors = new SensorHandler(i2c);
00120 
00121     main_id = Thread::gettid();
00122     buttons = new ButtonHandler(main_id);
00123     MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
00124 
00125     logDebug("Loading default plan");
00126 
00127 #if CHANNEL_PLAN == CP_AS923
00128     plan = new lora::ChannelPlan_AS923();
00129 #elif CHANNEL_PLAN == CP_US915
00130     plan = new lora::ChannelPlan_US915();
00131 #elif CHANNEL_PLAN == CP_AU915
00132     plan = new lora::ChannelPlan_AU915();
00133 #elif CHANNEL_PLAN == CP_EU868
00134     plan = new lora::ChannelPlan_EU868();
00135 #elif CHANNEL_PLAN == CP_KR920
00136     plan = new lora::ChannelPlan_KR920();
00137 #elif CHANNEL_PLAN == CP_IN865
00138     plan = new lora::ChannelPlan_IN865();
00139 #elif CHANNEL_PLAN == CP_AS923_JAPAN
00140     plan = new lora::ChannelPlan_AS923_Japan();
00141 #endif
00142     mDot* dot = mDot::getInstance(plan);
00143 
00144     uint8_t cplan[] = { 0 };
00145     mDot::mdot_file file;   
00146     vector<mDot::mdot_file> files = dot->listUserFiles();
00147 
00148     for (vector<mDot::mdot_file>::iterator it = files.begin(); it != files.end(); it++) {
00149         if (strcmp(file_cp,it->name)==0) {
00150             file = dot->openUserFile(it->name, mDot::FM_RDWR);
00151             dot->seekUserFile(file, 0, SEEK_SET);
00152             dot->readUserFile(file, cplan, 1); 
00153             dot->closeUserFile(file);
00154         }
00155     }
00156 
00157     if(cplan[0]) {
00158         if(cplan[0] != CHANNEL_PLAN){
00159             logDebug("Loading saved channel plan");
00160             switch (cplan[0]){
00161                 case CP_AS923:
00162                     delete plan;  
00163                     plan = new lora::ChannelPlan_AS923();
00164                     break;
00165 
00166                 case CP_US915:
00167                     delete plan;
00168                     plan = new lora::ChannelPlan_US915();
00169                     break;
00170 
00171                 case CP_AU915:
00172                     delete plan;
00173                     plan = new lora::ChannelPlan_AU915();
00174                     break;
00175 
00176                 case CP_EU868:
00177                     delete plan;
00178                     plan = new lora::ChannelPlan_EU868();
00179                     break;
00180 
00181                 case CP_KR920:
00182                     delete plan;
00183                     plan = new lora::ChannelPlan_KR920();
00184                     break;
00185 
00186                 case CP_AS923_JAPAN:
00187                     delete plan;
00188                     plan = new lora::ChannelPlan_AS923_Japan();
00189                     break;
00190 
00191                 case CP_IN865:
00192                     delete plan;
00193                     plan = new lora::ChannelPlan_IN865();
00194                     break;
00195 
00196                 default:
00197                     logInfo("Saved channel plan not valid Defaulting US915");
00198                     delete plan;
00199                     plan = new lora::ChannelPlan_US915();
00200                     break;
00201             }
00202             dot->setChannelPlan(plan);   
00203         }
00204     } 
00205     lora_handler = new LoRaHandler(main_id, dot);
00206 
00207     dot->setDisableDutyCycle(DISABLE_DUTY_CYCLE);
00208     dot->setLinkCheckThreshold(0);
00209     dot->setLinkCheckCount(0);
00210     //Adr off to make sure modes work, auto sleep off seems to cause issues, haven't looked into it yet
00211     dot->setAdr(false);
00212     dot->setLogLevel(MTSLog::DEBUG_LEVEL);
00213     dot->setAutoSleep(false); 
00214     // Seed the RNG
00215     srand(dot->getRadioRandom());
00216 
00217     led_cont->setLEDCurrent(16);
00218 
00219     modeJoin = new ModeJoin(lcd, buttons, dot, lora_handler, gps, sensors);
00220     modeSingle = new ModeSingle(lcd, buttons, dot, lora_handler, gps, sensors);
00221     modeSweep = new ModeSweep(lcd, buttons, dot, lora_handler, gps, sensors);
00222     modeDemo = new ModeDemo(lcd, buttons, dot, lora_handler, gps, sensors);
00223     modeConfig = new ModeConfig(lcd, buttons, dot, lora_handler, gps, sensors);
00224     modeGps = new ModeGps(lcd, buttons, dot, lora_handler, gps, sensors, modeJoin);
00225     modeData = new ModeData(lcd, buttons, dot, lora_handler, gps, sensors);
00226     modeRegion = new ModeRegion(lcd, buttons, dot, lora_handler, gps, sensors, file_cp);
00227 
00228     osDelay(1000);
00229     logInfo("%sGPS detected", gps->gpsDetected() ? "" : "no ");
00230 
00231     if(!cplan[0]) {
00232         dot->saveUserFile(file_cp, cplan, 1);    
00233         modeRegion->start();
00234     }
00235 
00236     // display startup screen for 3 seconds
00237     LayoutStartup ls(lcd, dot);
00238     ls.display();
00239     ls.updateGPS(gps->gpsDetected());
00240     osDelay(3000);
00241     logInfo("displaying main menu");
00242     mainMenu();
00243 
00244     return 0;
00245 }
00246 
00247 void mainMenu() {
00248     bool mode_selected = false;
00249     std::string selected;
00250     std::string product;
00251 
00252     typedef enum {
00253         demo = 1,
00254         config,
00255         single,
00256         sweep,
00257         gps,
00258         data,
00259         region
00260     } menu_items;
00261 
00262     std::string menu_strings[] = {
00263         "Select Mode",
00264         "LoRa Demo",
00265         "Configuration",
00266         "Survey Single",
00267         "Survey Sweep",
00268         "Survey GPS",
00269         "View Data",
00270         "Select Region"
00271     };
00272 
00273     std::vector<std::string> items;
00274     items.push_back(menu_strings[demo]);
00275     items.push_back(menu_strings[config]);
00276     items.push_back(menu_strings[single]);
00277     items.push_back(menu_strings[sweep]);
00278     items.push_back(menu_strings[gps]);
00279     items.push_back(menu_strings[data]);
00280     items.push_back(menu_strings[region]);
00281 
00282     while (true) {
00283         // reset session between modes
00284         dot->resetNetworkSession();
00285         selected = "";
00286         //dot->getChannelPlanName causes hard faults, not sure why.
00287         product = "DOT-BOX/EVB " + plan->GetPlanName();
00288         if(product.size() > 17)
00289             product = "DOT-BOX/EVB JAPAN";    
00290         LayoutScrollSelect menu(lcd, items, product, menu_strings[0]);
00291         menu.display();
00292 
00293         while (! mode_selected) {
00294             lora_handler->resetActivityLed();
00295             osEvent e = Thread::signal_wait(buttonSignal);
00296             if (e.status == osEventSignal) {
00297                 ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
00298                 switch (ev) {
00299                     case ButtonHandler::sw1_press:
00300                         selected = menu.select();
00301                         mode_selected = true;
00302                         break;
00303                     case ButtonHandler::sw2_press:
00304                         menu.scroll();
00305                         break;
00306                     case ButtonHandler::sw1_hold:
00307                         break;
00308                     default:
00309                         break;
00310                 }
00311             }
00312         }
00313         if (selected == menu_strings[demo]) {
00314             if (modeJoin->start())
00315                 modeDemo->start();
00316         } else if (selected == menu_strings[config]) {
00317             modeConfig->start();
00318         } else if (selected == menu_strings[single]) {
00319             if (modeJoin->start())
00320                 modeSingle->start();
00321         } else if (selected == menu_strings[sweep]) {
00322             if (modeJoin->start())
00323                 modeSweep->start();
00324         } else if (selected == menu_strings[gps]) {
00325             if (plan->IsPlanDynamic()) {
00326                 if(modeJoin->start())
00327                     modeGps->start();
00328             }
00329             else { 
00330                 modeGps->start();
00331             }
00332         } else if (selected == menu_strings[data]) {
00333             modeData->start();
00334         } else if (selected == menu_strings[region]) {
00335             modeRegion->start();
00336         }
00337         lora_handler->resetActivityLed();  
00338         mode_selected = false;
00339     }
00340 }