Federico Andrades / Mbed OS Dot-AT-Firmware

Dependencies:   MTS-Serial libxDot-dev-mbed5-deprecated

Fork of Dot-AT-Firmware by MultiTech

Files at this revision

API Documentation at this revision

Comitter:
jenkins@jenkinsdm1
Date:
Mon Jun 19 14:33:21 2017 -0500
Parent:
15:e20116281a78
Child:
17:95c9eb69329a
Commit message:
mdot-firmware revision 3.0.0-rc7

Changed in this revision

CommandTerminal/CmdChannelMask.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdDisplayConfig.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdFrequencyBand.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdIdentification.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdJoinRx1Offset.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdJoinRx2Datarate.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdJoinRx2Frequency.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdMacCmd.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdRxDataRate.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdRxFrequency.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdTxChannel.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdTxDataRate.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdTxFrequency.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CmdTxPower.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CommandTerminal.cpp Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/CommandTerminal.h Show annotated file Show diff for this revision Revisions of this file
CommandTerminal/Commands.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mts_at_version.h Show annotated file Show diff for this revision Revisions of this file
--- a/CommandTerminal/CmdChannelMask.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdChannelMask.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -1,4 +1,5 @@
 #include "CmdChannelMask.h"
+#include "ChannelPlan.h"
 
 CmdChannelMask::CmdChannelMask()
 :
@@ -56,7 +57,7 @@
             return false;
         }
 
-        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868) {
+        if (lora::ChannelPlan::IsPlanDynamic(CommandTerminal::Dot()->getFrequencyBand())) {
             if (offset > 0) {
                 CommandTerminal::setErrorMessage("Invalid offset, expects (0)");
                 return false;
--- a/CommandTerminal/CmdDisplayConfig.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdDisplayConfig.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -11,7 +11,9 @@
     CommandTerminal::Serial()->writef("Device ID:\t\t");
     CommandTerminal::Serial()->writef("%s\r\n", mts::Text::bin2hexString(CommandTerminal::Dot()->getDeviceId(), ":").c_str());
 
-    CommandTerminal::Serial()->writef("Frequency Band:\t\t%s\r\n", mDot::FrequencyBandStr(CommandTerminal::Dot()->getFrequencyBand()).c_str());
+    CommandTerminal::Serial()->writef("Default Frequency Band:\t%s\r\n", CommandTerminal::Dot()->FrequencyBandStr(CommandTerminal::Dot()->getDefaultFrequencyBand()).c_str());
+    // using getChannelPlanName here instead of mDot::FrequencyBandStr allows AT firmware to properly display custom channel plan names
+    CommandTerminal::Serial()->writef("Current Frequency Band:\t%s\r\n", CommandTerminal::Dot()->getChannelPlanName().c_str());
     CommandTerminal::Serial()->writef("Frequency Sub Band:\t%u\r\n", CommandTerminal::Dot()->getFrequencySubBand());
 
     CommandTerminal::Serial()->writef("Public Network:\t\t%s\r\n", CommandTerminal::Dot()->getPublicNetwork() ? "on" : "off");
@@ -53,6 +55,13 @@
 
     CommandTerminal::Serial()->writef("App Port:\t\t%d\r\n", CommandTerminal::Dot()->getAppPort());
 
+    CommandTerminal::Serial()->writef("Listen Before Talk:\t");
+    if (CommandTerminal::Dot()->getLbtTimeUs() == 0 && CommandTerminal::Dot()->getLbtThreshold() == 0) {
+        CommandTerminal::Serial()->writef("off\r\n");
+    } else {
+        CommandTerminal::Serial()->writef("%u us, %d dBm\r\n", CommandTerminal::Dot()->getLbtTimeUs(), CommandTerminal::Dot()->getLbtThreshold());
+    }
+
     CommandTerminal::Serial()->writef("Link Check Threshold:\t");
     if (CommandTerminal::Dot()->getLinkCheckThreshold() == 0) {
         CommandTerminal::Serial()->writef("off\r\n");
@@ -92,7 +101,9 @@
     CommandTerminal::Serial()->writef("Tx Frequency:\t\t%lu\r\n", CommandTerminal::Dot()->getTxFrequency());
 
     CommandTerminal::Serial()->writef("Tx Data Rate:\t\tDR%d - %s\r\n", CommandTerminal::Dot()->getTxDataRate(), CommandTerminal::Dot()->getDateRateDetails(CommandTerminal::Dot()->getTxDataRate()).c_str());
+    CommandTerminal::Serial()->writef("Min/Max Tx Data Rate:\tMin: DR%d - %s\r\n\t\t\tMax: DR%d - %s\r\n", CommandTerminal::Dot()->getMinDatarate(), CommandTerminal::Dot()->getDateRateDetails(CommandTerminal::Dot()->getMinDatarate()).c_str(), CommandTerminal::Dot()->getMaxDatarate(), CommandTerminal::Dot()->getDateRateDetails(CommandTerminal::Dot()->getMaxDatarate()).c_str());
     CommandTerminal::Serial()->writef("Tx Power:\t\t%u\r\n", CommandTerminal::Dot()->getTxPower());
+    CommandTerminal::Serial()->writef("Min/Max Tx Power:\tMin: %u\r\n\t\t\tMax: %u\r\n", CommandTerminal::Dot()->getMinTxPower(), CommandTerminal::Dot()->getMaxTxPower());
     CommandTerminal::Serial()->writef("Tx Antenna Gain:\t%d\r\n", CommandTerminal::Dot()->getAntennaGain());
     CommandTerminal::Serial()->writef("Tx Wait:\t\t%s\r\n", CommandTerminal::Dot()->getTxWait() ? "on" : "off");
 
--- a/CommandTerminal/CmdFrequencyBand.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdFrequencyBand.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -1,8 +1,7 @@
 #include "CmdFrequencyBand.h"
 
-
 CmdFrequencyBand::CmdFrequencyBand() :
-        Command("Frequency Band", "AT+FREQ", "Configured Frequency Band 'EU868', 'US915' or 'AU915'", "(EU868,US915,AU915)")
+        Command("Current Frequency Band", "AT+FREQ", "Current Frequency Band of Device 'US915', 'AU915', 'EU868', 'AS923', 'KR920', or 'AS923-JAPAN'", "(US915,AU915,EU868,AS923,KR920,AS923-JAPAN)")
 {
     _queryable = true;
 }
@@ -11,33 +10,10 @@
                                   {
     if (args.size() == 1)
     {
-        CommandTerminal::Serial()->writef("%s\r\n", mDot::FrequencyBandStr(CommandTerminal::Dot()->getFrequencyBand()).c_str());
+        // using getChannelPlanName here instead of mDot::FrequencyBandStr allows AT firmware to properly display custom channel plan names
+        CommandTerminal::Serial()->writef("%s\r\n", CommandTerminal::Dot()->getChannelPlanName().c_str());
     }
 
-#ifdef DEBUG_MAC
-    else if (args.size() == 2)
-    {
-        uint8_t band = mDot::FB_US915;
-        std::string band_str = mts::Text::toUpper(args[1]);
-
-
-        if (mDot::FrequencyBandStr(mDot::FB_EU868).find(band_str) != std::string::npos) {
-            band = mDot::FB_EU868;
-        }
-        if (mDot::FrequencyBandStr(mDot::FB_AU915).find(band_str) != std::string::npos) {
-            band = mDot::FB_AU915;
-        }
-        if (mDot::FrequencyBandStr(mDot::FB_US915).find(band_str) != std::string::npos) {
-            band = mDot::FB_US915;
-        }
-
-        if (CommandTerminal::Dot()->setFrequencyBand(band) != mDot::MDOT_OK) {
-            CommandTerminal::setErrorMessage(CommandTerminal::Dot()->getLastError());;
-            return 1;
-        }
-    }
-#endif
-
     return 0;
 }
 
@@ -46,23 +22,6 @@
     if (args.size() == 1)
         return true;
 
-#ifdef DEBUG_MAC
-    if (args.size() == 2)
-    {
-        std::string band = mts::Text::toUpper(args[1]);
-
-        if (mDot::FrequencyBandStr(mDot::FB_EU868).find(band) == std::string::npos &&
-            mDot::FrequencyBandStr(mDot::FB_US915).find(band) == std::string::npos &&
-            mDot::FrequencyBandStr(mDot::FB_AU915).find(band) == std::string::npos)
-        {
-            CommandTerminal::setErrorMessage("Invalid parameter, expects (EU868,US915,AU915)");
-            return false;
-        }
-
-        return true;
-    }
-#endif
-
     CommandTerminal::setErrorMessage("Invalid arguments");
     return false;
 }
--- a/CommandTerminal/CmdIdentification.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdIdentification.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -23,8 +23,9 @@
 #else
     CommandTerminal::Serial()->writef("MultiTech xDot\r\n");
 #endif /* TARGET_MTS_MDOT_F411RE */
-    CommandTerminal::Serial()->writef("Firmware: %s\r\n", version.c_str());
-    CommandTerminal::Serial()->writef("Library : %s\r\n", CommandTerminal::Dot()->getId().c_str());
+    CommandTerminal::Serial()->writef("Firmware : %s\r\n", version.c_str());
+    CommandTerminal::Serial()->writef("Library  : %s\r\n", CommandTerminal::Dot()->getId().c_str());
+    CommandTerminal::Serial()->writef("MTS-Lora : %s\r\n", CommandTerminal::Dot()->getMtsLoraId().c_str());
 
     return 0;
 }
--- a/CommandTerminal/CmdJoinRx1Offset.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdJoinRx1Offset.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -32,23 +32,6 @@
         return true;
 
     if (args.size() == 2) {
-        std::string dr = mts::Text::toUpper(args[1]);
-
-        int offset = -1;
-        sscanf(dr.c_str(), "%d", &offset);
-
-        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915 || CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-            if (offset < 0 || offset > 3) {
-                CommandTerminal::setErrorMessage("Invalid offset, expects (0-3)");
-                return false;
-            }
-        } else {
-            if (offset < 0 || offset > 5) {
-                CommandTerminal::setErrorMessage("Invalid offset, expects (0-5)");
-                return false;
-            }
-        }
-
         return true;
     }
 
--- a/CommandTerminal/CmdJoinRx2Datarate.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdJoinRx2Datarate.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -30,7 +30,7 @@
         }
 
         if (CommandTerminal::Dot()->setJoinRx2DataRate(datarate) != mDot::MDOT_OK) {
-            CommandTerminal::setErrorMessage(CommandTerminal::Dot()->getLastError());;
+            CommandTerminal::setErrorMessage(CommandTerminal::Dot()->getLastError());
             return 1;
         }
     }
@@ -43,35 +43,6 @@
         return true;
 
     if (args.size() == 2) {
-        std::string dr = mts::Text::toUpper(args[1]);
-
-        uint8_t i;
-        int datarate = -1;
-
-        int res = sscanf(dr.c_str(), "%d", &datarate);
-
-        if (res == 0) {
-            for (i = 0; i < 16; i++) {
-                if (mDot::DataRateStr(i).find(dr) != std::string::npos) {
-                    datarate = i;
-                    break;
-                }
-            }
-        }
-
-        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915 || CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-            // DR8-13 used for P2P modes
-            if (datarate < 8 || datarate > 13) {
-                CommandTerminal::setErrorMessage("Invalid data rate, expects (DR8-DR13)");
-                return false;
-            }
-        } else {
-            if (datarate < 0 || datarate > 7) {
-                CommandTerminal::setErrorMessage("Invalid data rate, expects (DR0-DR7)");
-                return false;
-            }
-        }
-
         return true;
     }
 
--- a/CommandTerminal/CmdJoinRx2Frequency.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdJoinRx2Frequency.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -10,17 +10,18 @@
 uint32_t CmdJoinRx2Frequency::action(std::vector<std::string> args) {
 
     if (args.size() == 1)
-    {
+        {
         CommandTerminal::Serial()->writef("%lu\r\n", CommandTerminal::Dot()->getJoinRx2Frequency());
     }
     else if (args.size() == 2)
-    {
+             {
         int frequency = 0;
 
         sscanf(args[1].c_str(), "%d", &frequency);
         if (CommandTerminal::Dot()->setJoinRx2Frequency(frequency) != mDot::MDOT_OK)
-        {
-            CommandTerminal::setErrorMessage(CommandTerminal::Dot()->getLastError());;
+            {
+            CommandTerminal::setErrorMessage(CommandTerminal::Dot()->getLastError());
+            ;
             return 1;
         }
     }
@@ -32,8 +33,7 @@
     if (args.size() == 1)
         return true;
 
-    if (args.size() == 2)
-        {
+    if (args.size() == 2) {
         int frequency = ULONG_MAX;
         if (sscanf(args[1].c_str(), "%d", &frequency) != 1) {
             CommandTerminal::setErrorMessage("Invalid argument");
@@ -41,16 +41,11 @@
         }
 
         if (frequency != 0 && (frequency < int(CommandTerminal::Dot()->getMinFrequency()) || frequency > int(CommandTerminal::Dot()->getMaxFrequency()))) {
-            if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868)
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,863000000-870000000)");
-            else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915)
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,915000000-928000000)");
-            else
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,902000000-928000000)");
-
+            char tmp[256];
+            sprintf(tmp, "Invalid frequency, expects (0,%lu-%lu)", CommandTerminal::Dot()->getMinFrequency(), CommandTerminal::Dot()->getMaxFrequency());
+            CommandTerminal::setErrorMessage(tmp);
             return false;
         }
-
         return true;
     }
 
--- a/CommandTerminal/CmdMacCmd.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdMacCmd.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -12,7 +12,7 @@
     if (args.size() == 1) {
         std::vector<uint8_t> cmds = CommandTerminal::Dot()->getMacCommands();
 
-        if (cmds.size() > 1) {
+        if (cmds.size() > 0) {
             for (size_t i = 0; i < cmds.size(); i++) {
                 CommandTerminal::Serial()->writef("%02x", cmds[i]);
             }
--- a/CommandTerminal/CmdRxDataRate.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdRxDataRate.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -2,7 +2,7 @@
 
 CmdRxDataRate::CmdRxDataRate()
 :
-  Command("Rx Data Rate", "AT+RXDR", "Set the Rx datarate, testing purposes only", "US:(7-10|DR0-DR4|DR8-DR13)) EU:(7-12|DR0-DR7))")
+  Command("Rx Data Rate", "AT+RXDR", "Set the Rx datarate, testing purposes only", "7-10|DR0-DR15, Depends on Channel Plan")
   
 {
     _queryable = true;
@@ -10,7 +10,7 @@
 
 uint32_t CmdRxDataRate::action(std::vector<std::string> args) {
     if (args.size() == 1) {
-        CommandTerminal::Serial()->writef("%s\r\n", mDot::DataRateStr(CommandTerminal::Dot()->getRxDataRate()).c_str());
+        CommandTerminal::Serial()->writef("DR%d - %s\r\n", CommandTerminal::Dot()->getTxDataRate(), CommandTerminal::Dot()->getDataRateDetails(CommandTerminal::Dot()->getRxDataRate()).c_str());
     }
     else if (args.size() == 2) {
         std::string dr = mts::Text::toUpper(args[1]);
@@ -27,15 +27,6 @@
                     break;
                 }
             }
-        } else {
-            if (datarate > 6) {
-                // Convert SF to DR
-                if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915 || CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-                    datarate = 10 - datarate;
-                } else {
-                    datarate = 12 - datarate;
-                }
-            }
         }
 
         if (CommandTerminal::Dot()->setRxDataRate(datarate) != mDot::MDOT_OK) {
@@ -52,49 +43,6 @@
         return true;
 
     if (args.size() == 2) {
-        std::string dr = mts::Text::toUpper(args[1]);
-
-        uint8_t i;
-        int datarate = -1;
-
-        int res = sscanf(dr.c_str(), "%d", &datarate);
-
-        if (res == 0) {
-            for (i = 0; i < 24; i++) {
-                if (mDot::DataRateStr(i).find(dr) != std::string::npos) {
-                    datarate = i;
-                    break;
-                }
-            }
-        } else {
-
-            if ((CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915  || CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915 ) && datarate > 10) {
-                datarate = -1;
-            } else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868 && datarate > 12) {
-                datarate = -1;
-            } else if (datarate > 6) {
-                // Convert SF to DR
-                if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915 || CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-                    datarate = 10 - datarate;
-                } else {
-                    datarate = 12 - datarate;
-                }
-            }
-        }
-
-        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915 || CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-            // DR8-13 used for P2P modes
-            if (datarate < 0 || datarate > 13 || (datarate >= 5 && datarate <= 7)) {
-                CommandTerminal::setErrorMessage("Invalid data rate, expects (7-10|DR0-DR4|DR8-DR13)");
-                return false;
-            }
-        } else {
-            if (datarate < 0 || datarate > 7) {
-                CommandTerminal::setErrorMessage("Invalid data rate, expects (7-12|DR0-DR7)");
-                return false;
-            }
-        }
-
         return true;
     }
 
--- a/CommandTerminal/CmdRxFrequency.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdRxFrequency.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -1,26 +1,26 @@
 #include "CmdRxFrequency.h"
 
-CmdRxFrequency::CmdRxFrequency() :
-    Command("Rx Frequency", "AT+RXF", "Set the Rx frequency for +RECV,+RECVC", "US:(0,902000000-928000000) EU:(0,863000000-870000000)")
+CmdRxFrequency::CmdRxFrequency()
+:
+  Command("Rx Frequency", "AT+RXF", "Set the Rx frequency for +RECV,+RECVC", "SEE PLAN")
 {
     _queryable = true;
 }
 
-uint32_t CmdRxFrequency::action(std::vector<std::string> args)
-{
-    if (args.size() == 1)
-    {
+uint32_t CmdRxFrequency::action(std::vector<std::string> args) {
+    if (args.size() == 1) {
         CommandTerminal::Serial()->writef("%lu\r\n", CommandTerminal::Dot()->getRxFrequency());
     }
     else if (args.size() == 2)
-    {
-        
+             {
+
         int frequency = 0;
         sscanf(args[1].c_str(), "%d", &frequency);
         if (CommandTerminal::Dot()->setRxFrequency(frequency) != mDot::MDOT_OK)
-        {
-            
-            CommandTerminal::setErrorMessage(CommandTerminal::Dot()->getLastError());;
+            {
+
+            CommandTerminal::setErrorMessage(CommandTerminal::Dot()->getLastError());
+            ;
             return 1;
         }
     }
@@ -28,28 +28,22 @@
     return 0;
 }
 
-bool CmdRxFrequency::verify(std::vector<std::string> args)
-{
+bool CmdRxFrequency::verify(std::vector<std::string> args) {
     if (args.size() == 1)
         return true;
 
     if (args.size() == 2)
-    {
+        {
         int frequency;
         if (sscanf(args[1].c_str(), "%d", &frequency) != 1) {
             CommandTerminal::setErrorMessage("Invalid argument");
             return false;
         }
 
-
         if (frequency != 0 && (frequency < int(CommandTerminal::Dot()->getMinFrequency()) || frequency > int(CommandTerminal::Dot()->getMaxFrequency()))) {
-            if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868)
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,863000000-870000000)");
-            else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915)
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,915000000-928000000)");
-            else
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,902000000-928000000)");
-
+            char tmp[256];
+            sprintf(tmp, "Invalid frequency, expects (0,%lu-%lu)", CommandTerminal::Dot()->getMinFrequency(), CommandTerminal::Dot()->getMaxFrequency());
+            CommandTerminal::setErrorMessage(tmp);
             return false;
         }
 
--- a/CommandTerminal/CmdTxChannel.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdTxChannel.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -1,4 +1,5 @@
 #include "CmdTxChannel.h"
+#include "ChannelPlan.h"
 
 CmdTxChannel::CmdTxChannel()
 : Command("Tx Channels", "AT+TXCH", "List Tx channel frequencies for sub-band", "<INDEX>,<FREQUENCY>,<DR_RANGE>") {
@@ -14,7 +15,7 @@
 
         CommandTerminal::Serial()->writef("Index\tFrequency  DR Max Min  On\r\n");
 
-        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868) {
+        if (lora::ChannelPlan::IsPlanDynamic(CommandTerminal::Dot()->getFrequencyBand())) {
             for (int8_t i = 0; i < 16; i++) {
                 if (channels[i] != 0)
                     CommandTerminal::Serial()->writef("  %d\t%d      %X   %X    %d\r\n", i, channels[i], ranges[i] >> 4, ranges[i] & 0xF, (mask[0] & (0x1 << i)) ? 1 : 0);
@@ -60,7 +61,10 @@
         sscanf(args[2].c_str(), "%d", &frequency);
         sscanf(args[3].c_str(), "%02x", &datarateRange);
 
-        CommandTerminal::Dot()->addChannel(index, frequency, datarateRange);
+        if (CommandTerminal::Dot()->addChannel(index, frequency, datarateRange) != mDot::MDOT_OK) {
+            CommandTerminal::setErrorMessage("Failed to add channel");
+            return 1;
+        }
     }
 
     return 0;
@@ -80,18 +84,15 @@
         sscanf(args[2].c_str(), "%d", &frequency);
         sscanf(args[3].c_str(), "%02x", &datarateRange);
 
-        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868) {
-            if (index < 3 || index > 15) {
-                CommandTerminal::setErrorMessage("Invalid index, expects (3-15)");
-                return false;
-            }
-
-            if (frequency != 0 && (frequency < 863000000 || frequency > 870000000)) {
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (863000000-870000000)");
+        if (lora::ChannelPlan::IsPlanDynamic(CommandTerminal::Dot()->getFrequencyBand())) {
+            if (frequency != 0 && (frequency < int(CommandTerminal::Dot()->getMinFrequency()) || frequency > int(CommandTerminal::Dot()->getMaxFrequency()))) {
+                char tmp[256];
+                sprintf(tmp, "Invalid frequency, expects (0,%lu-%lu)", CommandTerminal::Dot()->getMinFrequency(), CommandTerminal::Dot()->getMaxFrequency());
+                CommandTerminal::setErrorMessage(tmp);
                 return false;
             }
         } else {
-            CommandTerminal::setErrorMessage("US915|AU915 Channels cannot be changed, use AT+FSB or AT+CHM to limit");
+            CommandTerminal::setErrorMessage("Fixed channel plans cannot be changed, use AT+FSB or AT+CHM to limit");
             return false;
         }
 
--- a/CommandTerminal/CmdTxDataRate.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdTxDataRate.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -4,14 +4,14 @@
 
 
 CmdTxDataRate::CmdTxDataRate()
-: Command("Tx Data Rate", "AT+TXDR", "Set the Tx data rate for all channels", "US:(7-10|DR0-DR4|DR8-DR13)) EU:(7-12|DR0-DR7))") {
+: Command("Tx Data Rate", "AT+TXDR", "Set the Tx data rate for all channels", "7-10|DR0-DR15, Depends on Channel Plan") {
     _queryable = true;
 }
 
 uint32_t CmdTxDataRate::action(std::vector<std::string> args) {
     if (args.size() == 1)
         {
-        CommandTerminal::Serial()->writef("DR%d - %s\r\n", CommandTerminal::Dot()->getTxDataRate(), CommandTerminal::Dot()->getDateRateDetails(CommandTerminal::Dot()->getTxDataRate()).c_str());
+        CommandTerminal::Serial()->writef("DR%d - %s\r\n", CommandTerminal::Dot()->getTxDataRate(), CommandTerminal::Dot()->getDataRateDetails(CommandTerminal::Dot()->getTxDataRate()).c_str());
     } else if (args.size() == 2) {
         std::string dr = mts::Text::toUpper(args[1]);
         
@@ -27,18 +27,6 @@
                     break;
                 }
             }
-        } else {
-            if (datarate > 6) {
-                // Convert SF to DR
-
-                if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915) {
-                    datarate = 10 - datarate;
-                } else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-                    datarate = 10 - datarate;
-                } else {
-                    datarate = 12 - datarate;
-                }
-            }
         }
 
         if (CommandTerminal::Dot()->setTxDataRate(datarate) != mDot::MDOT_OK) {
@@ -55,78 +43,6 @@
         return true;
 
     if (args.size() == 2) {
-        std::string dr = mts::Text::toUpper(args[1]);
-
-        uint8_t i;
-        int datarate = -1;
-
-        int res = sscanf(dr.c_str(), "%d", &datarate);
-
-        if (res == 0) {
-            for (i = 0; i < 24; i++) {
-
-                if (mDot::DataRateStr(i).find(dr) != std::string::npos) {
-                    uint8_t _dr = i;
-
-                    if (_dr > 15) {
-                        _dr = 12 + (mDot::SF_12 - _dr);
-
-                        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868) {
-                            if (_dr == mDot::SF_7H) {
-                                _dr = mDot::DR6;
-                            } else if (_dr == mDot::SF_FSK) {
-                                _dr = mDot::DR7;
-                            } else {
-                                _dr = 12 - _dr;
-                            }
-                        } else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-                            _dr = 10 - _dr;
-                        } else {
-                            _dr = 10 - _dr;
-                        }
-                    }
-
-                    datarate = _dr;
-                    break;
-                }
-            }
-        } else {
-
-            if ((CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915) && datarate > 10) {
-                datarate = -1;
-            } else if (datarate > 12) {
-                datarate = -1;
-            } else if (datarate > 6) {
-                // Convert SF to DR
-                if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915) {
-                    datarate = 10 - datarate;
-                } else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-                    datarate = 10 - datarate;
-                } else {
-                    datarate = 12 - datarate;
-                }
-            }
-        }
-
-        if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_US915) {
-            // DR8-13 used for P2P modes
-            if (datarate < 0 || datarate > 13 || (datarate >= 5 && datarate <= 7)) {
-                CommandTerminal::setErrorMessage("Invalid data rate, expects (7-10|DR0-DR4|DR8-DR13)");
-                return false;
-            }
-        } else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915) {
-            // DR8-13 used for P2P modes
-            if (datarate < 0 || datarate > 13 || (datarate >= 5 && datarate <= 7)) {
-                CommandTerminal::setErrorMessage("Invalid data rate, expects (7-10|DR0-DR4|DR8-DR13)");
-                return false;
-            }
-        } else {
-            if (datarate < 0 || datarate > 7) {
-                CommandTerminal::setErrorMessage("Invalid data rate, expects (7-12|DR0-DR7)");
-                return false;
-            }
-        }
-
         return true;
     }
 
--- a/CommandTerminal/CmdTxFrequency.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdTxFrequency.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -3,7 +3,7 @@
 
 
 CmdTxFrequency::CmdTxFrequency() :
-    Command("Tx Frequency", "AT+TXF", "Set Tx frequency", "US:(0,902000000-928000000), AU:(0, 915000000-928000000), EU:(0,863000000-870000000)") {
+    Command("Tx Frequency", "AT+TXF", "Set Tx frequency", "SEE PLAN") {
     _queryable = true;
 }
 
@@ -42,13 +42,9 @@
         }
 
         if (frequency != 0 && (frequency < int(CommandTerminal::Dot()->getMinFrequency()) || frequency > int(CommandTerminal::Dot()->getMaxFrequency()))) {
-            if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_EU868)
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,863000000-870000000)"); 
-            else if (CommandTerminal::Dot()->getFrequencyBand() == mDot::FB_AU915)
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,915000000-928000000)");
-            else
-                CommandTerminal::setErrorMessage("Invalid frequency, expects (0,902000000-928000000)");
-
+            char tmp[256];
+            sprintf(tmp, "Invalid frequency, expects (0,%lu-%lu)", CommandTerminal::Dot()->getMinFrequency(), CommandTerminal::Dot()->getMaxFrequency());
+            CommandTerminal::setErrorMessage(tmp);
             return false;
         }
 
--- a/CommandTerminal/CmdTxPower.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CmdTxPower.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -1,7 +1,7 @@
 #include "CmdTxPower.h"
 
 CmdTxPower::CmdTxPower() :
-    Command("Tx Power", "AT+TXP", "Set the radio TX power before antenna gain in dBm", "(0-30)") {
+    Command("Tx Power", "AT+TXP", "Set the radio TX power before antenna gain in dBm", "(2-36, Depends on Channel Plan)") {
     _queryable = true;
 }
 
@@ -39,9 +39,13 @@
             return false;
         }
 
-        if (power < 0 || power > 30)
+        if (power < CommandTerminal::Dot()->getMinTxPower() || power > CommandTerminal::Dot()->getMaxTxPower())
         {
-            CommandTerminal::setErrorMessage("Invalid power, expects (0-30)");
+            char buf[8];
+            std::string error = "Invalid power, expects ";
+            snprintf(buf, sizeof(buf), "(%d-%d)", CommandTerminal::Dot()->getMinTxPower(), CommandTerminal::Dot()->getMaxTxPower());
+            error.append(buf);
+            CommandTerminal::setErrorMessage(error);
             return false;
         }
 
--- a/CommandTerminal/CommandTerminal.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CommandTerminal.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -2,6 +2,7 @@
 #include "CommandTerminal.h"
 #include "Command.h"
 #include "MTSLog.h"
+#include "ChannelPlan.h"
 #include <cstdarg>
 #include <deque>
 #if defined(TARGET_XDOT_L151CC)
@@ -66,11 +67,13 @@
     CmdDebugBaudRate(),
     CmdStartUpMode(),
 
+    CmdDefaultFrequencyBand(),
     CmdFrequencyBand(),
     CmdFrequencySubBand(),
     CmdPublicNetwork(),
     CmdDeviceId(),
     CmdDeviceClass(),
+    CmdLbt(),
 
     CmdAppPort(),
     CmdNetworkAddress(),
@@ -156,6 +159,7 @@
     CmdDumpRegisters(),
     CmdEraseFlash(),
     CmdDisableDutyCycle(),
+    CmdLBTRSSI(),
 #endif
 
 };
@@ -177,11 +181,13 @@
     CmdDebugBaudRate::verify,
     CmdStartUpMode::verify,
 
+    CmdDefaultFrequencyBand::verify,
     CmdFrequencyBand::verify,
     CmdFrequencySubBand::verify,
     CmdPublicNetwork::verify,
     CmdDeviceId::verify,
     CmdDeviceClass::verify,
+    CmdLbt::verify,
 
     CmdAppPort::verify,
     CmdNetworkAddress::verify,
@@ -267,6 +273,7 @@
     CmdDummy::verify,
     CmdEraseFlash::verify,
     CmdDisableDutyCycle::verify,
+    CmdLBTRSSI::verify,
 #endif
 
 };
@@ -288,11 +295,13 @@
     CmdDebugBaudRate::action,
     CmdStartUpMode::action,
 
+    CmdDefaultFrequencyBand::action,
     CmdFrequencyBand::action,
     CmdFrequencySubBand::action,
     CmdPublicNetwork::action,
     CmdDeviceId::action,
     CmdDeviceClass::action,
+    CmdLbt::action,
 
     CmdAppPort::action,
     CmdNetworkAddress::action,
@@ -378,6 +387,7 @@
     CmdDumpRegisters::action,
     CmdEraseFlash::action,
     CmdDisableDutyCycle::action,
+    CmdLBTRSSI::action,
 #endif
 
 };
@@ -636,7 +646,7 @@
         if (!_serial.escaped() && _dot->getFrequencySubBand() != 0 && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
             cnt = 0;
 
-            if (_dot->getFrequencyBand() == mDot::FB_US915 || _dot->getFrequencyBand() == mDot::FB_AU915 ) {
+            if (lora::ChannelPlan::IsPlanFixed(_dot->getFrequencyBand())) {
                 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
                 logWarning("Join retries exhausted, switching to sub band %u", band);
                 _dot->setFrequencySubBand(band);
--- a/CommandTerminal/CommandTerminal.h	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/CommandTerminal.h	Mon Jun 19 14:33:21 2017 -0500
@@ -76,6 +76,12 @@
             logDebug("RadioEvent - JoinAccept");
         }
 
+        virtual void JoinFailed(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) {
+            mDotEvent::JoinFailed(payload, size, rssi, snr);
+
+            logDebug("RadioEvent - JoinFailed");
+        }
+
         virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries = 0);
 
         virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot) {
@@ -112,6 +118,10 @@
             return 255;
         }
 
+        virtual void MissedAck(uint8_t retries) {
+            mDotEvent::MissedAck(retries);
+        }
+
         bool SendAck() {
             bool val = _sendAck;
             _sendAck = false;
--- a/CommandTerminal/Commands.h	Fri Nov 04 17:04:54 2016 -0500
+++ b/CommandTerminal/Commands.h	Mon Jun 19 14:33:21 2017 -0500
@@ -22,6 +22,7 @@
 #include "CmdDebugBaudRate.h"
 #include "CmdStartUpMode.h"
 
+#include "CmdDefaultFrequencyBand.h"
 #include "CmdFrequencyBand.h"
 #include "CmdDeviceId.h"
 #include "CmdDeviceClass.h"
@@ -67,6 +68,7 @@
 #include "CmdTxNextMs.h"
 #include "CmdTimeOnAir.h"
 #include "CmdFrequencySubBand.h"
+#include "CmdLbt.h"
 
 #include "CmdRxDelay.h"
 #include "CmdRxOutput.h"
@@ -104,11 +106,12 @@
 #include "CmdEraseFlash.h"
 #include "CmdSendContinuous.h"
 #include "CmdDisableDutyCycle.h"
+#include "CmdLBTRSSI.h"
 
 #endif // __COMMANDS_H__
 
 #ifdef MTS_RADIO_DEBUG_COMMANDS
-#define NO_OF_COMMANDS 91
+#define NO_OF_COMMANDS 92
 #else
 #define NO_OF_COMMANDS 85
 #endif
--- a/main.cpp	Fri Nov 04 17:04:54 2016 -0500
+++ b/main.cpp	Mon Jun 19 14:33:21 2017 -0500
@@ -3,18 +3,41 @@
 #include "CommandTerminal.h"
 #include "ATSerial.h"
 #include "ATSerialFlowControl.h"
+#include "ChannelPlans.h"
 
 #define SERIAL_BUFFER_SIZE 512
 
 Serial debug(USBTX, USBRX);
 
+#ifndef CHANNEL_PLAN
+#define CHANNEL_PLAN CP_US915
+#endif
+
 #ifndef UNIT_TEST
 
 int main()
 {
     debug.baud(115200);
 
-    mDot* dot = mDot::getInstance();
+#if CHANNEL_PLAN == CP_AS923
+    lora::ChannelPlan* plan = new lora::ChannelPlan_AS923();
+#elif CHANNEL_PLAN == CP_US915
+    lora::ChannelPlan* plan = new lora::ChannelPlan_US915();
+#elif CHANNEL_PLAN == CP_AU915
+    lora::ChannelPlan* plan = new lora::ChannelPlan_AU915();
+#elif CHANNEL_PLAN == CP_EU868
+    lora::ChannelPlan* plan = new lora::ChannelPlan_EU868();
+#elif CHANNEL_PLAN == CP_KR920
+    lora::ChannelPlan* plan = new lora::ChannelPlan_KR920();
+#elif CHANNEL_PLAN == CP_IN865
+    lora::ChannelPlan* plan = new lora::ChannelPlan_IN865();
+#elif CHANNEL_PLAN == CP_AS923_JAPAN
+    lora::ChannelPlan* plan = new lora::ChannelPlan_AS923_Japan();
+#endif
+    assert(plan);
+
+    mDot* dot = mDot::getInstance(plan);
+    assert(dot);
 
     // Seed the RNG
     srand(dot->getRadioRandom());
--- a/mts_at_version.h	Fri Nov 04 17:04:54 2016 -0500
+++ b/mts_at_version.h	Mon Jun 19 14:33:21 2017 -0500
@@ -1,6 +1,6 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define AT_APPLICATION_VERSION "2.0.16"
+#define AT_APPLICATION_VERSION "3.0.0-rc7"
 
 #endif