AT command firmware for MultiTech Dot devices.

Fork of mDot_AT_firmware by MultiTech

Dot Library Not Included!

Because these example programs can be used for both mDot and xDot devices, the LoRa stack is not included. The libmDot library should be imported if building for mDot devices. The libxDot library should be imported if building for xDot devices. The AT firmware was last tested with mbed-os-5.4.7. Using a version past mbed-os-5.4.7 will cause the build to fail. The library used with the AT firmware has to match the mbed-os version.

Dot Library Version 3 Updates

Dot Library versions 3.x.x require a channel plan to be injected into the stack. The Dot-Examples and Dot-AT-Firmware do this by defining a macro called "CHANNEL_PLAN" that controls the channel plan that will be used in the examples. Available channel plans will be in the Dot Library repository in the plans folder.

Revision 20 and earlier of Dot-Examples and revision 15 and earlier of Dot-AT-Firmware should be used with Dot Library versions prior to 3.0.0.

Fota Library

Th Fota Library must be added to compile for mDot 3.1.0 with Fota support. Latest dev libraries and 3.2.0 release will include Fota with libmDot/libxDot.

AT Firmware Description

This AT Firmware is what ships on mDot and xDot devices. It provides an AT command interface for using the mDot or xDot for LoRa communication.

AT command documentation can be found on Multitech.com.

The firmware changelog can be found here. The library changelog 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.

Stable and development libraries are available for both mDot and xDot platforms. The library chosen must match the target platform. Compiling for the mDot platform with the xDot library or vice versa will not succeed.

mDot Library

Development library for mDot.

libmDot-dev

Stable library for mDot.

libmDot

xDot Library

Development library for xDot.

libxDot-dev

Stable library for xDot.

libxDot

Committer:
Jason Reiss
Date:
Fri Jan 29 13:04:32 2021 -0600
Revision:
33:5c0252521669
Parent:
28:c222ca8383f4
Child:
34:3b696c2b1e4b
Remove moved commands

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike Fiore 1:e52ae6584f1c 1 #include "ctype.h"
Jason Reiss 27:5fafd3b26ac3 2 #include "CommandFactory.h"
Mike Fiore 1:e52ae6584f1c 3 #include "CommandTerminal.h"
Mike Fiore 1:e52ae6584f1c 4 #include "Command.h"
Mike Fiore 4:666017851052 5 #include "MTSLog.h"
jenkins@jenkinsdm1 16:d5cf2af81a6d 6 #include "ChannelPlan.h"
Mike Fiore 1:e52ae6584f1c 7 #include <cstdarg>
Mike Fiore 4:666017851052 8 #include <deque>
Jason Reiss 28:c222ca8383f4 9 #include "mts_at_version.h"
Jason Reiss 28:c222ca8383f4 10
Mike Fiore 14:f9a77400b622 11 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 14:f9a77400b622 12 #include "xdot_low_power.h"
Mike Fiore 14:f9a77400b622 13 #endif
Mike Fiore 1:e52ae6584f1c 14
Mike Fiore 14:f9a77400b622 15 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 1:e52ae6584f1c 16 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
Mike Fiore 14:f9a77400b622 17 #else
Mike Fiore 14:f9a77400b622 18 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa xDot Module\r\n\n";
Mike Fiore 14:f9a77400b622 19 #endif
Mike Fiore 1:e52ae6584f1c 20 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
Mike Fiore 1:e52ae6584f1c 21
Mike Fiore 1:e52ae6584f1c 22 const char CommandTerminal::newline[] = "\r\n";
Mike Fiore 1:e52ae6584f1c 23
Mike Fiore 1:e52ae6584f1c 24 // Command error text...
Mike Fiore 1:e52ae6584f1c 25 const char CommandTerminal::command_error[] = "Command not found!\r\n";
Mike Fiore 1:e52ae6584f1c 26
Mike Fiore 1:e52ae6584f1c 27 // Response texts...
Mike Fiore 1:e52ae6584f1c 28 const char CommandTerminal::help[] = "\r\nHelp\r\n";
Mike Fiore 1:e52ae6584f1c 29 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
Mike Fiore 9:ff62b20f7000 30 const char CommandTerminal::connect[] = "\r\nCONNECT\r\n";
Mike Fiore 9:ff62b20f7000 31 const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n";
Mike Fiore 1:e52ae6584f1c 32 const char CommandTerminal::done[] = "\r\nOK\r\n";
Mike Fiore 1:e52ae6584f1c 33 const char CommandTerminal::error[] = "\r\nERROR\r\n";
Mike Fiore 1:e52ae6584f1c 34
Mike Fiore 1:e52ae6584f1c 35 // Escape sequence...
Mike Fiore 1:e52ae6584f1c 36 const char CommandTerminal::escape_sequence[] = "+++";
Mike Fiore 1:e52ae6584f1c 37
Mike Fiore 9:ff62b20f7000 38 mts::ATSerial* CommandTerminal::_serialp = NULL;
Mike Fiore 14:f9a77400b622 39 mDot* CommandTerminal::_dot = NULL;
Mike Fiore 14:f9a77400b622 40
Mike Fiore 14:f9a77400b622 41 CommandTerminal::RadioEvent* CommandTerminal::_events = new RadioEvent();
Mike Fiore 9:ff62b20f7000 42
Mike Fiore 9:ff62b20f7000 43 static bool serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 44 static bool peer_to_peer = false;
Jason Reiss 27:5fafd3b26ac3 45 static bool command_processing = false;
Jason Reiss 27:5fafd3b26ac3 46 static bool urc_enabled = false;
Mike Fiore 1:e52ae6584f1c 47
Mike Fiore 14:f9a77400b622 48 std::string CommandTerminal::_errorMessage = "";
Mike Fiore 14:f9a77400b622 49
jenkins@jenkinsdm1 18:63f098f042b2 50 static uint8_t _battery_level = 0xFF;
jenkins@jenkinsdm1 18:63f098f042b2 51
Jason Reiss 23:4f0a981c0349 52 static uint8_t f_data[252]; //max payload 242 plus 10 bytes for format
Jason Reiss 23:4f0a981c0349 53 static uint32_t _rxAddress = 0;
Jason Reiss 28:c222ca8383f4 54 static uint32_t _rxFcnt = 0;
Jason Reiss 23:4f0a981c0349 55
Jason Reiss 27:5fafd3b26ac3 56 #if defined(TARGET_MTS_MDOT_F411RE)
Jason Reiss 27:5fafd3b26ac3 57 DigitalOut _packet_rx_pin(D12);
Jason Reiss 27:5fafd3b26ac3 58 DigitalOut _join_status_pin(A2);
Jason Reiss 27:5fafd3b26ac3 59 #else
Jason Reiss 27:5fafd3b26ac3 60 DigitalOut _packet_rx_pin(GPIO1);
Jason Reiss 27:5fafd3b26ac3 61 DigitalOut _join_status_pin(GPIO0);
Jason Reiss 27:5fafd3b26ac3 62 #endif
Jason Reiss 27:5fafd3b26ac3 63
Mike Fiore 14:f9a77400b622 64 void CommandTerminal::setErrorMessage(const char* message) {
Mike Fiore 14:f9a77400b622 65 _errorMessage.assign(message);
Mike Fiore 14:f9a77400b622 66 }
Mike Fiore 14:f9a77400b622 67
Mike Fiore 14:f9a77400b622 68 void CommandTerminal::setErrorMessage(const std::string& message) {
Mike Fiore 14:f9a77400b622 69 _errorMessage.assign(message);
Mike Fiore 1:e52ae6584f1c 70 }
Jason Reiss 23:4f0a981c0349 71
Mike Fiore 14:f9a77400b622 72 CommandTerminal::CommandTerminal(mts::ATSerial& serial) :
Mike Fiore 14:f9a77400b622 73 _serial(serial),
Mike Fiore 14:f9a77400b622 74 _mode(mDot::COMMAND_MODE),
Mike Fiore 14:f9a77400b622 75 _sleep_standby(true),
Mike Fiore 14:f9a77400b622 76 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 14:f9a77400b622 77 _xbee_on_sleep(XBEE_ON_SLEEP),
Mike Fiore 14:f9a77400b622 78 #else
Mike Fiore 14:f9a77400b622 79 _xbee_on_sleep(GPIO2),
Mike Fiore 14:f9a77400b622 80 #endif
Mike Fiore 14:f9a77400b622 81 _autoOTAEnabled(false)
Mike Fiore 14:f9a77400b622 82 {
Mike Fiore 14:f9a77400b622 83 _serialp = &serial;
Mike Fiore 14:f9a77400b622 84 }
Mike Fiore 14:f9a77400b622 85
Jason Reiss 28:c222ca8383f4 86 void free_mem() {
Jason Reiss 28:c222ca8383f4 87 // In order to get free mem within RTOS
Jason Reiss 28:c222ca8383f4 88 // we need to get the main thread's stack pointer
Jason Reiss 28:c222ca8383f4 89 // and subtract it with the top of the heap
Jason Reiss 28:c222ca8383f4 90 // ------+-------------------+ Last Address of RAM (INITIAL_SP)
Jason Reiss 28:c222ca8383f4 91 // | Scheduler Stack |
Jason Reiss 28:c222ca8383f4 92 // +-------------------+
Jason Reiss 28:c222ca8383f4 93 // | Main Thread Stack |
Jason Reiss 28:c222ca8383f4 94 // | | |
Jason Reiss 28:c222ca8383f4 95 // | v |
Jason Reiss 28:c222ca8383f4 96 // +-------------------+ <- bottom_of_stack/__get_MSP()
Jason Reiss 28:c222ca8383f4 97 // RAM | |
Jason Reiss 28:c222ca8383f4 98 // | Available RAM |
Jason Reiss 28:c222ca8383f4 99 // | |
Jason Reiss 28:c222ca8383f4 100 // +-------------------+ <- top_of_heap
Jason Reiss 28:c222ca8383f4 101 // | ^ |
Jason Reiss 28:c222ca8383f4 102 // | | |
Jason Reiss 28:c222ca8383f4 103 // | Heap |
Jason Reiss 28:c222ca8383f4 104 // +-------------------+ <- __end__ / HEAP_START (linker defined var)
Jason Reiss 28:c222ca8383f4 105 // | ZI |
Jason Reiss 28:c222ca8383f4 106 // +-------------------+
Jason Reiss 28:c222ca8383f4 107 // | ZI: Shell Stack |
Jason Reiss 28:c222ca8383f4 108 // +-------------------+
Jason Reiss 28:c222ca8383f4 109 // | ZI: Idle Stack |
Jason Reiss 28:c222ca8383f4 110 // +-------------------+
Jason Reiss 28:c222ca8383f4 111 // | ZI: Timer Stack |
Jason Reiss 28:c222ca8383f4 112 // +-------------------+
Jason Reiss 28:c222ca8383f4 113 // | RW |
Jason Reiss 28:c222ca8383f4 114 // ------+===================+ First Address of RAM
Jason Reiss 28:c222ca8383f4 115 // | |
Jason Reiss 28:c222ca8383f4 116 // Flash | |
Jason Reiss 28:c222ca8383f4 117 //
Jason Reiss 28:c222ca8383f4 118
Jason Reiss 28:c222ca8383f4 119 uint32_t bottom_of_stack = __get_MSP();
Jason Reiss 28:c222ca8383f4 120 char* top_of_heap = (char *) malloc(sizeof(char));
Jason Reiss 28:c222ca8383f4 121 uint32_t diff = bottom_of_stack - (uint32_t) top_of_heap;
Jason Reiss 28:c222ca8383f4 122
Jason Reiss 28:c222ca8383f4 123 free((void *) top_of_heap);
Jason Reiss 28:c222ca8383f4 124
Jason Reiss 28:c222ca8383f4 125 CommandTerminal::Serial()->writef("%lu bytes\r\n", diff);
Jason Reiss 28:c222ca8383f4 126 }
Jason Reiss 28:c222ca8383f4 127
Mike Fiore 14:f9a77400b622 128 void CommandTerminal::init() {
Mike Fiore 14:f9a77400b622 129 _dot->setEvents(_events);
Mike Fiore 1:e52ae6584f1c 130 }
Mike Fiore 1:e52ae6584f1c 131
Jason Reiss 28:c222ca8383f4 132 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 133 void CommandTerminal::printHelp() {
Mike Fiore 1:e52ae6584f1c 134 const char* name = NULL;
Mike Fiore 1:e52ae6584f1c 135 const char* text = NULL;
Mike Fiore 1:e52ae6584f1c 136 const char* desc = NULL;
Mike Fiore 1:e52ae6584f1c 137 const char* tab = "\t";
Mike Fiore 1:e52ae6584f1c 138
Mike Fiore 1:e52ae6584f1c 139 std::string header("Command");
Mike Fiore 1:e52ae6584f1c 140 header.append(tab);
Mike Fiore 1:e52ae6584f1c 141 header.append(tab);
Mike Fiore 1:e52ae6584f1c 142 header.append("Name");
Mike Fiore 1:e52ae6584f1c 143 header.append(tab);
Mike Fiore 1:e52ae6584f1c 144 header.append(tab);
Mike Fiore 1:e52ae6584f1c 145 header.append(tab);
Mike Fiore 1:e52ae6584f1c 146 header.append("Description");
Mike Fiore 1:e52ae6584f1c 147
Mike Fiore 1:e52ae6584f1c 148 write(newline);
Mike Fiore 1:e52ae6584f1c 149 write(header.c_str());
Mike Fiore 1:e52ae6584f1c 150 write(newline);
Mike Fiore 1:e52ae6584f1c 151 write(newline);
Mike Fiore 14:f9a77400b622 152
jenkins@jenkinsdm1 18:63f098f042b2 153 Command *cmd = NULL;
Jason Reiss 27:5fafd3b26ac3 154 for (int i = 0; i < CommandFactory::NUMBER_OF_CMDS; i++) {
Jason Reiss 27:5fafd3b26ac3 155 cmd = CommandFactory::Create(static_cast<CommandFactory::CmdId_t>(i));
jenkins@jenkinsdm1 18:63f098f042b2 156 name = cmd->name();
jenkins@jenkinsdm1 18:63f098f042b2 157 text = cmd->text();
jenkins@jenkinsdm1 18:63f098f042b2 158 desc = cmd->desc();
Mike Fiore 1:e52ae6584f1c 159 write(text);
Mike Fiore 1:e52ae6584f1c 160 if (strlen(text) < 8)
Mike Fiore 1:e52ae6584f1c 161 write(tab);
Mike Fiore 1:e52ae6584f1c 162 write(tab);
Mike Fiore 1:e52ae6584f1c 163 write(name);
Mike Fiore 1:e52ae6584f1c 164 if (strlen(name) < 8)
Mike Fiore 1:e52ae6584f1c 165 write(tab);
Mike Fiore 1:e52ae6584f1c 166 if (strlen(name) < 16)
Mike Fiore 1:e52ae6584f1c 167 write(tab);
Mike Fiore 1:e52ae6584f1c 168 write(tab);
Mike Fiore 1:e52ae6584f1c 169 write(desc);
Mike Fiore 1:e52ae6584f1c 170 write(newline);
jenkins@jenkinsdm1 18:63f098f042b2 171
jenkins@jenkinsdm1 18:63f098f042b2 172 delete cmd;
Mike Fiore 1:e52ae6584f1c 173 }
Mike Fiore 1:e52ae6584f1c 174
Mike Fiore 1:e52ae6584f1c 175 write(newline);
Mike Fiore 1:e52ae6584f1c 176 }
Jason Reiss 28:c222ca8383f4 177 #endif
Mike Fiore 1:e52ae6584f1c 178
Mike Fiore 1:e52ae6584f1c 179 bool CommandTerminal::writeable() {
Mike Fiore 14:f9a77400b622 180 return _serialp->writeable();
Mike Fiore 1:e52ae6584f1c 181 }
Mike Fiore 1:e52ae6584f1c 182
Mike Fiore 1:e52ae6584f1c 183 bool CommandTerminal::readable() {
Mike Fiore 14:f9a77400b622 184 return _serialp->readable();
Mike Fiore 1:e52ae6584f1c 185 }
Mike Fiore 1:e52ae6584f1c 186
Mike Fiore 1:e52ae6584f1c 187 char CommandTerminal::read() {
Mike Fiore 1:e52ae6584f1c 188 char ch;
Jason Reiss 28:c222ca8383f4 189 _serialp->read(ch);
Mike Fiore 1:e52ae6584f1c 190 return ch;
Mike Fiore 1:e52ae6584f1c 191 }
Mike Fiore 1:e52ae6584f1c 192
Mike Fiore 1:e52ae6584f1c 193 void CommandTerminal::write(const char* message) {
Mike Fiore 1:e52ae6584f1c 194 while (!writeable())
Mike Fiore 1:e52ae6584f1c 195 ;
Mike Fiore 14:f9a77400b622 196 _serialp->write(message, strlen(message));
Mike Fiore 1:e52ae6584f1c 197 }
Mike Fiore 1:e52ae6584f1c 198
Mike Fiore 1:e52ae6584f1c 199 void CommandTerminal::writef(const char* format, ...) {
Mike Fiore 1:e52ae6584f1c 200 char buff[256];
Mike Fiore 1:e52ae6584f1c 201
Mike Fiore 1:e52ae6584f1c 202 va_list ap;
Mike Fiore 1:e52ae6584f1c 203 va_start(ap, format);
Mike Fiore 1:e52ae6584f1c 204 int size = vsnprintf(buff, 256, format, ap);
Mike Fiore 1:e52ae6584f1c 205 while (!writeable())
Mike Fiore 1:e52ae6584f1c 206 ;
Mike Fiore 14:f9a77400b622 207 _serialp->write(buff, size);
Mike Fiore 1:e52ae6584f1c 208 va_end(ap);
Mike Fiore 1:e52ae6584f1c 209 }
Mike Fiore 1:e52ae6584f1c 210
Mike Fiore 9:ff62b20f7000 211 void CommandTerminal::serialLoop() {
Mike Fiore 1:e52ae6584f1c 212 Timer serial_read_timer;
Mike Fiore 1:e52ae6584f1c 213 std::vector<uint8_t> serial_buffer;
Mike Fiore 9:ff62b20f7000 214 std::vector<uint8_t> data;
Jason Reiss 28:c222ca8383f4 215 std::chrono::milliseconds timeout(0);
Jason Reiss 28:c222ca8383f4 216 std::chrono::milliseconds elapsed_time_ms;
Mike Fiore 1:e52ae6584f1c 217
Mike Fiore 9:ff62b20f7000 218 serial_read_timer.start();
Mike Fiore 1:e52ae6584f1c 219
Mike Fiore 9:ff62b20f7000 220 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Mike Fiore 9:ff62b20f7000 221 _xbee_on_sleep = GPIO_PIN_SET;
Mike Fiore 1:e52ae6584f1c 222
Jason Reiss 28:c222ca8383f4 223 timeout = std::chrono::milliseconds(_dot->getWakeDelay());
Jason Reiss 28:c222ca8383f4 224 elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(serial_read_timer.elapsed_time());
Mike Fiore 1:e52ae6584f1c 225
Mike Fiore 9:ff62b20f7000 226 // wait for timeout or start of serial data
Jason Reiss 28:c222ca8383f4 227 while (!readable() && elapsed_time_ms < timeout && !_serialp->escaped()) {
Jason Reiss 28:c222ca8383f4 228 ThisThread::sleep_for(2ms);
Jason Reiss 28:c222ca8383f4 229 elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(serial_read_timer.elapsed_time());
Mike Fiore 1:e52ae6584f1c 230 }
Mike Fiore 1:e52ae6584f1c 231 }
Mike Fiore 1:e52ae6584f1c 232
Mike Fiore 14:f9a77400b622 233 if (!readable() && _events->SendAck()) {
Mike Fiore 14:f9a77400b622 234 logDebug("SERIAL NOT READABLE and ACK REQUESTED");
Mike Fiore 14:f9a77400b622 235 goto L_SEND;
Mike Fiore 14:f9a77400b622 236 }
Mike Fiore 14:f9a77400b622 237
Mike Fiore 14:f9a77400b622 238 if (readable() && !_serialp->escaped()) {
Mike Fiore 6:e27eaad36a0c 239
Mike Fiore 6:e27eaad36a0c 240 serial_read_timer.reset();
Jason Reiss 28:c222ca8383f4 241 timeout = std::chrono::milliseconds(_dot->getWakeTimeout());
Jason Reiss 28:c222ca8383f4 242
Jason Reiss 28:c222ca8383f4 243 while (true) {
Jason Reiss 28:c222ca8383f4 244 elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(serial_read_timer.elapsed_time());
Jason Reiss 28:c222ca8383f4 245 if ((elapsed_time_ms >= timeout) ) {
Mike Fiore 9:ff62b20f7000 246
Jason Reiss 28:c222ca8383f4 247 break;
Jason Reiss 28:c222ca8383f4 248 }
Jason Reiss 28:c222ca8383f4 249 if (serial_buffer.size() >= _dot->getNextTxMaxSize()) {
Jason Reiss 28:c222ca8383f4 250 break;
Jason Reiss 28:c222ca8383f4 251 }
Jason Reiss 28:c222ca8383f4 252 if (_serialp->escaped()) {
Jason Reiss 28:c222ca8383f4 253 break;
Jason Reiss 28:c222ca8383f4 254 }
Jason Reiss 28:c222ca8383f4 255 if (readable()) {
Mike Fiore 1:e52ae6584f1c 256 serial_buffer.push_back(read());
Mike Fiore 1:e52ae6584f1c 257 serial_read_timer.reset();
Jason Reiss 28:c222ca8383f4 258 } else {
Jason Reiss 28:c222ca8383f4 259 ThisThread::sleep_for(5ms);
Mike Fiore 1:e52ae6584f1c 260 }
Mike Fiore 1:e52ae6584f1c 261 }
Mike Fiore 9:ff62b20f7000 262
Mike Fiore 1:e52ae6584f1c 263 serial_read_timer.stop(), serial_read_timer.reset();
Mike Fiore 1:e52ae6584f1c 264
Mike Fiore 1:e52ae6584f1c 265 if (!serial_buffer.empty()) {
Mike Fiore 9:ff62b20f7000 266 if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
Mike Fiore 14:f9a77400b622 267 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 9:ff62b20f7000 268
Mike Fiore 14:f9a77400b622 269 L_SEND:
Mike Fiore 9:ff62b20f7000 270 // wait for any duty cycle limit to expire
Mike Fiore 14:f9a77400b622 271 while (_dot->getNextTxMs() > 0 && !_serialp->escaped()) {
Jason Reiss 28:c222ca8383f4 272 ThisThread::sleep_for(10ms);
Mike Fiore 9:ff62b20f7000 273 }
Mike Fiore 9:ff62b20f7000 274
Mike Fiore 14:f9a77400b622 275 if (_dot->getIsIdle()) {
Mike Fiore 9:ff62b20f7000 276 logDebug("Received serial data, sending out radio.");
Jason Reiss 27:5fafd3b26ac3 277 if(_dot->getRxOutput() == mDot::EXTENDED || _dot->getRxOutput() == mDot::EXTENDED_HEX) {
Jason Reiss 23:4f0a981c0349 278 formatPacketSDSend(serial_buffer);
Jason Reiss 23:4f0a981c0349 279 }
Jason Reiss 28:c222ca8383f4 280
Mike Fiore 9:ff62b20f7000 281 if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 282 logDebug("Send failed.");
Mike Fiore 9:ff62b20f7000 283 // If the data should be tossed after send failure, clear buffer
Mike Fiore 9:ff62b20f7000 284 if (_dot->getSerialClearOnError()) {
Mike Fiore 9:ff62b20f7000 285 serial_buffer.clear();
Mike Fiore 9:ff62b20f7000 286 }
Mike Fiore 9:ff62b20f7000 287 } else {
Mike Fiore 1:e52ae6584f1c 288
Mike Fiore 9:ff62b20f7000 289 // wait for send to finish
Jason Reiss 27:5fafd3b26ac3 290 do {
Jason Reiss 28:c222ca8383f4 291 ThisThread::sleep_for(50ms);
Jason Reiss 27:5fafd3b26ac3 292 } while (!_dot->getIsIdle() && !_serialp->escaped());
Mike Fiore 9:ff62b20f7000 293
Mike Fiore 9:ff62b20f7000 294 // call recv to wait for any packet before sending again
Jason Reiss 23:4f0a981c0349 295 if (!_serialp->escaped()) {
Jason Reiss 23:4f0a981c0349 296 data.clear();
Mike Fiore 9:ff62b20f7000 297 _dot->recv(data);
Jason Reiss 23:4f0a981c0349 298 }
Mike Fiore 9:ff62b20f7000 299
Mike Fiore 9:ff62b20f7000 300 // Clear the serial buffer if send is success
Mike Fiore 9:ff62b20f7000 301 serial_buffer.clear();
Mike Fiore 14:f9a77400b622 302
Jason Reiss 27:5fafd3b26ac3 303 // In P2P and Class B & C mode pending data will be sent automatically without uplink
Jason Reiss 27:5fafd3b26ac3 304 if (peer_to_peer != true && _dot->getClass() == "A") {
Mike Fiore 14:f9a77400b622 305 if (_dot->getDataPending()) {
Mike Fiore 14:f9a77400b622 306 logDebug("Data is pending");
Mike Fiore 14:f9a77400b622 307 goto L_SEND;
Mike Fiore 14:f9a77400b622 308 }
Mike Fiore 14:f9a77400b622 309 if (_dot->getAckRequested()) {
Mike Fiore 14:f9a77400b622 310 logDebug("Ack requested");
Mike Fiore 14:f9a77400b622 311 goto L_SEND;
Mike Fiore 14:f9a77400b622 312 }
Jason Reiss 23:4f0a981c0349 313 if (_dot->hasMacCommands()) {
Jason Reiss 23:4f0a981c0349 314 logDebug("Pending MAC answers");
Jason Reiss 23:4f0a981c0349 315 goto L_SEND;
Jason Reiss 23:4f0a981c0349 316 }
Mike Fiore 14:f9a77400b622 317 }
Mike Fiore 9:ff62b20f7000 318 }
Mike Fiore 1:e52ae6584f1c 319 } else {
Mike Fiore 6:e27eaad36a0c 320 logDebug("Radio is busy, cannot send.\r\n");
Jason Reiss 28:c222ca8383f4 321 ThisThread::sleep_for(10ms);
Mike Fiore 1:e52ae6584f1c 322 }
Mike Fiore 1:e52ae6584f1c 323
Mike Fiore 1:e52ae6584f1c 324 } else {
Mike Fiore 6:e27eaad36a0c 325 logDebug("No data received from serial to send.\r\n");
Mike Fiore 1:e52ae6584f1c 326 }
Mike Fiore 9:ff62b20f7000 327 }
Mike Fiore 9:ff62b20f7000 328
Mike Fiore 14:f9a77400b622 329 if (!_serialp->readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serialp->escaped()) {
Mike Fiore 14:f9a77400b622 330 sleep(true);
Mike Fiore 1:e52ae6584f1c 331 }
Mike Fiore 9:ff62b20f7000 332
Mike Fiore 14:f9a77400b622 333 if (_serialp->escaped()) {
Mike Fiore 14:f9a77400b622 334 _serialp->clearEscaped();
Mike Fiore 14:f9a77400b622 335 _serialp->rxClear();
Mike Fiore 9:ff62b20f7000 336 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 337 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 338 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 339 write(done);
Mike Fiore 9:ff62b20f7000 340 return;
Mike Fiore 9:ff62b20f7000 341 }
Mike Fiore 9:ff62b20f7000 342
Mike Fiore 9:ff62b20f7000 343 if (!_dot->getNetworkJoinStatus()) {
Mike Fiore 9:ff62b20f7000 344 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 345 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 346 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 347 write(no_carrier);
Mike Fiore 9:ff62b20f7000 348 return;
Mike Fiore 9:ff62b20f7000 349 }
Mike Fiore 1:e52ae6584f1c 350 }
Mike Fiore 1:e52ae6584f1c 351
Mike Fiore 1:e52ae6584f1c 352 bool CommandTerminal::autoJoinCheck() {
Mike Fiore 1:e52ae6584f1c 353
Mike Fiore 1:e52ae6584f1c 354 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 355 int sleep = 1000;
Mike Fiore 1:e52ae6584f1c 356 Timer tmr;
Mike Fiore 9:ff62b20f7000 357 tmr.start();
Mike Fiore 1:e52ae6584f1c 358 int cnt = 0;
Mike Fiore 1:e52ae6584f1c 359
Mike Fiore 1:e52ae6584f1c 360 while (!_dot->getNetworkJoinStatus()) {
Mike Fiore 14:f9a77400b622 361 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 362 write("\r\nJoining network... ");
Mike Fiore 14:f9a77400b622 363 }
Mike Fiore 14:f9a77400b622 364 logInfo("Joining network... ");
Mike Fiore 1:e52ae6584f1c 365
Mike Fiore 9:ff62b20f7000 366 if (_dot->getNextTxMs() > 0) {
Mike Fiore 14:f9a77400b622 367 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 368 writef("\r\nWaiting %lu s before next join attempt\r\n", _dot->getNextTxMs() / 1000);
Mike Fiore 14:f9a77400b622 369 }
Mike Fiore 14:f9a77400b622 370 logInfo("Waiting %lu s before next join attempt", _dot->getNextTxMs() / 1000);
Mike Fiore 9:ff62b20f7000 371
Mike Fiore 9:ff62b20f7000 372 tmr.reset();
Mike Fiore 9:ff62b20f7000 373 while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
Mike Fiore 14:f9a77400b622 374 osDelay(20);
Mike Fiore 1:e52ae6584f1c 375 }
Mike Fiore 1:e52ae6584f1c 376 }
Mike Fiore 1:e52ae6584f1c 377
Mike Fiore 9:ff62b20f7000 378 if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
Mike Fiore 14:f9a77400b622 379 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 380 write("Network Joined\r\n");
Mike Fiore 14:f9a77400b622 381 write(done);
Mike Fiore 14:f9a77400b622 382 }
Mike Fiore 14:f9a77400b622 383 logInfo("Network Joined");
Mike Fiore 1:e52ae6584f1c 384 return false;
Mike Fiore 1:e52ae6584f1c 385 }
Mike Fiore 1:e52ae6584f1c 386
Mike Fiore 14:f9a77400b622 387 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 388 write("Network Join failed\r\n");
Mike Fiore 14:f9a77400b622 389 write(error);
Mike Fiore 14:f9a77400b622 390 }
Mike Fiore 14:f9a77400b622 391 logInfo("Network Join failed");
Mike Fiore 1:e52ae6584f1c 392
Mike Fiore 14:f9a77400b622 393 if (!_serial.escaped() && _dot->getFrequencySubBand() != 0 && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
Mike Fiore 1:e52ae6584f1c 394 cnt = 0;
Mike Fiore 1:e52ae6584f1c 395
jenkins@jenkinsdm1 16:d5cf2af81a6d 396 if (lora::ChannelPlan::IsPlanFixed(_dot->getFrequencyBand())) {
Mike Fiore 1:e52ae6584f1c 397 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
Mike Fiore 9:ff62b20f7000 398 logWarning("Join retries exhausted, switching to sub band %u", band);
Mike Fiore 1:e52ae6584f1c 399 _dot->setFrequencySubBand(band);
Mike Fiore 1:e52ae6584f1c 400 }
Mike Fiore 1:e52ae6584f1c 401 }
Mike Fiore 1:e52ae6584f1c 402
Mike Fiore 1:e52ae6584f1c 403 tmr.reset();
Mike Fiore 9:ff62b20f7000 404 while (tmr.read_ms() < sleep && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 405 osDelay(10);
Mike Fiore 1:e52ae6584f1c 406 }
Mike Fiore 1:e52ae6584f1c 407
Mike Fiore 9:ff62b20f7000 408 if (_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 409 _serial.clearEscaped();
Mike Fiore 9:ff62b20f7000 410 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 411 _mode = mDot::COMMAND_MODE;
Mike Fiore 14:f9a77400b622 412 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 413 write("Join Canceled\r\n");
Mike Fiore 14:f9a77400b622 414 write(done);
Mike Fiore 14:f9a77400b622 415 }
Mike Fiore 14:f9a77400b622 416 logInfo("Join Canceled\r\n");
Mike Fiore 9:ff62b20f7000 417 return true;
Mike Fiore 9:ff62b20f7000 418 }
Mike Fiore 1:e52ae6584f1c 419 }
Mike Fiore 1:e52ae6584f1c 420
Mike Fiore 1:e52ae6584f1c 421 return false;
Mike Fiore 1:e52ae6584f1c 422 }
Mike Fiore 1:e52ae6584f1c 423
Jason Reiss 28:c222ca8383f4 424 #define CMD_DEFS_COUNT (13)
Jason Reiss 28:c222ca8383f4 425 #define CMD_DEFS_VARIANT_SIZE (4)
Jason Reiss 28:c222ca8383f4 426 #define CMD_DEFS_LABEL_SIZE (7)
Jason Reiss 28:c222ca8383f4 427
Jason Reiss 28:c222ca8383f4 428 struct CommandDefinition {
Jason Reiss 28:c222ca8383f4 429 const char label[CMD_DEFS_LABEL_SIZE];
Jason Reiss 28:c222ca8383f4 430 const char var[CMD_DEFS_VARIANT_SIZE];
Jason Reiss 28:c222ca8383f4 431 uint8_t max_args;
Jason Reiss 28:c222ca8383f4 432 CommandFactory::CmdId_t id;
Jason Reiss 28:c222ca8383f4 433 };
Jason Reiss 28:c222ca8383f4 434
Jason Reiss 28:c222ca8383f4 435 // Table of commands handled locally
Jason Reiss 28:c222ca8383f4 436 static const CommandDefinition cmd_defs[CMD_DEFS_COUNT] = {
Jason Reiss 28:c222ca8383f4 437 {"", "", 0, CommandFactory::eAT},
Jason Reiss 28:c222ca8383f4 438 {"E", "?01", 0, CommandFactory::eATE},
Jason Reiss 28:c222ca8383f4 439 {"V", "?01", 0, CommandFactory::eATVERBOSE},
Jason Reiss 28:c222ca8383f4 440 {"&K", "?03", 0, CommandFactory::eATK},
Jason Reiss 28:c222ca8383f4 441 {"+URC", "?", 1, CommandFactory::eURC},
Jason Reiss 28:c222ca8383f4 442 {"+LW", "?", 0, CommandFactory::eLW},
Jason Reiss 28:c222ca8383f4 443 {"+SD", "?", 0, CommandFactory::eSD},
Jason Reiss 28:c222ca8383f4 444 {"&W", "", 0, CommandFactory::eATW},
Jason Reiss 28:c222ca8383f4 445 {"&WP", "", 0, CommandFactory::eATWP},
Jason Reiss 28:c222ca8383f4 446 {"+SS", "", 0, CommandFactory::eSS},
Jason Reiss 28:c222ca8383f4 447 {"+DP", "?", 0, CommandFactory::eDP},
Jason Reiss 28:c222ca8383f4 448 {"+SLEEP", "", 1, CommandFactory::eSLEEP},
Jason Reiss 28:c222ca8383f4 449 {"+MEM", "?", 0, CommandFactory::eMEM}
Jason Reiss 28:c222ca8383f4 450 };
Jason Reiss 28:c222ca8383f4 451
Jason Reiss 28:c222ca8383f4 452
Jason Reiss 28:c222ca8383f4 453
Mike Fiore 1:e52ae6584f1c 454 void CommandTerminal::start() {
Mike Fiore 1:e52ae6584f1c 455
Mike Fiore 1:e52ae6584f1c 456 char ch;
Mike Fiore 1:e52ae6584f1c 457 bool running = true;
Mike Fiore 1:e52ae6584f1c 458 bool echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 459 std::string command;
Mike Fiore 14:f9a77400b622 460 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 4:666017851052 461 std::deque<std::string> history;
Mike Fiore 4:666017851052 462 int history_index = -1;
Mike Fiore 14:f9a77400b622 463 #endif
Mike Fiore 1:e52ae6584f1c 464 std::vector<std::string> args;
Mike Fiore 9:ff62b20f7000 465 bool join_canceled = false;
Mike Fiore 1:e52ae6584f1c 466
Mike Fiore 14:f9a77400b622 467 _autoOTAEnabled = _dot->getJoinMode() == mDot::AUTO_OTA;
Mike Fiore 14:f9a77400b622 468
Mike Fiore 1:e52ae6584f1c 469 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Mike Fiore 9:ff62b20f7000 470
Mike Fiore 9:ff62b20f7000 471 serial_data_mode = true;
Mike Fiore 9:ff62b20f7000 472 _mode = mDot::SERIAL_MODE;
Mike Fiore 1:e52ae6584f1c 473
Mike Fiore 1:e52ae6584f1c 474 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 475 char ch;
Mike Fiore 1:e52ae6584f1c 476
Mike Fiore 9:ff62b20f7000 477 if (!_dot->getStandbyFlag()) {
Mike Fiore 9:ff62b20f7000 478 // wake up from power-on/reset
Mike Fiore 9:ff62b20f7000 479
Mike Fiore 9:ff62b20f7000 480 int escape_timeout = 1000;
Mike Fiore 9:ff62b20f7000 481 Timer tmr;
Mike Fiore 9:ff62b20f7000 482 Timer escape_tmr;
Mike Fiore 1:e52ae6584f1c 483
Mike Fiore 9:ff62b20f7000 484 // wait one second for possible escape by user pressing '+' key
Mike Fiore 9:ff62b20f7000 485 tmr.reset();
Mike Fiore 9:ff62b20f7000 486 tmr.start();
Mike Fiore 9:ff62b20f7000 487 escape_tmr.reset();
Mike Fiore 9:ff62b20f7000 488 escape_tmr.start();
Mike Fiore 9:ff62b20f7000 489 while (tmr.read_ms() < escape_timeout) {
Mike Fiore 9:ff62b20f7000 490 if (_serial.readable()) {
Mike Fiore 9:ff62b20f7000 491 _serial.read(&ch, 1);
Mike Fiore 9:ff62b20f7000 492 escape_buffer += ch;
Mike Fiore 9:ff62b20f7000 493 }
Mike Fiore 1:e52ae6584f1c 494
Mike Fiore 9:ff62b20f7000 495 if (escape_buffer.find("+") != std::string::npos) {
Mike Fiore 9:ff62b20f7000 496 logInfo("Escape detected");
Mike Fiore 9:ff62b20f7000 497 join_canceled = true;
Mike Fiore 9:ff62b20f7000 498 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 499 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 500 command.clear();
Mike Fiore 9:ff62b20f7000 501 break;
Mike Fiore 9:ff62b20f7000 502 }
Mike Fiore 9:ff62b20f7000 503
Mike Fiore 9:ff62b20f7000 504 if (escape_tmr.read_ms() > escape_timeout)
Mike Fiore 9:ff62b20f7000 505 escape_buffer.clear();
Mike Fiore 9:ff62b20f7000 506
Mike Fiore 9:ff62b20f7000 507 osDelay(1);
Mike Fiore 1:e52ae6584f1c 508 }
Mike Fiore 1:e52ae6584f1c 509 }
Mike Fiore 1:e52ae6584f1c 510
Mike Fiore 9:ff62b20f7000 511 if (_mode == mDot::SERIAL_MODE && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
Mike Fiore 9:ff62b20f7000 512 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 513 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 514 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 515
Mike Fiore 9:ff62b20f7000 516 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
Mike Fiore 9:ff62b20f7000 517 _serial.writef("Network Not Joined\r\n");
Mike Fiore 9:ff62b20f7000 518 _serial.writef(error);
Mike Fiore 9:ff62b20f7000 519 }
Mike Fiore 9:ff62b20f7000 520 }
Mike Fiore 1:e52ae6584f1c 521 }
Mike Fiore 1:e52ae6584f1c 522
Mike Fiore 9:ff62b20f7000 523 if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
Mike Fiore 9:ff62b20f7000 524 peer_to_peer = true;
Jason Reiss 27:5fafd3b26ac3 525 Fota::getInstance()->enable(false);
Jason Reiss 27:5fafd3b26ac3 526 CommandTerminal::Dot()->clearMacCommands();
Jason Reiss 27:5fafd3b26ac3 527 CommandTerminal::Dot()->setTxDataRate(CommandTerminal::Dot()->getTxDataRate());
Mike Fiore 9:ff62b20f7000 528 } else {
Mike Fiore 9:ff62b20f7000 529 peer_to_peer = false;
Mike Fiore 9:ff62b20f7000 530 }
Mike Fiore 1:e52ae6584f1c 531 //Run terminal session
Mike Fiore 1:e52ae6584f1c 532 while (running) {
Jason Reiss 28:c222ca8383f4 533
Jason Reiss 28:c222ca8383f4 534 if (_events != NULL && CommandTerminal::Dot()->getTestModeEnabled() && _events->PacketReceived && _events->RxPort == 224) {
Jason Reiss 28:c222ca8383f4 535 _events->handleTestModePacket();
Jason Reiss 28:c222ca8383f4 536 return;
Jason Reiss 28:c222ca8383f4 537 }
Jason Reiss 28:c222ca8383f4 538
Jason Reiss 28:c222ca8383f4 539 // wait for input to reduce at command idle current
Mike Fiore 9:ff62b20f7000 540 while (!readable() || _mode == mDot::SERIAL_MODE) {
Mike Fiore 14:f9a77400b622 541 if (!join_canceled && _autoOTAEnabled) {
Mike Fiore 9:ff62b20f7000 542 join_canceled = autoJoinCheck();
Mike Fiore 9:ff62b20f7000 543 if (join_canceled)
Mike Fiore 9:ff62b20f7000 544 command.clear();
Mike Fiore 9:ff62b20f7000 545 }
Mike Fiore 1:e52ae6584f1c 546
Mike Fiore 14:f9a77400b622 547 if (!_autoOTAEnabled || (!join_canceled && _autoOTAEnabled)) {
Mike Fiore 9:ff62b20f7000 548 switch (_mode) {
Mike Fiore 9:ff62b20f7000 549 case mDot::SERIAL_MODE:
Mike Fiore 9:ff62b20f7000 550 // signal wakeup, read serial and output to radio
Mike Fiore 9:ff62b20f7000 551 serialLoop();
Mike Fiore 9:ff62b20f7000 552 continue;
Mike Fiore 9:ff62b20f7000 553 break;
Mike Fiore 9:ff62b20f7000 554 default:
Mike Fiore 9:ff62b20f7000 555 break;
Mike Fiore 9:ff62b20f7000 556 }
Mike Fiore 1:e52ae6584f1c 557 }
Mike Fiore 9:ff62b20f7000 558
Mike Fiore 9:ff62b20f7000 559 ch = '\0';
Mike Fiore 1:e52ae6584f1c 560
Jason Reiss 27:5fafd3b26ac3 561 if (_mode != mDot::SERIAL_MODE) {
Jason Reiss 28:c222ca8383f4 562 ThisThread::sleep_for(10ms);
Jason Reiss 27:5fafd3b26ac3 563 }
Mike Fiore 9:ff62b20f7000 564 _serial.escaped();
Mike Fiore 9:ff62b20f7000 565 }
Mike Fiore 1:e52ae6584f1c 566
Mike Fiore 1:e52ae6584f1c 567 // read characters
Mike Fiore 1:e52ae6584f1c 568 if (readable()) {
Mike Fiore 1:e52ae6584f1c 569 ch = read();
Mike Fiore 1:e52ae6584f1c 570
Mike Fiore 4:666017851052 571 if (ch == '\b' || ch == 0x7f) {
Mike Fiore 1:e52ae6584f1c 572 if (!command.empty()) {
Mike Fiore 1:e52ae6584f1c 573 writef("\b \b");
Mike Fiore 1:e52ae6584f1c 574 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 575 }
Mike Fiore 1:e52ae6584f1c 576 continue;
Mike Fiore 4:666017851052 577 } else if (ch == 0x1b || ch == 0x09) {
Mike Fiore 4:666017851052 578 osDelay(20);
Mike Fiore 4:666017851052 579 // catch escape sequence, or tab
Mike Fiore 9:ff62b20f7000 580 char ch1 = 0x00, ch2 = 0x00;
Mike Fiore 4:666017851052 581
Mike Fiore 4:666017851052 582 if (readable()) {
Mike Fiore 4:666017851052 583 ch1 = read();
Mike Fiore 4:666017851052 584 if (readable())
Mike Fiore 4:666017851052 585 ch2 = read();
Mike Fiore 4:666017851052 586
Mike Fiore 14:f9a77400b622 587 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 4:666017851052 588 if (ch1 == 0x5b && ch2 == 0x41) {
Mike Fiore 4:666017851052 589 // up key
Mike Fiore 9:ff62b20f7000 590 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 591 writef("\b \b");
Mike Fiore 4:666017851052 592 }
Mike Fiore 4:666017851052 593 if (history.size() > 0) {
Mike Fiore 9:ff62b20f7000 594 if (++history_index >= int(history.size() - 1))
Mike Fiore 4:666017851052 595 history_index = history.size() - 1;
Mike Fiore 4:666017851052 596
Mike Fiore 4:666017851052 597 command = history[history_index];
Mike Fiore 4:666017851052 598 writef("%s", history[history_index].c_str());
Mike Fiore 4:666017851052 599 } else {
Mike Fiore 4:666017851052 600 command.clear();
Mike Fiore 4:666017851052 601 }
Mike Fiore 4:666017851052 602 } else if (ch1 == 0x5b && ch2 == 0x42) {
Mike Fiore 4:666017851052 603
Mike Fiore 4:666017851052 604 // down key
Mike Fiore 9:ff62b20f7000 605 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 606 writef("\b \b");
Mike Fiore 4:666017851052 607 }
Mike Fiore 4:666017851052 608
Mike Fiore 4:666017851052 609 if (--history_index < 0) {
Mike Fiore 4:666017851052 610 history_index = -1;
Mike Fiore 4:666017851052 611 command.clear();
Mike Fiore 4:666017851052 612 } else {
Mike Fiore 4:666017851052 613 command = history[history_index];
Mike Fiore 4:666017851052 614 writef("%s", history[history_index].c_str());
Mike Fiore 4:666017851052 615 }
Mike Fiore 4:666017851052 616 }
Mike Fiore 14:f9a77400b622 617 #endif
Mike Fiore 4:666017851052 618 }
Mike Fiore 9:ff62b20f7000 619 while (readable())
Mike Fiore 9:ff62b20f7000 620 read();
Mike Fiore 4:666017851052 621 continue;
Mike Fiore 1:e52ae6584f1c 622 } else {
Mike Fiore 1:e52ae6584f1c 623 command += ch;
Mike Fiore 1:e52ae6584f1c 624 }
Mike Fiore 1:e52ae6584f1c 625
Mike Fiore 1:e52ae6584f1c 626 // echo chars if enabled
Mike Fiore 1:e52ae6584f1c 627 if (echo && !(ch == '\r' || ch == '\n'))
Mike Fiore 1:e52ae6584f1c 628 writef("%c", ch);
Mike Fiore 1:e52ae6584f1c 629 }
Mike Fiore 1:e52ae6584f1c 630
Mike Fiore 1:e52ae6584f1c 631 // look for end of command line
Mike Fiore 1:e52ae6584f1c 632 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 633 // remove new line or cr character
Mike Fiore 1:e52ae6584f1c 634 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 635 write("\r"); // match standard modem output
Mike Fiore 1:e52ae6584f1c 636 write(newline);
Mike Fiore 1:e52ae6584f1c 637 } else {
Mike Fiore 1:e52ae6584f1c 638 continue;
Mike Fiore 1:e52ae6584f1c 639 }
Mike Fiore 1:e52ae6584f1c 640
Mike Fiore 1:e52ae6584f1c 641 // trim whitespace from command
Mike Fiore 1:e52ae6584f1c 642 mts::Text::trim(command, "\r\n\t ");
Mike Fiore 1:e52ae6584f1c 643
Mike Fiore 1:e52ae6584f1c 644 if (command.size() < 1) {
Mike Fiore 1:e52ae6584f1c 645 command.clear();
Mike Fiore 1:e52ae6584f1c 646 continue;
Mike Fiore 1:e52ae6584f1c 647 }
Mike Fiore 1:e52ae6584f1c 648
Jason Reiss 27:5fafd3b26ac3 649 _packet_rx_pin = 0;
Jason Reiss 27:5fafd3b26ac3 650 command_processing = true;
Jason Reiss 27:5fafd3b26ac3 651
Mike Fiore 1:e52ae6584f1c 652 // parse command and args
Mike Fiore 1:e52ae6584f1c 653 args.clear();
Mike Fiore 1:e52ae6584f1c 654
Mike Fiore 1:e52ae6584f1c 655 // find first '=' character
Mike Fiore 1:e52ae6584f1c 656 size_t delim_index = command.find("=");
Mike Fiore 1:e52ae6584f1c 657 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 658 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 659 } else {
Mike Fiore 1:e52ae6584f1c 660 // find first ' ' character
Mike Fiore 1:e52ae6584f1c 661 delim_index = command.find(" ");
Mike Fiore 1:e52ae6584f1c 662 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 663 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 664 } else {
Mike Fiore 1:e52ae6584f1c 665 args.push_back(command);
Mike Fiore 1:e52ae6584f1c 666 }
Mike Fiore 1:e52ae6584f1c 667 }
Mike Fiore 1:e52ae6584f1c 668
Mike Fiore 1:e52ae6584f1c 669 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 670 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
Mike Fiore 1:e52ae6584f1c 671 args.insert(args.end(), params.begin(), params.end());
Mike Fiore 1:e52ae6584f1c 672 }
Mike Fiore 1:e52ae6584f1c 673
Mike Fiore 1:e52ae6584f1c 674 args[0] = mts::Text::toUpper(args[0]);
Jason Reiss 28:c222ca8383f4 675 bool handled = false;
Mike Fiore 1:e52ae6584f1c 676
Mike Fiore 1:e52ae6584f1c 677 // print help
Mike Fiore 1:e52ae6584f1c 678 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
Jason Reiss 28:c222ca8383f4 679 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 680 printHelp();
Jason Reiss 28:c222ca8383f4 681 #endif
Mike Fiore 1:e52ae6584f1c 682 command.clear();
Jason Reiss 28:c222ca8383f4 683 handled = true;
Jason Reiss 28:c222ca8383f4 684 } else if (args[0].find("AT") == 0) {
Jason Reiss 28:c222ca8383f4 685 const CommandDefinition* def = NULL; // Command to handle if matched
Jason Reiss 28:c222ca8383f4 686 char variant = '\0'; // Variant character
Jason Reiss 28:c222ca8383f4 687 for (int d = 0; (d < CMD_DEFS_COUNT) && (def == NULL); ++d) {
Jason Reiss 28:c222ca8383f4 688 size_t label_size = 2 + strlen(cmd_defs[d].label);
Jason Reiss 28:c222ca8383f4 689 if (args[0].find(cmd_defs[d].label) == 2) {
Jason Reiss 28:c222ca8383f4 690 // Label found following "AT"
Jason Reiss 28:c222ca8383f4 691 for (int v = 0; v < CMD_DEFS_VARIANT_SIZE; ++v) {
Jason Reiss 28:c222ca8383f4 692 if ((args[0][label_size] == cmd_defs[d].var[v]) &&
Jason Reiss 28:c222ca8383f4 693 (args[0][label_size] == '\0' || args[0][label_size + 1] == '\0')) {
Jason Reiss 28:c222ca8383f4 694 // Check for variant characters following label, this includes a NULL
Jason Reiss 28:c222ca8383f4 695 def = &cmd_defs[d];
Jason Reiss 28:c222ca8383f4 696 variant = cmd_defs[d].var[v];
Jason Reiss 28:c222ca8383f4 697 break;
Jason Reiss 28:c222ca8383f4 698 }
Mike Fiore 14:f9a77400b622 699 }
Mike Fiore 4:666017851052 700 }
Mike Fiore 4:666017851052 701 }
Jason Reiss 28:c222ca8383f4 702 if (def != NULL) {
Jason Reiss 28:c222ca8383f4 703 handled = true;
Jason Reiss 28:c222ca8383f4 704 if (args.size() == 2 && args[1].length() == 1 && args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 705 handled = false;
Jason Reiss 28:c222ca8383f4 706 } else if (args.size() - 1 > def->max_args) {
Jason Reiss 28:c222ca8383f4 707 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 708 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 709 #endif
Jason Reiss 28:c222ca8383f4 710 write(error);
Jason Reiss 28:c222ca8383f4 711 } else {
Jason Reiss 28:c222ca8383f4 712 switch (def->id) {
Jason Reiss 28:c222ca8383f4 713 case CommandFactory::eAT:
Jason Reiss 28:c222ca8383f4 714 write(done);
Jason Reiss 28:c222ca8383f4 715 break;
Jason Reiss 28:c222ca8383f4 716 case CommandFactory::eATE:
Jason Reiss 28:c222ca8383f4 717 if (variant == '1' || variant == '0') {
Jason Reiss 28:c222ca8383f4 718 _dot->setEcho(variant == '1');
Jason Reiss 28:c222ca8383f4 719 echo = _dot->getEcho();
Jason Reiss 28:c222ca8383f4 720 } else {
Jason Reiss 28:c222ca8383f4 721 writef("%d\r\n", _dot->getEcho());
Jason Reiss 28:c222ca8383f4 722 }
Jason Reiss 28:c222ca8383f4 723 write(done);
Jason Reiss 28:c222ca8383f4 724 break;
Jason Reiss 28:c222ca8383f4 725 case CommandFactory::eATVERBOSE:
Jason Reiss 28:c222ca8383f4 726 if (variant == '1' || variant == '0') {
Jason Reiss 28:c222ca8383f4 727 _dot->setVerbose(variant == '1');
Jason Reiss 28:c222ca8383f4 728 } else {
Jason Reiss 28:c222ca8383f4 729 writef("%d\r\n", _dot->getVerbose());
Jason Reiss 28:c222ca8383f4 730 }
Jason Reiss 28:c222ca8383f4 731 write(done);
Jason Reiss 28:c222ca8383f4 732 break;
Jason Reiss 28:c222ca8383f4 733 case CommandFactory::eATK:
Jason Reiss 28:c222ca8383f4 734 if (variant == '3' || variant == '0') {
Jason Reiss 28:c222ca8383f4 735 _dot->setFlowControl(variant == '3');
Jason Reiss 28:c222ca8383f4 736 } else {
Jason Reiss 28:c222ca8383f4 737 writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
Jason Reiss 28:c222ca8383f4 738 }
Jason Reiss 28:c222ca8383f4 739 write(done);
Jason Reiss 28:c222ca8383f4 740 break;
Jason Reiss 28:c222ca8383f4 741 case CommandFactory::eURC:
Jason Reiss 28:c222ca8383f4 742 if (args.size() == 1) {
Jason Reiss 28:c222ca8383f4 743 writef("%d\r\n", urc_enabled);
Jason Reiss 28:c222ca8383f4 744 write(done);
Jason Reiss 28:c222ca8383f4 745 } else if (args[1].length() == 1) {
Jason Reiss 28:c222ca8383f4 746 if (args[1][0] != '?' && args[1][0] != '0' && args[1][0] != '1') {
Jason Reiss 28:c222ca8383f4 747 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 748 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 749 #endif
Jason Reiss 28:c222ca8383f4 750 write(error);
Jason Reiss 28:c222ca8383f4 751 } else if (args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 752 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 753 write("(0:disable,1:enable)\r\n");
Jason Reiss 28:c222ca8383f4 754 write(done);
Jason Reiss 28:c222ca8383f4 755 #else
Jason Reiss 28:c222ca8383f4 756 write(error);
Jason Reiss 28:c222ca8383f4 757 #endif
Jason Reiss 28:c222ca8383f4 758 } else {
Jason Reiss 28:c222ca8383f4 759 urc_enabled = (args[1][0] == '1');
Jason Reiss 28:c222ca8383f4 760 write(done);
Jason Reiss 28:c222ca8383f4 761 }
Jason Reiss 28:c222ca8383f4 762 } else {
Jason Reiss 28:c222ca8383f4 763 write(error);
Jason Reiss 28:c222ca8383f4 764 }
Jason Reiss 28:c222ca8383f4 765 break;
Jason Reiss 28:c222ca8383f4 766 case CommandFactory::eLW:
Jason Reiss 28:c222ca8383f4 767 writef("%s\r\n", _dot->getMACVersion());
Jason Reiss 28:c222ca8383f4 768 write(done);
Jason Reiss 28:c222ca8383f4 769 break;
Jason Reiss 28:c222ca8383f4 770 case CommandFactory::eMEM:
Jason Reiss 28:c222ca8383f4 771 free_mem();
Jason Reiss 28:c222ca8383f4 772 write(done);
Jason Reiss 28:c222ca8383f4 773 break;
Jason Reiss 28:c222ca8383f4 774 case CommandFactory::eSD:
Jason Reiss 28:c222ca8383f4 775 if (_dot->getNetworkJoinStatus()) {
Jason Reiss 28:c222ca8383f4 776 logDebug("Enter Serial Mode");
Jason Reiss 28:c222ca8383f4 777 write(connect);
Jason Reiss 28:c222ca8383f4 778 serial_data_mode = true;
Jason Reiss 28:c222ca8383f4 779 _serialp->clearEscaped();
Jason Reiss 28:c222ca8383f4 780 _mode = mDot::SERIAL_MODE;
Jason Reiss 28:c222ca8383f4 781 } else {
Jason Reiss 28:c222ca8383f4 782 logDebug("Network Not Joined");
Jason Reiss 28:c222ca8383f4 783 write("Network Not Joined\r\n");
Jason Reiss 28:c222ca8383f4 784 write(error);
Jason Reiss 28:c222ca8383f4 785 }
Jason Reiss 28:c222ca8383f4 786 break;
Jason Reiss 28:c222ca8383f4 787 case CommandFactory::eATW:
Jason Reiss 28:c222ca8383f4 788 if (!_dot->saveConfig()) {
Jason Reiss 28:c222ca8383f4 789 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 790 write("Failed to save to flash");
Jason Reiss 28:c222ca8383f4 791 #endif
Jason Reiss 28:c222ca8383f4 792 write(error);
Jason Reiss 28:c222ca8383f4 793 } else {
Jason Reiss 28:c222ca8383f4 794 write(done);
Jason Reiss 28:c222ca8383f4 795 }
Jason Reiss 28:c222ca8383f4 796 break;
Jason Reiss 28:c222ca8383f4 797 case CommandFactory::eATWP:
Jason Reiss 28:c222ca8383f4 798 if (!_dot->saveProtectedConfig()) {
Jason Reiss 28:c222ca8383f4 799 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 800 write("Failed to save to flash");
Jason Reiss 28:c222ca8383f4 801 #endif
Jason Reiss 28:c222ca8383f4 802 write(error);
Jason Reiss 28:c222ca8383f4 803 } else {
Jason Reiss 28:c222ca8383f4 804 write(done);
Jason Reiss 28:c222ca8383f4 805 }
Jason Reiss 28:c222ca8383f4 806 break;
Jason Reiss 28:c222ca8383f4 807 case CommandFactory::eSS:
Jason Reiss 28:c222ca8383f4 808 _dot->saveNetworkSession();
Jason Reiss 28:c222ca8383f4 809 write(done);
Jason Reiss 28:c222ca8383f4 810 break;
Jason Reiss 28:c222ca8383f4 811 case CommandFactory::eDP:
Jason Reiss 28:c222ca8383f4 812 writef("%d\r\n", _dot->getDataPending());
Jason Reiss 28:c222ca8383f4 813 write(done);
Jason Reiss 28:c222ca8383f4 814 break;
Jason Reiss 28:c222ca8383f4 815 case CommandFactory::eSLEEP: {
Jason Reiss 28:c222ca8383f4 816 bool temp_sleep_standby;
Jason Reiss 28:c222ca8383f4 817 bool valid = false;
Jason Reiss 28:c222ca8383f4 818 if ((args.size() > 1) && (args[1].length() == 1)) {
Jason Reiss 28:c222ca8383f4 819 if ((args[1][0] != '?' && args[1][0] != '0' && args[1][0] != '1')) {
Jason Reiss 28:c222ca8383f4 820 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 821 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 822 #endif
Jason Reiss 28:c222ca8383f4 823 write(error);
Jason Reiss 28:c222ca8383f4 824 } else if (args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 825 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 826 write("(0:deepsleep,1:sleep)\r\n");
Jason Reiss 28:c222ca8383f4 827 write(done);
Jason Reiss 28:c222ca8383f4 828 #else
Jason Reiss 28:c222ca8383f4 829 write(error);
Jason Reiss 28:c222ca8383f4 830 #endif
Jason Reiss 28:c222ca8383f4 831 } else {
Jason Reiss 28:c222ca8383f4 832 valid = true;
Jason Reiss 28:c222ca8383f4 833 temp_sleep_standby = (args[1][0] == '0');
Jason Reiss 28:c222ca8383f4 834 }
Jason Reiss 28:c222ca8383f4 835 } else if (args.size() == 1) {
Jason Reiss 28:c222ca8383f4 836 valid = true;
Jason Reiss 28:c222ca8383f4 837 temp_sleep_standby = _sleep_standby;
Jason Reiss 28:c222ca8383f4 838 } else {
Jason Reiss 28:c222ca8383f4 839 write(error);
Jason Reiss 28:c222ca8383f4 840 }
Jason Reiss 28:c222ca8383f4 841
Jason Reiss 28:c222ca8383f4 842 if (valid) {
Jason Reiss 28:c222ca8383f4 843 if (!_dot->getIsIdle()) {
Jason Reiss 28:c222ca8383f4 844 write("Dot is not idle\r\n");
Jason Reiss 28:c222ca8383f4 845 write(error);
Jason Reiss 28:c222ca8383f4 846 } else {
Jason Reiss 28:c222ca8383f4 847 _sleep_standby = temp_sleep_standby;
Jason Reiss 28:c222ca8383f4 848 #if defined(TARGET_MTS_MDOT_F411RE)
Jason Reiss 28:c222ca8383f4 849 //Read the board ID. If all 0's, it is revision B. This hardware does not support deep sleep.
Jason Reiss 28:c222ca8383f4 850 DigitalIn ID2(PC_4);
Jason Reiss 28:c222ca8383f4 851 DigitalIn ID1(PC_5);
Jason Reiss 28:c222ca8383f4 852 DigitalIn ID0(PD_2);
Jason Reiss 28:c222ca8383f4 853 if(ID2 == 0 && ID1 == 0 && ID0 == 0 && _sleep_standby == 1){
Jason Reiss 28:c222ca8383f4 854 _sleep_standby = 0;
Jason Reiss 28:c222ca8383f4 855 logWarning("This hardware version does not support deep sleep. Using sleep mode instead.");
Jason Reiss 28:c222ca8383f4 856 }
Jason Reiss 28:c222ca8383f4 857 #endif
Jason Reiss 28:c222ca8383f4 858 write(done);
Jason Reiss 28:c222ca8383f4 859 if (_dot->getBaud() < 9600)
Jason Reiss 28:c222ca8383f4 860 osDelay(20);
Jason Reiss 28:c222ca8383f4 861 else if (_dot->getBaud() > 57600)
Jason Reiss 28:c222ca8383f4 862 osDelay(2);
Jason Reiss 28:c222ca8383f4 863 else
Jason Reiss 28:c222ca8383f4 864 osDelay(5);
Jason Reiss 28:c222ca8383f4 865 this->sleep(_sleep_standby);
Jason Reiss 28:c222ca8383f4 866 osDelay(1);
Jason Reiss 28:c222ca8383f4 867 }
Jason Reiss 28:c222ca8383f4 868 }
Jason Reiss 28:c222ca8383f4 869 break;
Jason Reiss 28:c222ca8383f4 870 }
Jason Reiss 28:c222ca8383f4 871 default:
Jason Reiss 28:c222ca8383f4 872 handled = false;
Jason Reiss 28:c222ca8383f4 873 // Unhandled command
Jason Reiss 28:c222ca8383f4 874 // Will only reach here if the table contains commands that do not have explicit cases
Jason Reiss 28:c222ca8383f4 875 break;
Jason Reiss 28:c222ca8383f4 876 }
Jason Reiss 28:c222ca8383f4 877 }
Jason Reiss 28:c222ca8383f4 878 #ifdef MTS_RADIO_DEBUG_COMMANDS
Jason Reiss 28:c222ca8383f4 879 } else if (args[0].find("AT+TM!") == 0 && args[0].length() == 6) {
Jason Reiss 28:c222ca8383f4 880 handled = true;
Jason Reiss 28:c222ca8383f4 881 if ((args.size() > 1) && (args[1].length() == 1)) {
Jason Reiss 28:c222ca8383f4 882 if (args[1][0] == '0' || args[1][0] == '1') {
Jason Reiss 28:c222ca8383f4 883 _dot->setTestModeEnabled(args[1][0] == '1');
Jason Reiss 28:c222ca8383f4 884 write(done);
Jason Reiss 28:c222ca8383f4 885 } else {
Jason Reiss 28:c222ca8383f4 886 write(error);
Jason Reiss 28:c222ca8383f4 887 }
Jason Reiss 28:c222ca8383f4 888 } else {
Jason Reiss 28:c222ca8383f4 889 writef("%d\r\n", _dot->getTestModeEnabled());
Jason Reiss 28:c222ca8383f4 890 write(done);
Jason Reiss 28:c222ca8383f4 891 }
Jason Reiss 28:c222ca8383f4 892 #endif
Jason Reiss 28:c222ca8383f4 893 }
Jason Reiss 28:c222ca8383f4 894 }
Jason Reiss 28:c222ca8383f4 895
Jason Reiss 28:c222ca8383f4 896 if (!handled) {
Mike Fiore 1:e52ae6584f1c 897 bool found = false;
Mike Fiore 1:e52ae6584f1c 898 bool query = false;
Mike Fiore 1:e52ae6584f1c 899
Mike Fiore 1:e52ae6584f1c 900 std::string lookfor = args[0];
Mike Fiore 1:e52ae6584f1c 901
Jason Reiss 28:c222ca8383f4 902 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 903 // per command help
Jason Reiss 28:c222ca8383f4 904 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) {
Mike Fiore 1:e52ae6584f1c 905 lookfor = mts::Text::toUpper(args[1]);
Jason Reiss 28:c222ca8383f4 906 }
Jason Reiss 28:c222ca8383f4 907 #endif
Mike Fiore 1:e52ae6584f1c 908 // trim off any trailing '?' and mark as a query command
Mike Fiore 1:e52ae6584f1c 909 if (args[0].rfind("?") == args[0].length() - 1) {
Mike Fiore 1:e52ae6584f1c 910 query = true;
Mike Fiore 1:e52ae6584f1c 911 lookfor = args[0].substr(0, args[0].length() - 1);
Mike Fiore 1:e52ae6584f1c 912 }
Mike Fiore 1:e52ae6584f1c 913
Mike Fiore 1:e52ae6584f1c 914 // search for command
jenkins@jenkinsdm1 18:63f098f042b2 915 Command *cmd = NULL;
Jason Reiss 27:5fafd3b26ac3 916 for (int i = 0; i < CommandFactory::NUMBER_OF_CMDS; i++) {
Jason Reiss 27:5fafd3b26ac3 917 cmd = CommandFactory::Create(static_cast<CommandFactory::CmdId_t>(i));
Mike Fiore 1:e52ae6584f1c 918
Mike Fiore 1:e52ae6584f1c 919 // match CMD or CMD? syntax if command is queryable
jenkins@jenkinsdm1 18:63f098f042b2 920 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
Mike Fiore 1:e52ae6584f1c 921 found = true;
Jason Reiss 28:c222ca8383f4 922 _errorMessage.clear();
Jason Reiss 28:c222ca8383f4 923 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 924 if (args[0] == "HELP") {
jenkins@jenkinsdm1 18:63f098f042b2 925 writef("%s%s", cmd->help().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 926 write(done);
Mike Fiore 1:e52ae6584f1c 927 }
Mike Fiore 1:e52ae6584f1c 928 else if (args.size() > 1 && args[1] == "?") {
jenkins@jenkinsdm1 18:63f098f042b2 929 writef("%s%s", cmd->usage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 930 write(done);
jenkins@jenkinsdm1 18:63f098f042b2 931 } else if (!cmd->verify(args)) {
Jason Reiss 28:c222ca8383f4 932 #else
Jason Reiss 28:c222ca8383f4 933 if (args.size() > 1 && args[1] == "?") {
Jason Reiss 28:c222ca8383f4 934 write(error);
Jason Reiss 28:c222ca8383f4 935 } else if (!cmd->verify(args)) {
Jason Reiss 28:c222ca8383f4 936 #endif
Jason Reiss 28:c222ca8383f4 937 if (!_errorMessage.empty()) {
Jason Reiss 28:c222ca8383f4 938 writef("%s%s", _errorMessage.c_str(), newline);
Jason Reiss 28:c222ca8383f4 939 }
Jason Reiss 28:c222ca8383f4 940 write(error);
Mike Fiore 1:e52ae6584f1c 941 } else {
Jason Reiss 28:c222ca8383f4 942 _errorMessage.clear();
jenkins@jenkinsdm1 18:63f098f042b2 943 if (cmd->action(args) == 0) {
Mike Fiore 1:e52ae6584f1c 944 writef("%s", done);
Mike Fiore 1:e52ae6584f1c 945 } else {
Jason Reiss 28:c222ca8383f4 946 // Action was not successful
Jason Reiss 28:c222ca8383f4 947 if (_errorMessage.empty()) {
Jason Reiss 28:c222ca8383f4 948 // If no error message was set, check for error recorded in mdot
Jason Reiss 28:c222ca8383f4 949 std::string dot_error = _dot->getLastError();
Jason Reiss 28:c222ca8383f4 950 if (!dot_error.empty()) {
Jason Reiss 28:c222ca8383f4 951 writef("%s%s", dot_error.c_str(), newline);
Jason Reiss 28:c222ca8383f4 952 }
Jason Reiss 28:c222ca8383f4 953 } else {
Jason Reiss 28:c222ca8383f4 954 // Command set an error message
Jason Reiss 28:c222ca8383f4 955 writef("%s%s", _errorMessage.c_str(), newline);
Jason Reiss 28:c222ca8383f4 956 }
Jason Reiss 28:c222ca8383f4 957 write(error);
Mike Fiore 1:e52ae6584f1c 958 }
Mike Fiore 1:e52ae6584f1c 959 }
Mike Fiore 1:e52ae6584f1c 960 }
jenkins@jenkinsdm1 18:63f098f042b2 961
jenkins@jenkinsdm1 18:63f098f042b2 962 delete cmd;
Jason Reiss 28:c222ca8383f4 963
Jason Reiss 28:c222ca8383f4 964 if (found) {
Jason Reiss 28:c222ca8383f4 965 break;
Jason Reiss 28:c222ca8383f4 966 }
Mike Fiore 1:e52ae6584f1c 967 }
Mike Fiore 1:e52ae6584f1c 968
Mike Fiore 1:e52ae6584f1c 969 if (!found) {
Jason Reiss 28:c222ca8383f4 970 write(command_error);
Jason Reiss 28:c222ca8383f4 971 write(error);
Mike Fiore 1:e52ae6584f1c 972 }
Mike Fiore 1:e52ae6584f1c 973 }
Mike Fiore 1:e52ae6584f1c 974
Jason Reiss 28:c222ca8383f4 975
Jason Reiss 27:5fafd3b26ac3 976 _join_status_pin = CommandTerminal::Dot()->getNetworkJoinStatus();
Jason Reiss 27:5fafd3b26ac3 977 command_processing = false;
Jason Reiss 27:5fafd3b26ac3 978
Jason Reiss 27:5fafd3b26ac3 979
Mike Fiore 14:f9a77400b622 980 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 4:666017851052 981 if (history.size() == 0 || history.front() != command)
Mike Fiore 4:666017851052 982 history.push_front(command);
Mike Fiore 4:666017851052 983 history_index = -1;
Mike Fiore 1:e52ae6584f1c 984 command.clear();
Mike Fiore 1:e52ae6584f1c 985
Mike Fiore 4:666017851052 986 while (history.size() > 10)
Mike Fiore 4:666017851052 987 history.pop_back();
Mike Fiore 14:f9a77400b622 988 #else
Mike Fiore 14:f9a77400b622 989 command.clear();
Mike Fiore 14:f9a77400b622 990 #endif
Mike Fiore 1:e52ae6584f1c 991 }
Mike Fiore 1:e52ae6584f1c 992 }
Mike Fiore 1:e52ae6584f1c 993
Mike Fiore 1:e52ae6584f1c 994 void CommandTerminal::sleep(bool standby) {
Mike Fiore 1:e52ae6584f1c 995 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 1:e52ae6584f1c 996
Mike Fiore 4:666017851052 997 _serial.rxClear();
Mike Fiore 4:666017851052 998 _serial.txClear();
Mike Fiore 1:e52ae6584f1c 999
Mike Fiore 14:f9a77400b622 1000 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 14:f9a77400b622 1001 xdot_save_gpio_state();
Mike Fiore 14:f9a77400b622 1002
Mike Fiore 14:f9a77400b622 1003 /* GPIO Ports Clock Enable */
Mike Fiore 14:f9a77400b622 1004 __GPIOA_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 1005 __GPIOB_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 1006 __GPIOC_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 1007 __GPIOH_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 1008
Mike Fiore 14:f9a77400b622 1009 GPIO_InitTypeDef GPIO_InitStruct;
Mike Fiore 14:f9a77400b622 1010
Mike Fiore 14:f9a77400b622 1011 // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
Mike Fiore 14:f9a77400b622 1012 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
Mike Fiore 14:f9a77400b622 1013 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1014 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1015 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1016
Mike Fiore 14:f9a77400b622 1017 // I2C_SDA & I2C_SCL to analog nopull
Mike Fiore 14:f9a77400b622 1018 GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
Mike Fiore 14:f9a77400b622 1019 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1020 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1021 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1022
Mike Fiore 14:f9a77400b622 1023 // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
Mike Fiore 14:f9a77400b622 1024 GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
Mike Fiore 14:f9a77400b622 1025 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1026 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1027 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1028
Mike Fiore 14:f9a77400b622 1029 // iterate through potential wake pins - leave the configured wake pin alone if one is needed
Mike Fiore 14:f9a77400b622 1030 if (_dot->getWakePin() != WAKE || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1031 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 14:f9a77400b622 1032 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1033 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1034 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1035 }
Mike Fiore 14:f9a77400b622 1036 if (_dot->getWakePin() != GPIO0 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1037 GPIO_InitStruct.Pin = GPIO_PIN_4;
Mike Fiore 14:f9a77400b622 1038 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1039 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1040 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1041 }
Mike Fiore 14:f9a77400b622 1042 if (_dot->getWakePin() != GPIO1 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1043 GPIO_InitStruct.Pin = GPIO_PIN_5;
Mike Fiore 14:f9a77400b622 1044 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1045 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1046 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1047 }
Mike Fiore 14:f9a77400b622 1048 if (_dot->getWakePin() != GPIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1049 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 14:f9a77400b622 1050 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1051 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1052 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1053 }
Mike Fiore 14:f9a77400b622 1054 if (_dot->getWakePin() != GPIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1055 GPIO_InitStruct.Pin = GPIO_PIN_2;
Mike Fiore 14:f9a77400b622 1056 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1057 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1058 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1059 }
Mike Fiore 14:f9a77400b622 1060 if (_dot->getWakePin() != UART1_RX || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1061 GPIO_InitStruct.Pin = GPIO_PIN_10;
Mike Fiore 14:f9a77400b622 1062 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1063 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1064 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1065 }
Mike Fiore 14:f9a77400b622 1066 #else
Mike Fiore 14:f9a77400b622 1067 uint32_t portA[6];
Mike Fiore 14:f9a77400b622 1068 uint32_t portB[6];
Mike Fiore 14:f9a77400b622 1069 uint32_t portC[6];
Mike Fiore 14:f9a77400b622 1070 uint32_t portD[6];
Mike Fiore 14:f9a77400b622 1071 uint32_t portH[6];
Mike Fiore 14:f9a77400b622 1072
Mike Fiore 14:f9a77400b622 1073 //Save the GPIO state.
Mike Fiore 14:f9a77400b622 1074 portA[0] = GPIOA->MODER;
Mike Fiore 14:f9a77400b622 1075 portA[1] = GPIOA->OTYPER;
Mike Fiore 14:f9a77400b622 1076 portA[2] = GPIOA->OSPEEDR;
Mike Fiore 14:f9a77400b622 1077 portA[3] = GPIOA->PUPDR;
Mike Fiore 14:f9a77400b622 1078 portA[4] = GPIOA->AFR[0];
Mike Fiore 14:f9a77400b622 1079 portA[5] = GPIOA->AFR[1];
Mike Fiore 14:f9a77400b622 1080
Mike Fiore 14:f9a77400b622 1081 portB[0] = GPIOB->MODER;
Mike Fiore 14:f9a77400b622 1082 portB[1] = GPIOB->OTYPER;
Mike Fiore 14:f9a77400b622 1083 portB[2] = GPIOB->OSPEEDR;
Mike Fiore 14:f9a77400b622 1084 portB[3] = GPIOB->PUPDR;
Mike Fiore 14:f9a77400b622 1085 portB[4] = GPIOB->AFR[0];
Mike Fiore 14:f9a77400b622 1086 portB[5] = GPIOB->AFR[1];
Mike Fiore 14:f9a77400b622 1087
Mike Fiore 14:f9a77400b622 1088 portC[0] = GPIOC->MODER;
Mike Fiore 14:f9a77400b622 1089 portC[1] = GPIOC->OTYPER;
Mike Fiore 14:f9a77400b622 1090 portC[2] = GPIOC->OSPEEDR;
Mike Fiore 14:f9a77400b622 1091 portC[3] = GPIOC->PUPDR;
Mike Fiore 14:f9a77400b622 1092 portC[4] = GPIOC->AFR[0];
Mike Fiore 14:f9a77400b622 1093 portC[5] = GPIOC->AFR[1];
Mike Fiore 14:f9a77400b622 1094
Mike Fiore 14:f9a77400b622 1095 portD[0] = GPIOD->MODER;
Mike Fiore 14:f9a77400b622 1096 portD[1] = GPIOD->OTYPER;
Mike Fiore 14:f9a77400b622 1097 portD[2] = GPIOD->OSPEEDR;
Mike Fiore 14:f9a77400b622 1098 portD[3] = GPIOD->PUPDR;
Mike Fiore 14:f9a77400b622 1099 portD[4] = GPIOD->AFR[0];
Mike Fiore 14:f9a77400b622 1100 portD[5] = GPIOD->AFR[1];
Mike Fiore 14:f9a77400b622 1101
Mike Fiore 14:f9a77400b622 1102 portH[0] = GPIOH->MODER;
Mike Fiore 14:f9a77400b622 1103 portH[1] = GPIOH->OTYPER;
Mike Fiore 14:f9a77400b622 1104 portH[2] = GPIOH->OSPEEDR;
Mike Fiore 14:f9a77400b622 1105 portH[3] = GPIOH->PUPDR;
Mike Fiore 14:f9a77400b622 1106 portH[4] = GPIOH->AFR[0];
Mike Fiore 14:f9a77400b622 1107 portH[5] = GPIOH->AFR[1];
Mike Fiore 14:f9a77400b622 1108
Mike Fiore 14:f9a77400b622 1109 /* GPIO Ports Clock Enable */
Mike Fiore 14:f9a77400b622 1110 __GPIOA_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 1111 __GPIOB_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 1112 __GPIOC_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 1113
Mike Fiore 14:f9a77400b622 1114 GPIO_InitTypeDef GPIO_InitStruct;
Mike Fiore 14:f9a77400b622 1115
Mike Fiore 14:f9a77400b622 1116 // Set port A pins to analog nopull
Jason Reiss 23:4f0a981c0349 1117 GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10
Mike Fiore 14:f9a77400b622 1118 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
Mike Fiore 14:f9a77400b622 1119 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1120 GPIO_InitStruct.Pull = GPIO_NOPULL;
Jason Reiss 23:4f0a981c0349 1121 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1122
Mike Fiore 14:f9a77400b622 1123 // Set port B pins to analog nopull
Mike Fiore 14:f9a77400b622 1124 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
Mike Fiore 14:f9a77400b622 1125 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1126 GPIO_InitStruct.Pull = GPIO_NOPULL;
Jason Reiss 23:4f0a981c0349 1127 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1128
Mike Fiore 14:f9a77400b622 1129 // Set port C pins to analog nopull
Mike Fiore 14:f9a77400b622 1130 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
Mike Fiore 14:f9a77400b622 1131 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1132 GPIO_InitStruct.Pull = GPIO_NOPULL;
Jason Reiss 23:4f0a981c0349 1133 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1134
Mike Fiore 14:f9a77400b622 1135 // iterate through potential wake pins - leave the configured wake pin alone if one is needed
Mike Fiore 14:f9a77400b622 1136 // XBEE_DIN - PA3
Mike Fiore 14:f9a77400b622 1137 // XBEE_DIO2 - PA5
Mike Fiore 14:f9a77400b622 1138 // XBEE_DIO3 - PA4
Mike Fiore 14:f9a77400b622 1139 // XBEE_DIO4 - PA7
Mike Fiore 14:f9a77400b622 1140 // XBEE_DIO5 - PC1
Mike Fiore 14:f9a77400b622 1141 // XBEE_DIO6 - PA1
Mike Fiore 14:f9a77400b622 1142 // XBEE_DIO7 - PA0
Mike Fiore 14:f9a77400b622 1143 // XBEE_SLEEPRQ - PA11
Jason Reiss 23:4f0a981c0349 1144
Mike Fiore 14:f9a77400b622 1145 if (_dot->getWakePin() != XBEE_DIN || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1146 GPIO_InitStruct.Pin = GPIO_PIN_3;
Mike Fiore 14:f9a77400b622 1147 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1148 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1149 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1150 }
Mike Fiore 14:f9a77400b622 1151
Mike Fiore 14:f9a77400b622 1152 if (_dot->getWakePin() != XBEE_DIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1153 GPIO_InitStruct.Pin = GPIO_PIN_5;
Mike Fiore 14:f9a77400b622 1154 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1155 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1156 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1157 }
Mike Fiore 14:f9a77400b622 1158
Mike Fiore 14:f9a77400b622 1159 if (_dot->getWakePin() != XBEE_DIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1160 GPIO_InitStruct.Pin = GPIO_PIN_4;
Mike Fiore 14:f9a77400b622 1161 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1162 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1163 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1164 }
Mike Fiore 14:f9a77400b622 1165
Mike Fiore 14:f9a77400b622 1166 if (_dot->getWakePin() != XBEE_DIO4 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1167 GPIO_InitStruct.Pin = GPIO_PIN_7;
Mike Fiore 14:f9a77400b622 1168 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1169 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1170 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1171 }
Mike Fiore 14:f9a77400b622 1172
Mike Fiore 14:f9a77400b622 1173 if (_dot->getWakePin() != XBEE_DIO5 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1174 GPIO_InitStruct.Pin = GPIO_PIN_1;
Mike Fiore 14:f9a77400b622 1175 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1176 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1177 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1178 }
Mike Fiore 14:f9a77400b622 1179
Mike Fiore 14:f9a77400b622 1180 if (_dot->getWakePin() != XBEE_DIO6 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1181 GPIO_InitStruct.Pin = GPIO_PIN_1;
Mike Fiore 14:f9a77400b622 1182 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1183 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1184 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1185 }
Mike Fiore 14:f9a77400b622 1186
Mike Fiore 14:f9a77400b622 1187 if (_dot->getWakePin() != XBEE_DIO7 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1188 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 14:f9a77400b622 1189 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1190 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1191 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1192 }
Mike Fiore 14:f9a77400b622 1193
Mike Fiore 14:f9a77400b622 1194 if (_dot->getWakePin() != XBEE_SLEEPRQ|| _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 1195 GPIO_InitStruct.Pin = GPIO_PIN_11;
Mike Fiore 14:f9a77400b622 1196 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 1197 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 1198 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 1199 }
Jason Reiss 23:4f0a981c0349 1200
Mike Fiore 14:f9a77400b622 1201 #endif
Mike Fiore 4:666017851052 1202 _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
Mike Fiore 14:f9a77400b622 1203
Mike Fiore 14:f9a77400b622 1204 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 14:f9a77400b622 1205 xdot_restore_gpio_state();
Mike Fiore 14:f9a77400b622 1206 #else
Mike Fiore 14:f9a77400b622 1207 //Restore the GPIO state.
Mike Fiore 14:f9a77400b622 1208 GPIOA->MODER = portA[0];
Mike Fiore 14:f9a77400b622 1209 GPIOA->OTYPER = portA[1];
Mike Fiore 14:f9a77400b622 1210 GPIOA->OSPEEDR = portA[2];
Mike Fiore 14:f9a77400b622 1211 GPIOA->PUPDR = portA[3];
Mike Fiore 14:f9a77400b622 1212 GPIOA->AFR[0] = portA[4];
Mike Fiore 14:f9a77400b622 1213 GPIOA->AFR[1] = portA[5];
Mike Fiore 14:f9a77400b622 1214
Mike Fiore 14:f9a77400b622 1215 GPIOB->MODER = portB[0];
Mike Fiore 14:f9a77400b622 1216 GPIOB->OTYPER = portB[1];
Mike Fiore 14:f9a77400b622 1217 GPIOB->OSPEEDR = portB[2];
Mike Fiore 14:f9a77400b622 1218 GPIOB->PUPDR = portB[3];
Mike Fiore 14:f9a77400b622 1219 GPIOB->AFR[0] = portB[4];
Mike Fiore 14:f9a77400b622 1220 GPIOB->AFR[1] = portB[5];
Mike Fiore 14:f9a77400b622 1221
Mike Fiore 14:f9a77400b622 1222 GPIOC->MODER = portC[0];
Mike Fiore 14:f9a77400b622 1223 GPIOC->OTYPER = portC[1];
Mike Fiore 14:f9a77400b622 1224 GPIOC->OSPEEDR = portC[2];
Mike Fiore 14:f9a77400b622 1225 GPIOC->PUPDR = portC[3];
Mike Fiore 14:f9a77400b622 1226 GPIOC->AFR[0] = portC[4];
Mike Fiore 14:f9a77400b622 1227 GPIOC->AFR[1] = portC[5];
Mike Fiore 14:f9a77400b622 1228
Mike Fiore 14:f9a77400b622 1229 GPIOD->MODER = portD[0];
Mike Fiore 14:f9a77400b622 1230 GPIOD->OTYPER = portD[1];
Mike Fiore 14:f9a77400b622 1231 GPIOD->OSPEEDR = portD[2];
Mike Fiore 14:f9a77400b622 1232 GPIOD->PUPDR = portD[3];
Mike Fiore 14:f9a77400b622 1233 GPIOD->AFR[0] = portD[4];
Mike Fiore 14:f9a77400b622 1234 GPIOD->AFR[1] = portD[5];
Mike Fiore 14:f9a77400b622 1235
Mike Fiore 14:f9a77400b622 1236 GPIOH->MODER = portH[0];
Mike Fiore 14:f9a77400b622 1237 GPIOH->OTYPER = portH[1];
Mike Fiore 14:f9a77400b622 1238 GPIOH->OSPEEDR = portH[2];
Mike Fiore 14:f9a77400b622 1239 GPIOH->PUPDR = portH[3];
Mike Fiore 14:f9a77400b622 1240 GPIOH->AFR[0] = portH[4];
Mike Fiore 14:f9a77400b622 1241 GPIOH->AFR[1] = portH[5];
Mike Fiore 14:f9a77400b622 1242 #endif
Mike Fiore 14:f9a77400b622 1243
Mike Fiore 14:f9a77400b622 1244 _serial.rxClear();
Mike Fiore 14:f9a77400b622 1245 _serial.txClear();
Jason Reiss 23:4f0a981c0349 1246 Fota::getInstance()->fixEventQueue();
Mike Fiore 14:f9a77400b622 1247 }
Mike Fiore 14:f9a77400b622 1248
Mike Fiore 14:f9a77400b622 1249 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
Jason Reiss 23:4f0a981c0349 1250 switch(format) {
Jason Reiss 23:4f0a981c0349 1251 case(mDot::HEXADECIMAL):
Jason Reiss 23:4f0a981c0349 1252 return mts::Text::bin2hexString(data);
Jason Reiss 23:4f0a981c0349 1253
Jason Reiss 23:4f0a981c0349 1254 case(mDot::BINARY):
Jason Reiss 23:4f0a981c0349 1255 return std::string(data.begin(), data.end());
Jason Reiss 23:4f0a981c0349 1256
Jason Reiss 23:4f0a981c0349 1257 case(mDot::EXTENDED):
Jason Reiss 27:5fafd3b26ac3 1258 return formatPacket(data, false);
Jason Reiss 27:5fafd3b26ac3 1259
Jason Reiss 27:5fafd3b26ac3 1260 case(mDot::EXTENDED_HEX):
Jason Reiss 27:5fafd3b26ac3 1261 return formatPacket(data, true);
Jason Reiss 23:4f0a981c0349 1262
Jason Reiss 23:4f0a981c0349 1263 default:
Jason Reiss 23:4f0a981c0349 1264 return "";
Jason Reiss 23:4f0a981c0349 1265 }
Mike Fiore 1:e52ae6584f1c 1266 }
Mike Fiore 1:e52ae6584f1c 1267
Mike Fiore 1:e52ae6584f1c 1268 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
Mike Fiore 1:e52ae6584f1c 1269 Timer timer;
Mike Fiore 1:e52ae6584f1c 1270
Mike Fiore 1:e52ae6584f1c 1271 timer.start();
Mike Fiore 1:e52ae6584f1c 1272 while (timer.read_ms() < timeout) {
Mike Fiore 1:e52ae6584f1c 1273
Mike Fiore 1:e52ae6584f1c 1274 if (dot != NULL) {
Mike Fiore 1:e52ae6584f1c 1275 if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
Mike Fiore 1:e52ae6584f1c 1276 return false;
Mike Fiore 1:e52ae6584f1c 1277 }
Mike Fiore 1:e52ae6584f1c 1278 }
Mike Fiore 1:e52ae6584f1c 1279
Mike Fiore 9:ff62b20f7000 1280 if (_serialp != NULL && _serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 1281 _serialp->clearEscaped();
Mike Fiore 9:ff62b20f7000 1282 return true;
Mike Fiore 1:e52ae6584f1c 1283 }
Mike Fiore 1:e52ae6584f1c 1284
Mike Fiore 1:e52ae6584f1c 1285 osDelay(10);
Mike Fiore 1:e52ae6584f1c 1286 }
Mike Fiore 1:e52ae6584f1c 1287
Mike Fiore 1:e52ae6584f1c 1288 return false;
Mike Fiore 1:e52ae6584f1c 1289 }
Mike Fiore 1:e52ae6584f1c 1290
Mike Fiore 9:ff62b20f7000 1291 void CommandTerminal::wakeup(void) {
Mike Fiore 9:ff62b20f7000 1292 }
Mike Fiore 9:ff62b20f7000 1293
Jason Reiss 27:5fafd3b26ac3 1294 void CommandTerminal::RadioEvent::RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int16_t snr, lora::DownlinkControl ctrl, uint8_t slot) {
Jason Reiss 27:5fafd3b26ac3 1295 mDotEvent::RxDone(payload, size, rssi, snr, ctrl, slot);
Jason Reiss 27:5fafd3b26ac3 1296 logDebug("RadioEvent - RxDone");
Jason Reiss 27:5fafd3b26ac3 1297 }
Jason Reiss 27:5fafd3b26ac3 1298
Jason Reiss 27:5fafd3b26ac3 1299 void CommandTerminal::RadioEvent::RxTimeout(uint8_t slot) {
Jason Reiss 27:5fafd3b26ac3 1300 mDotEvent::RxTimeout(slot);
Jason Reiss 27:5fafd3b26ac3 1301 _packet_rx_pin = 0;
Jason Reiss 27:5fafd3b26ac3 1302 }
Jason Reiss 27:5fafd3b26ac3 1303
Jason Reiss 28:c222ca8383f4 1304 void CommandTerminal::RadioEvent::PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int16_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries, uint32_t address, uint32_t fcnt, bool dupRx) {
Jason Reiss 28:c222ca8383f4 1305 mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, slot, retries, address, fcnt, dupRx);
Jason Reiss 27:5fafd3b26ac3 1306 _rxAddress = address;
Jason Reiss 28:c222ca8383f4 1307 _rxFcnt = fcnt;
Jason Reiss 27:5fafd3b26ac3 1308
jenkins@jenkinsdm1 18:63f098f042b2 1309 if(port == 200 || port == 201 || port == 202) {
Jason Reiss 23:4f0a981c0349 1310 Fota::getInstance()->processCmd(payload, port, size);
Jason Reiss 27:5fafd3b26ac3 1311 if (CommandTerminal::Dot()->getRxOutput() < mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1312 return;
Jason Reiss 27:5fafd3b26ac3 1313 }
jenkins@jenkinsdm1 18:63f098f042b2 1314 }
Jason Reiss 27:5fafd3b26ac3 1315
Jason Reiss 27:5fafd3b26ac3 1316 _packet_rx_pin = 1;
Jason Reiss 27:5fafd3b26ac3 1317
jenkins@jenkinsdm1 18:63f098f042b2 1318 if (serial_data_mode && port != 0) {
Mike Fiore 14:f9a77400b622 1319 if (size > 0) {
Jason Reiss 27:5fafd3b26ac3 1320 while (!CommandTerminal::Serial()->writeable()) ;
Jason Reiss 27:5fafd3b26ac3 1321 if (CommandTerminal::Dot()->getRxOutput() >= mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1322 formatPacket(RxPayload, size, CommandTerminal::Dot()->getRxOutput() == mDot::EXTENDED_HEX);
Jason Reiss 23:4f0a981c0349 1323 } else {
Jason Reiss 23:4f0a981c0349 1324 CommandTerminal::Serial()->write((char*) RxPayload, RxPayloadSize);
Jason Reiss 23:4f0a981c0349 1325 }
Mike Fiore 9:ff62b20f7000 1326 }
Jason Reiss 23:4f0a981c0349 1327 if (!CommandTerminal::Serial()->readable()
Jason Reiss 23:4f0a981c0349 1328 && (_dot->getAckRequested()
Jason Reiss 27:5fafd3b26ac3 1329 || (peer_to_peer == false && _dot->hasMacCommands()))
Jason Reiss 27:5fafd3b26ac3 1330 && (peer_to_peer || _dot->getClass() == "C" || _dot->getSettings()->Session.Class == lora::CLASS_B)) {
Mike Fiore 14:f9a77400b622 1331 _sendAck = true;
Mike Fiore 9:ff62b20f7000 1332 }
Jason Reiss 27:5fafd3b26ac3 1333 } else if (urc_enabled) {
Jason Reiss 27:5fafd3b26ac3 1334 if (!command_processing) {
Jason Reiss 27:5fafd3b26ac3 1335 while (!CommandTerminal::Serial()->writeable()) ;
Jason Reiss 27:5fafd3b26ac3 1336 if (CommandTerminal::Dot()->getRxOutput() >= mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1337 formatPacket(RxPayload, size, CommandTerminal::Dot()->getRxOutput() == mDot::EXTENDED_HEX);
Jason Reiss 27:5fafd3b26ac3 1338 } else {
Jason Reiss 28:c222ca8383f4 1339 CommandTerminal::Serial()->write("RECV\r\n", 6);
Jason Reiss 27:5fafd3b26ac3 1340 }
Jason Reiss 27:5fafd3b26ac3 1341 }
Mike Fiore 9:ff62b20f7000 1342 }
Mike Fiore 1:e52ae6584f1c 1343 }
Mike Fiore 9:ff62b20f7000 1344
Jason Reiss 28:c222ca8383f4 1345 void CommandTerminal::RadioEvent::handleTestModePacket() {
Jason Reiss 28:c222ca8383f4 1346 #ifdef MTS_RADIO_DEBUG_COMMANDS
Jason Reiss 28:c222ca8383f4 1347 static uint32_t last_rx_seq = 0;
Jason Reiss 28:c222ca8383f4 1348 bool start_test = false;
Jason Reiss 28:c222ca8383f4 1349
Jason Reiss 28:c222ca8383f4 1350 std::string packet = mts::Text::bin2hexString(RxPayload, RxPayloadSize);
Jason Reiss 28:c222ca8383f4 1351
Jason Reiss 28:c222ca8383f4 1352 start_test = RxPayloadSize == 4;
Jason Reiss 28:c222ca8383f4 1353 start_test = start_test && (RxPayload[0] == 0x01);
Jason Reiss 28:c222ca8383f4 1354 start_test = start_test && (RxPayload[1] == 0x01);
Jason Reiss 28:c222ca8383f4 1355 start_test = start_test && (RxPayload[2] == 0x01);
Jason Reiss 28:c222ca8383f4 1356 start_test = start_test && (RxPayload[3] == 0x01);
Jason Reiss 28:c222ca8383f4 1357
Jason Reiss 28:c222ca8383f4 1358 if (start_test) {
Jason Reiss 28:c222ca8383f4 1359 CommandTerminal::Dot()->getSettings()->Test.TestMode = true;
Jason Reiss 28:c222ca8383f4 1360
Jason Reiss 28:c222ca8383f4 1361 last_rx_seq = CommandTerminal::Dot()->getSettings()->Session.UplinkCounter;
Jason Reiss 28:c222ca8383f4 1362
Jason Reiss 28:c222ca8383f4 1363 uint16_t testDownlinkCounter = 0;
Jason Reiss 28:c222ca8383f4 1364 uint32_t txPeriod = 5000;
Jason Reiss 28:c222ca8383f4 1365 bool testConfirmed = false;
Jason Reiss 28:c222ca8383f4 1366
Jason Reiss 28:c222ca8383f4 1367 // init counter
Jason Reiss 28:c222ca8383f4 1368 std::vector<uint8_t> data;
Jason Reiss 28:c222ca8383f4 1369 uint8_t savedPort = CommandTerminal::Dot()->getAppPort();
Jason Reiss 28:c222ca8383f4 1370 uint8_t savedAcks = CommandTerminal::Dot()->getAck();
Jason Reiss 28:c222ca8383f4 1371 bool savedAdr = CommandTerminal::Dot()->getAdr();
Jason Reiss 28:c222ca8383f4 1372
Jason Reiss 28:c222ca8383f4 1373 CommandTerminal::Dot()->setAck(0);
Jason Reiss 28:c222ca8383f4 1374 CommandTerminal::Dot()->setAdr(true);
Jason Reiss 28:c222ca8383f4 1375 CommandTerminal::Dot()->setAppPort(224);
Jason Reiss 28:c222ca8383f4 1376
Jason Reiss 28:c222ca8383f4 1377 Timer sentTimer;
Jason Reiss 28:c222ca8383f4 1378 sentTimer.start();
Jason Reiss 28:c222ca8383f4 1379 while (CommandTerminal::Dot()->getSettings()->Test.TestMode) {
Jason Reiss 28:c222ca8383f4 1380 TEST_START:
Jason Reiss 28:c222ca8383f4 1381 if (RxPort == 224) {
Jason Reiss 28:c222ca8383f4 1382 data.clear();
Jason Reiss 28:c222ca8383f4 1383
Jason Reiss 28:c222ca8383f4 1384 switch (RxPayload[0]) {
Jason Reiss 28:c222ca8383f4 1385 case 0x00: { // PackageVersionReq
Jason Reiss 28:c222ca8383f4 1386 data.push_back(0x00);
Jason Reiss 28:c222ca8383f4 1387 data.push_back(0x06);
Jason Reiss 28:c222ca8383f4 1388 data.push_back(0x01);
Jason Reiss 28:c222ca8383f4 1389 break;
Jason Reiss 28:c222ca8383f4 1390 }
Jason Reiss 28:c222ca8383f4 1391 case 0x01: { // DutResetReq
Jason Reiss 28:c222ca8383f4 1392 if (RxPayloadSize == 1) {
Jason Reiss 28:c222ca8383f4 1393 CommandTerminal::Dot()->resetCpu();
Jason Reiss 28:c222ca8383f4 1394 }
Jason Reiss 28:c222ca8383f4 1395 break;
Jason Reiss 28:c222ca8383f4 1396 }
Jason Reiss 28:c222ca8383f4 1397 case 0x02: { // DutJoinReq
Jason Reiss 28:c222ca8383f4 1398 if (RxPayloadSize == 1) {
Jason Reiss 28:c222ca8383f4 1399 CommandTerminal::Dot()->joinNetworkOnce();
Jason Reiss 28:c222ca8383f4 1400 }
Jason Reiss 28:c222ca8383f4 1401 break;
Jason Reiss 28:c222ca8383f4 1402 }
Jason Reiss 28:c222ca8383f4 1403 case 0x03: { // SwitchClassReq
Jason Reiss 28:c222ca8383f4 1404 std::string cls = "A";
Jason Reiss 28:c222ca8383f4 1405 if (RxPayload[1] > 0 && RxPayload[1] < 3) {
Jason Reiss 28:c222ca8383f4 1406 cls = RxPayload[1] == 0x01 ? "B" : "C";
Jason Reiss 28:c222ca8383f4 1407 }
Jason Reiss 28:c222ca8383f4 1408 CommandTerminal::Dot()->setClass(cls);
Jason Reiss 28:c222ca8383f4 1409 break;
Jason Reiss 28:c222ca8383f4 1410 }
Jason Reiss 28:c222ca8383f4 1411 case 0x04: { // ADR Enabled/Disable
Jason Reiss 28:c222ca8383f4 1412 if (RxPayload[1] == 1)
Jason Reiss 28:c222ca8383f4 1413 CommandTerminal::Dot()->setAdr(true);
Jason Reiss 28:c222ca8383f4 1414 else
Jason Reiss 28:c222ca8383f4 1415 CommandTerminal::Dot()->setAdr(false);
Jason Reiss 28:c222ca8383f4 1416 break;
Jason Reiss 28:c222ca8383f4 1417 }
Jason Reiss 28:c222ca8383f4 1418 case 0x05: { // RegionalDutyCycleCtrlReq
Jason Reiss 28:c222ca8383f4 1419 if (RxPayload[1] == 0)
Jason Reiss 28:c222ca8383f4 1420 CommandTerminal::Dot()->setDisableDutyCycle(true);
Jason Reiss 28:c222ca8383f4 1421 else
Jason Reiss 28:c222ca8383f4 1422 CommandTerminal::Dot()->setDisableDutyCycle(false);
Jason Reiss 28:c222ca8383f4 1423
Jason Reiss 28:c222ca8383f4 1424 break;
Jason Reiss 28:c222ca8383f4 1425 }
Jason Reiss 28:c222ca8383f4 1426 case 0x06: { // TxPeriodicityChangeReq
Jason Reiss 28:c222ca8383f4 1427 if (RxPayload[1] < 2)
Jason Reiss 28:c222ca8383f4 1428 // 0, 1 => 5s
Jason Reiss 28:c222ca8383f4 1429 txPeriod = 5000U;
Jason Reiss 28:c222ca8383f4 1430 else if (RxPayload[1] < 8)
Jason Reiss 28:c222ca8383f4 1431 // 2 - 7 => 10s - 60s
Jason Reiss 28:c222ca8383f4 1432 txPeriod = (RxPayload[1] - 1) * 10000U;
Jason Reiss 28:c222ca8383f4 1433 else if (RxPayload[1] < 11) {
Jason Reiss 28:c222ca8383f4 1434 // 8, 9, 10 => 120s, 240s, 480s
Jason Reiss 28:c222ca8383f4 1435 txPeriod = 120 * (1 << (RxPayload[1] - 8)) * 1000U;
Jason Reiss 28:c222ca8383f4 1436 }
Jason Reiss 28:c222ca8383f4 1437 break;
Jason Reiss 28:c222ca8383f4 1438 }
Jason Reiss 28:c222ca8383f4 1439 case 0x07: { // TxFramesCtrl
Jason Reiss 28:c222ca8383f4 1440 if (RxPayload[1] == 0) {
Jason Reiss 28:c222ca8383f4 1441 // NO-OP
Jason Reiss 28:c222ca8383f4 1442 } else if (RxPayload[1] == 1) {
Jason Reiss 28:c222ca8383f4 1443 testConfirmed = false;
Jason Reiss 28:c222ca8383f4 1444 CommandTerminal::Dot()->getSettings()->Network.AckEnabled = 0;
Jason Reiss 28:c222ca8383f4 1445 CommandTerminal::Dot()->getSettings()->Session.Redundancy = 0;
Jason Reiss 28:c222ca8383f4 1446 } else if (RxPayload[1] == 2) {
Jason Reiss 28:c222ca8383f4 1447 testConfirmed = true;
Jason Reiss 28:c222ca8383f4 1448 CommandTerminal::Dot()->getSettings()->Network.AckEnabled = 8;
Jason Reiss 28:c222ca8383f4 1449 CommandTerminal::Dot()->getSettings()->Session.Redundancy = 8;
Jason Reiss 28:c222ca8383f4 1450 }
Jason Reiss 28:c222ca8383f4 1451 break;
Jason Reiss 28:c222ca8383f4 1452 }
Jason Reiss 28:c222ca8383f4 1453 case 0x08: { // EchoPayloadReq
Jason Reiss 28:c222ca8383f4 1454 data.push_back(0x08);
Jason Reiss 28:c222ca8383f4 1455 for (size_t i = 1; i < RxPayloadSize; i++) {
Jason Reiss 28:c222ca8383f4 1456 data.push_back(RxPayload[i] + 1);
Jason Reiss 28:c222ca8383f4 1457 }
Jason Reiss 28:c222ca8383f4 1458 break;
Jason Reiss 28:c222ca8383f4 1459 }
Jason Reiss 28:c222ca8383f4 1460 case 0x09: { // RxAppCntReq
Jason Reiss 28:c222ca8383f4 1461 data.push_back(0x09);
Jason Reiss 28:c222ca8383f4 1462 data.push_back(testDownlinkCounter >> 8);
Jason Reiss 28:c222ca8383f4 1463 data.push_back(testDownlinkCounter & 0xFF);
Jason Reiss 28:c222ca8383f4 1464 break;
Jason Reiss 28:c222ca8383f4 1465 }
Jason Reiss 28:c222ca8383f4 1466 case 0x0A: { // RxAppCntResetReq
Jason Reiss 28:c222ca8383f4 1467 testDownlinkCounter = 0;
Jason Reiss 28:c222ca8383f4 1468 break;
Jason Reiss 28:c222ca8383f4 1469 }
Jason Reiss 28:c222ca8383f4 1470 case 0x20: { // LinkCheckReq
Jason Reiss 28:c222ca8383f4 1471 CommandTerminal::Dot()->addMacCommand(lora::MOTE_MAC_LINK_CHECK_REQ, 0, 0);
Jason Reiss 28:c222ca8383f4 1472 break;
Jason Reiss 28:c222ca8383f4 1473 }
Jason Reiss 28:c222ca8383f4 1474 case 0x21: { // DeviceTimeReq
Jason Reiss 28:c222ca8383f4 1475 CommandTerminal::Dot()->addDeviceTimeRequest();
Jason Reiss 28:c222ca8383f4 1476 break;
Jason Reiss 28:c222ca8383f4 1477 }
Jason Reiss 28:c222ca8383f4 1478 case 0x22: { // PingSlotInfo
Jason Reiss 28:c222ca8383f4 1479 CommandTerminal::Dot()->setPingPeriodicity(RxPayload[1]);
Jason Reiss 28:c222ca8383f4 1480 CommandTerminal::Dot()->addMacCommand(lora::MOTE_MAC_PING_SLOT_INFO_REQ, RxPayload[1], 0);
Jason Reiss 28:c222ca8383f4 1481 break;
Jason Reiss 28:c222ca8383f4 1482 }
Jason Reiss 28:c222ca8383f4 1483 case 0x7D: { // TxCw
Jason Reiss 28:c222ca8383f4 1484 uint32_t freq = 0;
Jason Reiss 28:c222ca8383f4 1485 uint16_t timeout = 0;
Jason Reiss 28:c222ca8383f4 1486 uint8_t power = 0;
Jason Reiss 28:c222ca8383f4 1487
Jason Reiss 28:c222ca8383f4 1488 timeout = RxPayload[1] << 8 | RxPayload[2];
Jason Reiss 28:c222ca8383f4 1489 freq = (RxPayload[3] << 16 | RxPayload[4] << 8 | RxPayload[5]) * 100;
Jason Reiss 28:c222ca8383f4 1490 power = RxPayload[6];
Jason Reiss 28:c222ca8383f4 1491
Jason Reiss 28:c222ca8383f4 1492 CommandTerminal::Dot()->sendContinuous(true, timeout * 1000, freq, power);
Jason Reiss 28:c222ca8383f4 1493 break;
Jason Reiss 28:c222ca8383f4 1494 }
Jason Reiss 28:c222ca8383f4 1495 case 0x7E: { // DutFPort224DisableReq
Jason Reiss 28:c222ca8383f4 1496 _dot->setTestModeEnabled(false);
Jason Reiss 28:c222ca8383f4 1497 CommandTerminal::Dot()->getSettings()->Test.TestMode = false;
Jason Reiss 28:c222ca8383f4 1498 _dot->saveConfig();
Jason Reiss 28:c222ca8383f4 1499 break;
Jason Reiss 28:c222ca8383f4 1500 }
Jason Reiss 28:c222ca8383f4 1501 case 0x7F: { // DutVersionReq
Jason Reiss 28:c222ca8383f4 1502 std::string version = AT_APPLICATION_VERSION;
Jason Reiss 28:c222ca8383f4 1503 int temp = 0;
Jason Reiss 28:c222ca8383f4 1504
Jason Reiss 28:c222ca8383f4 1505 data.push_back(0x7F);
Jason Reiss 28:c222ca8383f4 1506 int ret = sscanf(&version[0], "%d", &temp);
Jason Reiss 28:c222ca8383f4 1507 data.push_back(temp); // AT_APP_VERSION_MAJOR; // MAJOR
Jason Reiss 28:c222ca8383f4 1508 ret = sscanf(&version[2], "%d", &temp);
Jason Reiss 28:c222ca8383f4 1509 data.push_back(temp); // AT_APP_VERSION_MINOR; // MINOR
Jason Reiss 28:c222ca8383f4 1510 ret = sscanf(&version[4], "%d", &temp);
Jason Reiss 28:c222ca8383f4 1511 data.push_back(temp); // AT_APP_VERSION_PATCH; // PATCH
Jason Reiss 28:c222ca8383f4 1512 break;
Jason Reiss 28:c222ca8383f4 1513 }
Jason Reiss 28:c222ca8383f4 1514 default: {
Jason Reiss 28:c222ca8383f4 1515 break;
Jason Reiss 28:c222ca8383f4 1516 }
Jason Reiss 28:c222ca8383f4 1517 }
Jason Reiss 28:c222ca8383f4 1518 }
Jason Reiss 28:c222ca8383f4 1519
Jason Reiss 28:c222ca8383f4 1520 do {
Jason Reiss 28:c222ca8383f4 1521 if (std::chrono::duration_cast<std::chrono::milliseconds>(sentTimer.elapsed_time()).count() < txPeriod)
Jason Reiss 28:c222ca8383f4 1522 osDelay(txPeriod - std::chrono::duration_cast<std::chrono::milliseconds>(sentTimer.elapsed_time()).count());
Jason Reiss 28:c222ca8383f4 1523
Jason Reiss 28:c222ca8383f4 1524 sentTimer.reset();
Jason Reiss 28:c222ca8383f4 1525
Jason Reiss 28:c222ca8383f4 1526 if (CommandTerminal::Dot()->send(data, testConfirmed) == mDot::MDOT_MAX_PAYLOAD_EXCEEDED) {
Jason Reiss 28:c222ca8383f4 1527 data.clear();
Jason Reiss 28:c222ca8383f4 1528 RxPort = 0;
Jason Reiss 28:c222ca8383f4 1529 goto TEST_START;
Jason Reiss 28:c222ca8383f4 1530 }
Jason Reiss 28:c222ca8383f4 1531
Jason Reiss 28:c222ca8383f4 1532 if (PacketReceived) {
Jason Reiss 28:c222ca8383f4 1533 last_rx_seq = CommandTerminal::Dot()->getSettings()->Session.UplinkCounter;
Jason Reiss 28:c222ca8383f4 1534 } else if ( CommandTerminal::Dot()->getSettings()->Session.UplinkCounter - last_rx_seq > 160) {
Jason Reiss 28:c222ca8383f4 1535 CommandTerminal::Dot()->setAck(savedAcks);
Jason Reiss 28:c222ca8383f4 1536 CommandTerminal::Dot()->setAppPort(savedPort);
Jason Reiss 28:c222ca8383f4 1537 CommandTerminal::Dot()->setAdr(savedAdr);
Jason Reiss 28:c222ca8383f4 1538 CommandTerminal::Dot()->getSettings()->Test.TestMode = false;
Jason Reiss 28:c222ca8383f4 1539 start_test = false;
Jason Reiss 28:c222ca8383f4 1540 break;
Jason Reiss 28:c222ca8383f4 1541 }
Jason Reiss 28:c222ca8383f4 1542
Jason Reiss 28:c222ca8383f4 1543 data.clear();
Jason Reiss 28:c222ca8383f4 1544
Jason Reiss 28:c222ca8383f4 1545 } while (CommandTerminal::Dot()->recv(data) != mDot::MDOT_OK);
Jason Reiss 28:c222ca8383f4 1546
Jason Reiss 28:c222ca8383f4 1547 if (RxPort != 0 || RxPayloadSize == 0)
Jason Reiss 28:c222ca8383f4 1548 testDownlinkCounter++;
Jason Reiss 28:c222ca8383f4 1549 }
Jason Reiss 28:c222ca8383f4 1550 }
Jason Reiss 28:c222ca8383f4 1551 #endif
Jason Reiss 28:c222ca8383f4 1552 }
Jason Reiss 28:c222ca8383f4 1553
jenkins@jenkinsdm1 18:63f098f042b2 1554 uint8_t CommandTerminal::getBatteryLevel() {
jenkins@jenkinsdm1 18:63f098f042b2 1555 return _battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1556 }
jenkins@jenkinsdm1 18:63f098f042b2 1557
Jason Reiss 23:4f0a981c0349 1558 void CommandTerminal::setBatteryLevel(uint8_t battery_level) {
jenkins@jenkinsdm1 18:63f098f042b2 1559 _battery_level = battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1560 }
jenkins@jenkinsdm1 18:63f098f042b2 1561
Jason Reiss 27:5fafd3b26ac3 1562 void CommandTerminal::formatPacket(uint8_t* payload, uint16_t size, bool hex) {
Jason Reiss 23:4f0a981c0349 1563
Jason Reiss 23:4f0a981c0349 1564 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1565 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1566 } else {
Jason Reiss 23:4f0a981c0349 1567 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1568 }
Jason Reiss 23:4f0a981c0349 1569
Jason Reiss 23:4f0a981c0349 1570 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1571 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1572 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1573 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 28:c222ca8383f4 1574 f_data[5] = _rxFcnt & 0xFF;
Jason Reiss 28:c222ca8383f4 1575 f_data[6] = (_rxFcnt >> 8) & 0xFF;
Jason Reiss 28:c222ca8383f4 1576 f_data[7] = (_rxFcnt >> 16) & 0xFF;
Jason Reiss 28:c222ca8383f4 1577 f_data[8] = (_rxFcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1578 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1579
Jason Reiss 23:4f0a981c0349 1580 for(int i = 0; i < size; i++)
Jason Reiss 23:4f0a981c0349 1581 f_data[i+10] = payload[i];
Jason Reiss 23:4f0a981c0349 1582
Jason Reiss 27:5fafd3b26ac3 1583 if (hex) {
Jason Reiss 27:5fafd3b26ac3 1584 std::string data = "RECV " + mts::Text::bin2hexString(f_data, size + 10) + "\r\n";
Jason Reiss 27:5fafd3b26ac3 1585 CommandTerminal::Serial()->write(data.c_str(), data.size());
Jason Reiss 27:5fafd3b26ac3 1586 } else {
Jason Reiss 27:5fafd3b26ac3 1587 CommandTerminal::Serial()->write((char*)f_data, size + 10);
Jason Reiss 27:5fafd3b26ac3 1588 }
Jason Reiss 23:4f0a981c0349 1589 }
Jason Reiss 23:4f0a981c0349 1590
Jason Reiss 23:4f0a981c0349 1591
Jason Reiss 27:5fafd3b26ac3 1592 std::string CommandTerminal::formatPacket(std::vector<uint8_t> payload, bool hex) {
Jason Reiss 23:4f0a981c0349 1593
Jason Reiss 23:4f0a981c0349 1594 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1595 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1596 } else {
Jason Reiss 23:4f0a981c0349 1597 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1598 }
Jason Reiss 23:4f0a981c0349 1599
Jason Reiss 23:4f0a981c0349 1600 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1601 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1602 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1603 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 28:c222ca8383f4 1604 f_data[5] = _rxFcnt & 0xFF;
Jason Reiss 28:c222ca8383f4 1605 f_data[6] = (_rxFcnt >> 8) & 0xFF;
Jason Reiss 28:c222ca8383f4 1606 f_data[7] = (_rxFcnt >> 16) & 0xFF;
Jason Reiss 28:c222ca8383f4 1607 f_data[8] = (_rxFcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1608 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1609
Jason Reiss 27:5fafd3b26ac3 1610 for(size_t i = 0; i < payload.size(); i++)
Jason Reiss 23:4f0a981c0349 1611 f_data[i+10] = payload.at(i);
Jason Reiss 23:4f0a981c0349 1612
Jason Reiss 27:5fafd3b26ac3 1613 if (hex) {
Jason Reiss 27:5fafd3b26ac3 1614 return mts::Text::bin2hexString(f_data, payload.size() + 10);
Jason Reiss 27:5fafd3b26ac3 1615 } else {
Jason Reiss 27:5fafd3b26ac3 1616 return std::string((char*)f_data, payload.size() + 10);
Jason Reiss 27:5fafd3b26ac3 1617 }
Jason Reiss 27:5fafd3b26ac3 1618
Jason Reiss 23:4f0a981c0349 1619 }
Jason Reiss 23:4f0a981c0349 1620
Jason Reiss 23:4f0a981c0349 1621
Jason Reiss 23:4f0a981c0349 1622
Jason Reiss 23:4f0a981c0349 1623 void CommandTerminal::formatPacketSDSend(std::vector<uint8_t> &payload) {
Jason Reiss 27:5fafd3b26ac3 1624 if (_dot->getRxOutput() == mDot::EXTENDED_HEX) {
Jason Reiss 27:5fafd3b26ac3 1625 int temp;
Jason Reiss 27:5fafd3b26ac3 1626 std::vector<uint8_t> converted;
Jason Reiss 27:5fafd3b26ac3 1627
Jason Reiss 27:5fafd3b26ac3 1628 for (size_t i=0; i < payload.size(); i+=2) {
Jason Reiss 27:5fafd3b26ac3 1629 if (sscanf((char*)&payload[i], "%2x", &temp) == 1) {
Jason Reiss 28:c222ca8383f4 1630 logDebug("Converted %s to %d", payload[i] + payload[i+1], temp);
Jason Reiss 27:5fafd3b26ac3 1631 converted.push_back((uint8_t)temp);
Jason Reiss 27:5fafd3b26ac3 1632 }
Jason Reiss 27:5fafd3b26ac3 1633 }
Jason Reiss 27:5fafd3b26ac3 1634
Jason Reiss 27:5fafd3b26ac3 1635 payload = converted;
Jason Reiss 27:5fafd3b26ac3 1636 }
Jason Reiss 27:5fafd3b26ac3 1637
Jason Reiss 23:4f0a981c0349 1638 if(payload.size() >= 3) {
Jason Reiss 23:4f0a981c0349 1639 _dot->setAppPort(payload[0]);
Jason Reiss 23:4f0a981c0349 1640 _dot->setRepeat(0);
Jason Reiss 23:4f0a981c0349 1641 _dot->setAck(0);
Jason Reiss 23:4f0a981c0349 1642 switch(payload[1]) {
Jason Reiss 23:4f0a981c0349 1643 case 0:
Jason Reiss 23:4f0a981c0349 1644 _dot->setAck(payload[2]);
Jason Reiss 23:4f0a981c0349 1645 break;
Jason Reiss 23:4f0a981c0349 1646 case 1:
Jason Reiss 23:4f0a981c0349 1647 _dot->setRepeat(payload[2]);
Jason Reiss 23:4f0a981c0349 1648 break;
Jason Reiss 23:4f0a981c0349 1649 default:
Jason Reiss 23:4f0a981c0349 1650 break;
Jason Reiss 23:4f0a981c0349 1651 }
Jason Reiss 23:4f0a981c0349 1652 payload.erase(payload.begin(), payload.begin()+3);
Jason Reiss 23:4f0a981c0349 1653 }
Jason Reiss 27:5fafd3b26ac3 1654
Jason Reiss 23:4f0a981c0349 1655 }
Jason Reiss 23:4f0a981c0349 1656
Jason Reiss 23:4f0a981c0349 1657
Jason Reiss 23:4f0a981c0349 1658
Mike Fiore 9:ff62b20f7000 1659 CommandTerminal::~CommandTerminal() {
Mike Fiore 9:ff62b20f7000 1660 delete _events;
Mike Fiore 9:ff62b20f7000 1661 }