MTDOT-BOX-EVB-Factory-Firmware

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

main.cpp

Committer:
jenkins@jenkinsdm1
Date:
2019-03-14
Revision:
16:e76cec0eec43
Parent:
12:05435282f899

File content as of revision 16:e76cec0eec43:

/* Copyright (c) <2016> <MultiTech Systems>, MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
 * and associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

// mbed headers
#include "mbed.h"
#include "rtos.h"
// MTS headers
#include "mDot.h"
#include "MTSLog.h"
// display headers
#include "DOGS102.h"
#include "NCP5623B.h"
#include "LayoutStartup.h"
#include "LayoutScrollSelect.h"
#include "LayoutConfig.h"
#include "LayoutHelp.h"
// button header
#include "ButtonHandler.h"
// LoRa header
#include "LoRaHandler.h"
// Sensor header
#include "SensorHandler.h"
// mode objects
#include "ModeJoin.h"
#include "ModeSingle.h"
#include "ModeSweep.h"
#include "ModeDemo.h"
#include "ModeConfig.h"
#include "ModeGps.h"
#include "ModeData.h"
#include "ModeRegion.h"
// misc heders
#include "FileName.h"
#include <string>

#ifndef CHANNEL_PLAN
#define CHANNEL_PLAN  CP_US915
#endif

#define DISABLE_DUTY_CYCLE true

// LCD and LED controllers
SPI lcd_spi(SPI1_MOSI, SPI1_MISO, SPI1_SCK);
DigitalOut lcd_spi_cs(SPI1_CS, 1);
DigitalOut lcd_cd(XBEE_ON_SLEEP, 1);
DOGS102* lcd;

I2C i2c(I2C_SDA, I2C_SCL);
static const int i2c_freq = 400000;  // i2c bus frequency in Hz

NCP5623B* led_cont;

// Thread informaiton
osThreadId main_id;

// Button controller
ButtonHandler* buttons;

// LoRa controller
LoRaHandler* lora_handler;

lora::ChannelPlan* plan;
mDot* dot;

// GPS
GPSPARSER* gps;
MTSSerial  gps_serial(XBEE_DOUT, XBEE_DIN, 256, 2048);

// Sensors
SensorHandler* sensors;

// Modes
ModeJoin* modeJoin;
ModeSingle* modeSingle;
ModeSweep* modeSweep;
ModeDemo* modeDemo;
ModeConfig* modeConfig;
ModeGps* modeGps;
ModeData* modeData;
ModeRegion* modeRegion;

// Serial debug port
Serial debug_port(USBTX, USBRX);

// Survey Data File
char file_name[] = "SurveyData.txt";

// Channel plan file
char file_cp[] = "ChannelPlan";

// Prototypes
void mainMenu();

int main() {
    debug_port.baud(115200);

    i2c.frequency(i2c_freq);

    lcd = new DOGS102(lcd_spi, lcd_spi_cs, lcd_cd);
    // NCP5623B::LEDs 1 & 2 are the screen backlight - not used on default build
    // NCP5623B::LED3 is EVB LED2
    led_cont = new NCP5623B(i2c);
    gps = new GPSPARSER(&gps_serial, led_cont);
    sensors = new SensorHandler(i2c);

    main_id = Thread::gettid();
    buttons = new ButtonHandler(main_id);
    MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);

    logDebug("Loading default plan");

#if CHANNEL_PLAN == CP_AS923
    plan = new lora::ChannelPlan_AS923();
#elif CHANNEL_PLAN == CP_US915
    plan = new lora::ChannelPlan_US915();
#elif CHANNEL_PLAN == CP_AU915
    plan = new lora::ChannelPlan_AU915();
#elif CHANNEL_PLAN == CP_EU868
    plan = new lora::ChannelPlan_EU868();
#elif CHANNEL_PLAN == CP_KR920
    plan = new lora::ChannelPlan_KR920();
#elif CHANNEL_PLAN == CP_IN865
    plan = new lora::ChannelPlan_IN865();
#elif CHANNEL_PLAN == CP_AS923_JAPAN
    plan = new lora::ChannelPlan_AS923_Japan();
#endif
    mDot* dot = mDot::getInstance(plan);

    uint8_t cplan[] = { 0 };
    mDot::mdot_file file;	
    vector<mDot::mdot_file> files = dot->listUserFiles();

    for (vector<mDot::mdot_file>::iterator it = files.begin(); it != files.end(); it++) {
        if (strcmp(file_cp,it->name)==0) {
            file = dot->openUserFile(it->name, mDot::FM_RDWR);
            dot->seekUserFile(file, 0, SEEK_SET);
            dot->readUserFile(file, cplan, 1); 
            dot->closeUserFile(file);
        }
    }

    if(cplan[0]) {
        if(cplan[0] != CHANNEL_PLAN){
            logDebug("Loading saved channel plan");
            switch (cplan[0]){
                case CP_AS923:
                    delete plan;  
                    plan = new lora::ChannelPlan_AS923();
                    break;

                case CP_US915:
                    delete plan;
                    plan = new lora::ChannelPlan_US915();
                    break;

                case CP_AU915:
                    delete plan;
                    plan = new lora::ChannelPlan_AU915();
                    break;

                case CP_EU868:
                    delete plan;
                    plan = new lora::ChannelPlan_EU868();
                    break;

                case CP_KR920:
                    delete plan;
                    plan = new lora::ChannelPlan_KR920();
                    break;

                case CP_AS923_JAPAN:
                    delete plan;
                    plan = new lora::ChannelPlan_AS923_Japan();
                    break;

                case CP_IN865:
                    delete plan;
                    plan = new lora::ChannelPlan_IN865();
                    break;

                default:
                    logInfo("Saved channel plan not valid Defaulting US915");
                    delete plan;
                    plan = new lora::ChannelPlan_US915();
                    break;
            }
            dot->setChannelPlan(plan);   
        }
    } 
    lora_handler = new LoRaHandler(main_id, dot);

    dot->setDisableDutyCycle(DISABLE_DUTY_CYCLE);
    dot->setLinkCheckThreshold(0);
    dot->setLinkCheckCount(0);
    //Adr off to make sure modes work, auto sleep off seems to cause issues, haven't looked into it yet
    dot->setAdr(false);
    dot->setLogLevel(MTSLog::DEBUG_LEVEL);
    dot->setAutoSleep(false); 
    // Seed the RNG
    srand(dot->getRadioRandom());

    led_cont->setLEDCurrent(16);

    modeJoin = new ModeJoin(lcd, buttons, dot, lora_handler, gps, sensors);
    modeSingle = new ModeSingle(lcd, buttons, dot, lora_handler, gps, sensors);
    modeSweep = new ModeSweep(lcd, buttons, dot, lora_handler, gps, sensors);
    modeDemo = new ModeDemo(lcd, buttons, dot, lora_handler, gps, sensors);
    modeConfig = new ModeConfig(lcd, buttons, dot, lora_handler, gps, sensors);
    modeGps = new ModeGps(lcd, buttons, dot, lora_handler, gps, sensors, modeJoin);
    modeData = new ModeData(lcd, buttons, dot, lora_handler, gps, sensors);
    modeRegion = new ModeRegion(lcd, buttons, dot, lora_handler, gps, sensors, file_cp);

    osDelay(1000);
    logInfo("%sGPS detected", gps->gpsDetected() ? "" : "no ");

    if(!cplan[0]) {
        dot->saveUserFile(file_cp, cplan, 1);    
        modeRegion->start();
    }

    // display startup screen for 3 seconds
    LayoutStartup ls(lcd, dot);
    ls.display();
    ls.updateGPS(gps->gpsDetected());
    osDelay(3000);
    logInfo("displaying main menu");
    mainMenu();

    return 0;
}

void mainMenu() {
    bool mode_selected = false;
    std::string selected;
    std::string product;

    typedef enum {
        demo = 1,
        config,
        single,
        sweep,
        gps,
        data,
        region
    } menu_items;

    std::string menu_strings[] = {
        "Select Mode",
        "LoRa Demo",
        "Configuration",
        "Survey Single",
        "Survey Sweep",
        "Survey GPS",
        "View Data",
        "Select Region"
    };

    std::vector<std::string> items;
    items.push_back(menu_strings[demo]);
    items.push_back(menu_strings[config]);
    items.push_back(menu_strings[single]);
    items.push_back(menu_strings[sweep]);
    items.push_back(menu_strings[gps]);
    items.push_back(menu_strings[data]);
    items.push_back(menu_strings[region]);

    while (true) {
        // reset session between modes
        dot->resetNetworkSession();
        selected = "";
        //dot->getChannelPlanName causes hard faults, not sure why.
        product = "DOT-BOX/EVB " + plan->GetPlanName();
        if(product.size() > 17)
            product = "DOT-BOX/EVB JAPAN";    
        LayoutScrollSelect menu(lcd, items, product, menu_strings[0]);
        menu.display();

        while (! mode_selected) {
            lora_handler->resetActivityLed();
            osEvent e = Thread::signal_wait(buttonSignal);
            if (e.status == osEventSignal) {
                ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
                switch (ev) {
                    case ButtonHandler::sw1_press:
                        selected = menu.select();
                        mode_selected = true;
                        break;
                    case ButtonHandler::sw2_press:
                        menu.scroll();
                        break;
                    case ButtonHandler::sw1_hold:
                        break;
                    default:
                        break;
                }
            }
        }
        if (selected == menu_strings[demo]) {
            if (modeJoin->start())
                modeDemo->start();
        } else if (selected == menu_strings[config]) {
            modeConfig->start();
        } else if (selected == menu_strings[single]) {
            if (modeJoin->start())
                modeSingle->start();
        } else if (selected == menu_strings[sweep]) {
            if (modeJoin->start())
                modeSweep->start();
        } else if (selected == menu_strings[gps]) {
            if (plan->IsPlanDynamic()) {
                if(modeJoin->start())
                    modeGps->start();
            }
            else { 
                modeGps->start();
            }
        } else if (selected == menu_strings[data]) {
            modeData->start();
        } else if (selected == menu_strings[region]) {
            modeRegion->start();
        }
        lora_handler->resetActivityLed();  
        mode_selected = false;
    }
}