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

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

MTDOT-BOX/EVB Firmware Description

This Firmware is what ships on DotBox and EVB devices. It is intended to be used as a proof of concept and site survey tool for planning LoRa deployments. The firmware provides a number of different modes of operation:

  • Configuration - Use AT commands to configure network credentials, TX power, TX data rate, view the survey data file, etc.
  • Survey Single - Test network connectivity at current location at a specific TX power and TX data rate. Uplink information, downlink information, and GPS information are saved to the survey data file and can also be sent to the gateway.
  • Survey Sweep - Test network connectivity at current location across a range of TX powers and TX data rates. Uplink information, downlink information, and GPS information for each survey in the sweep are saved to the survey data file and can also be sent to the gateway.
  • LoRa Demo - Gather data from onboard sensors and display it on the screen in real time. Send packets containing sensor data to the gateway either on an interval or when triggered by the user. GPS data is not transmitted.
  • Survey GPS - Gather sensor and GPS data and transmit it to the gateway either on an interval or when triggered by the user. Add padding to packets, switch frequency sub bands, TX power, TX data rate, and more all without exiting Survey GPS Mode.
  • View Data - View the survey data file on the screen one survey at a time.

Additional documentation and information for the MTDOT-BOX/EVB Factory Firmware can be found here.


Dot Libraries

Dot Library Limitations

The commit messages in libmDot-mbed5 and libmDot-dev-mbed5 specify the version of the Dot library the commit contains and the version of mbed-os it was compiled against. We recommend building your application with the version of mbed-os specified in the commit message of the version of the Dot library you're using. This will ensure that you don't run into any runtime issues caused by differences in the mbed-os versions.

Development library for mDot.

[Repository '/teams/MultiTech/code/libmDot-dev-mbed5/' not found]

Stable library for mDot.

Import librarylibmDot-mbed5

Stable version of the mDot library for mbed 5. This version of the library is suitable for deployment scenarios. See lastest commit message for version of mbed-os library that has been tested against.

Committer:
jenkins@jenkinsdm1
Date:
Thu Mar 14 08:23:20 2019 -0500
Revision:
16:e76cec0eec43
Parent:
13:20bdea8bb997
dotbox-firmware revision 3.1.2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jenkins@jenkinsdm1 13:20bdea8bb997 1 /* Copyright (c) <2018> <MultiTech Systems>, MIT License
jenkins@jenkinsdm1 13:20bdea8bb997 2 *
jenkins@jenkinsdm1 13:20bdea8bb997 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
jenkins@jenkinsdm1 13:20bdea8bb997 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
jenkins@jenkinsdm1 13:20bdea8bb997 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
jenkins@jenkinsdm1 13:20bdea8bb997 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
jenkins@jenkinsdm1 13:20bdea8bb997 7 * furnished to do so, subject to the following conditions:
jenkins@jenkinsdm1 13:20bdea8bb997 8 *
jenkins@jenkinsdm1 13:20bdea8bb997 9 * The above copyright notice and this permission notice shall be included in all copies or
jenkins@jenkinsdm1 13:20bdea8bb997 10 * substantial portions of the Software.
jenkins@jenkinsdm1 13:20bdea8bb997 11 *
jenkins@jenkinsdm1 13:20bdea8bb997 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
jenkins@jenkinsdm1 13:20bdea8bb997 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
jenkins@jenkinsdm1 13:20bdea8bb997 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
jenkins@jenkinsdm1 13:20bdea8bb997 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jenkins@jenkinsdm1 13:20bdea8bb997 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
jenkins@jenkinsdm1 13:20bdea8bb997 17 */
jenkins@jenkinsdm1 13:20bdea8bb997 18
jenkins@jenkinsdm1 13:20bdea8bb997 19 #include "ChannelPlans.h"
jenkins@jenkinsdm1 13:20bdea8bb997 20 #include "ModeRegion.h"
jenkins@jenkinsdm1 13:20bdea8bb997 21 #include "MTSLog.h"
jenkins@jenkinsdm1 13:20bdea8bb997 22
jenkins@jenkinsdm1 13:20bdea8bb997 23 ModeRegion::ModeRegion(
jenkins@jenkinsdm1 13:20bdea8bb997 24 DOGS102* lcd,
jenkins@jenkinsdm1 13:20bdea8bb997 25 ButtonHandler* buttons,
jenkins@jenkinsdm1 13:20bdea8bb997 26 mDot* dot,
jenkins@jenkinsdm1 13:20bdea8bb997 27 LoRaHandler* lora,
jenkins@jenkinsdm1 13:20bdea8bb997 28 GPSPARSER* gps,
jenkins@jenkinsdm1 13:20bdea8bb997 29 SensorHandler* sensors,
jenkins@jenkinsdm1 13:20bdea8bb997 30 const char* file_cp)
jenkins@jenkinsdm1 13:20bdea8bb997 31 : Mode(lcd, buttons, dot, lora, gps, sensors)
jenkins@jenkinsdm1 13:20bdea8bb997 32 , _file_cp(file_cp)
jenkins@jenkinsdm1 13:20bdea8bb997 33 {
jenkins@jenkinsdm1 13:20bdea8bb997 34 // Add all of our supported regions
jenkins@jenkinsdm1 13:20bdea8bb997 35 _regions.push_back("US915");
jenkins@jenkinsdm1 13:20bdea8bb997 36 _regions.push_back("AU915");
jenkins@jenkinsdm1 13:20bdea8bb997 37 _regions.push_back("EU868");
jenkins@jenkinsdm1 13:20bdea8bb997 38 _regions.push_back("AS923");
jenkins@jenkinsdm1 13:20bdea8bb997 39 _regions.push_back("AS923-JAPAN");
jenkins@jenkinsdm1 13:20bdea8bb997 40 _regions.push_back("KR920");
jenkins@jenkinsdm1 13:20bdea8bb997 41 _regions.push_back("IN865");
jenkins@jenkinsdm1 13:20bdea8bb997 42
jenkins@jenkinsdm1 13:20bdea8bb997 43 _menu = new LayoutScrollSelect(lcd, _regions, "Select Region");
jenkins@jenkinsdm1 13:20bdea8bb997 44 }
jenkins@jenkinsdm1 13:20bdea8bb997 45
jenkins@jenkinsdm1 13:20bdea8bb997 46 ModeRegion::~ModeRegion()
jenkins@jenkinsdm1 13:20bdea8bb997 47 {
jenkins@jenkinsdm1 13:20bdea8bb997 48 delete _menu;
jenkins@jenkinsdm1 13:20bdea8bb997 49 }
jenkins@jenkinsdm1 13:20bdea8bb997 50
jenkins@jenkinsdm1 13:20bdea8bb997 51 bool ModeRegion::start()
jenkins@jenkinsdm1 13:20bdea8bb997 52 {
jenkins@jenkinsdm1 13:20bdea8bb997 53 std::string region("");
jenkins@jenkinsdm1 13:20bdea8bb997 54
jenkins@jenkinsdm1 13:20bdea8bb997 55 // clear any stale signals
jenkins@jenkinsdm1 13:20bdea8bb997 56 osSignalClear(_main_id, buttonSignal | loraSignal);
jenkins@jenkinsdm1 13:20bdea8bb997 57
jenkins@jenkinsdm1 13:20bdea8bb997 58 _menu->display();
jenkins@jenkinsdm1 13:20bdea8bb997 59
jenkins@jenkinsdm1 13:20bdea8bb997 60 while (true) {
jenkins@jenkinsdm1 13:20bdea8bb997 61 osEvent e = Thread::signal_wait(0, 250);
jenkins@jenkinsdm1 13:20bdea8bb997 62 if (e.status == osEventSignal) {
jenkins@jenkinsdm1 13:20bdea8bb997 63 if (e.value.signals & buttonSignal) {
jenkins@jenkinsdm1 13:20bdea8bb997 64 _be = _buttons->getButtonEvent();
jenkins@jenkinsdm1 13:20bdea8bb997 65
jenkins@jenkinsdm1 13:20bdea8bb997 66 switch (_be) {
jenkins@jenkinsdm1 13:20bdea8bb997 67 case ButtonHandler::sw1_press:
jenkins@jenkinsdm1 13:20bdea8bb997 68 region = _menu->select();
jenkins@jenkinsdm1 13:20bdea8bb997 69 setFreqBand(region);
jenkins@jenkinsdm1 13:20bdea8bb997 70 return true;
jenkins@jenkinsdm1 13:20bdea8bb997 71 case ButtonHandler::sw2_press:
jenkins@jenkinsdm1 13:20bdea8bb997 72 _menu->scroll();
jenkins@jenkinsdm1 13:20bdea8bb997 73 break;
jenkins@jenkinsdm1 13:20bdea8bb997 74 case ButtonHandler::sw1_hold:
jenkins@jenkinsdm1 13:20bdea8bb997 75 return true;
jenkins@jenkinsdm1 13:20bdea8bb997 76 default:
jenkins@jenkinsdm1 13:20bdea8bb997 77 break;
jenkins@jenkinsdm1 13:20bdea8bb997 78 }
jenkins@jenkinsdm1 13:20bdea8bb997 79 }
jenkins@jenkinsdm1 13:20bdea8bb997 80 }
jenkins@jenkinsdm1 13:20bdea8bb997 81 }
jenkins@jenkinsdm1 13:20bdea8bb997 82 }
jenkins@jenkinsdm1 13:20bdea8bb997 83
jenkins@jenkinsdm1 13:20bdea8bb997 84 void ModeRegion::setFreqBand(std::string region)
jenkins@jenkinsdm1 13:20bdea8bb997 85 {
jenkins@jenkinsdm1 13:20bdea8bb997 86 uint8_t cp[] = { 0 };
jenkins@jenkinsdm1 13:20bdea8bb997 87 mDot::mdot_file file = _dot->openUserFile(_file_cp, mDot::FM_RDWR);
jenkins@jenkinsdm1 13:20bdea8bb997 88
jenkins@jenkinsdm1 13:20bdea8bb997 89 // First delete the existing plan
jenkins@jenkinsdm1 13:20bdea8bb997 90 lora::ChannelPlan *plan = _dot->getChannelPlan();
jenkins@jenkinsdm1 13:20bdea8bb997 91 if (plan != NULL)
jenkins@jenkinsdm1 13:20bdea8bb997 92 delete plan;
jenkins@jenkinsdm1 13:20bdea8bb997 93
jenkins@jenkinsdm1 13:20bdea8bb997 94 // Construct a channel plan for the selected region
jenkins@jenkinsdm1 13:20bdea8bb997 95 if (region == "US915") {
jenkins@jenkinsdm1 13:20bdea8bb997 96 plan = new lora::ChannelPlan_US915();
jenkins@jenkinsdm1 13:20bdea8bb997 97 cp[0] = CP_US915;
jenkins@jenkinsdm1 13:20bdea8bb997 98 } else if (region == "AU915") {
jenkins@jenkinsdm1 13:20bdea8bb997 99 plan = new lora::ChannelPlan_AU915();
jenkins@jenkinsdm1 13:20bdea8bb997 100 cp[0] = CP_AU915;
jenkins@jenkinsdm1 13:20bdea8bb997 101 } else if (region == "EU868") {
jenkins@jenkinsdm1 13:20bdea8bb997 102 plan = new lora::ChannelPlan_EU868();
jenkins@jenkinsdm1 13:20bdea8bb997 103 cp[0] = CP_EU868;
jenkins@jenkinsdm1 13:20bdea8bb997 104 } else if (region == "AS923") {
jenkins@jenkinsdm1 13:20bdea8bb997 105 plan = new lora::ChannelPlan_AS923();
jenkins@jenkinsdm1 13:20bdea8bb997 106 cp[0] = CP_AS923;
jenkins@jenkinsdm1 13:20bdea8bb997 107 } else if (region == "AS923-JAPAN") {
jenkins@jenkinsdm1 13:20bdea8bb997 108 plan = new lora::ChannelPlan_AS923_Japan();
jenkins@jenkinsdm1 13:20bdea8bb997 109 cp[0] = CP_AS923_JAPAN;
jenkins@jenkinsdm1 13:20bdea8bb997 110 } else if (region == "KR920") {
jenkins@jenkinsdm1 13:20bdea8bb997 111 plan = new lora::ChannelPlan_KR920();
jenkins@jenkinsdm1 13:20bdea8bb997 112 cp[0] = CP_KR920;
jenkins@jenkinsdm1 13:20bdea8bb997 113 } else if (region == "IN865") {
jenkins@jenkinsdm1 13:20bdea8bb997 114 plan = new lora::ChannelPlan_IN865();
jenkins@jenkinsdm1 13:20bdea8bb997 115 cp[0] = CP_IN865;
jenkins@jenkinsdm1 13:20bdea8bb997 116 }
jenkins@jenkinsdm1 13:20bdea8bb997 117
jenkins@jenkinsdm1 13:20bdea8bb997 118 if (_dot->setChannelPlan(plan) == mDot::MDOT_OK) {
jenkins@jenkinsdm1 13:20bdea8bb997 119 // Update the channel plan config
jenkins@jenkinsdm1 13:20bdea8bb997 120 _dot->seekUserFile(file, 0, SEEK_SET);
jenkins@jenkinsdm1 13:20bdea8bb997 121 _dot->writeUserFile(file, cp, 1);
jenkins@jenkinsdm1 13:20bdea8bb997 122 _dot->closeUserFile(file);
jenkins@jenkinsdm1 13:20bdea8bb997 123 _band = _dot->getFrequencyBand();
jenkins@jenkinsdm1 13:20bdea8bb997 124 logInfo("Setting channel plan to %s", region.c_str());
jenkins@jenkinsdm1 13:20bdea8bb997 125 } else {
jenkins@jenkinsdm1 13:20bdea8bb997 126 logError("Failed to set channel plan to %s", region.c_str());
jenkins@jenkinsdm1 13:20bdea8bb997 127 }
jenkins@jenkinsdm1 13:20bdea8bb997 128 }