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:
Wed Apr 24 10:47:25 2019 -0500
Revision:
23:4f0a981c0349
Parent:
22:a13ac7df92c0
Child:
27:5fafd3b26ac3
Update for v3.2.0 release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike Fiore 1:e52ae6584f1c 1 #include "ctype.h"
jenkins@jenkinsdm1 18:63f098f042b2 2 #include "CmdFactory.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>
Mike Fiore 14:f9a77400b622 9 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 14:f9a77400b622 10 #include "xdot_low_power.h"
Mike Fiore 14:f9a77400b622 11 #endif
Mike Fiore 1:e52ae6584f1c 12
Mike Fiore 14:f9a77400b622 13 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 1:e52ae6584f1c 14 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
Mike Fiore 14:f9a77400b622 15 #else
Mike Fiore 14:f9a77400b622 16 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa xDot Module\r\n\n";
Mike Fiore 14:f9a77400b622 17 #endif
Mike Fiore 1:e52ae6584f1c 18 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
Mike Fiore 1:e52ae6584f1c 19
Mike Fiore 1:e52ae6584f1c 20 const char CommandTerminal::newline[] = "\r\n";
Mike Fiore 1:e52ae6584f1c 21
Mike Fiore 1:e52ae6584f1c 22 // Command error text...
Mike Fiore 1:e52ae6584f1c 23 const char CommandTerminal::command_error[] = "Command not found!\r\n";
Mike Fiore 1:e52ae6584f1c 24
Mike Fiore 1:e52ae6584f1c 25 // Response texts...
Mike Fiore 1:e52ae6584f1c 26 const char CommandTerminal::help[] = "\r\nHelp\r\n";
Mike Fiore 1:e52ae6584f1c 27 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
Mike Fiore 9:ff62b20f7000 28 const char CommandTerminal::connect[] = "\r\nCONNECT\r\n";
Mike Fiore 9:ff62b20f7000 29 const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n";
Mike Fiore 1:e52ae6584f1c 30 const char CommandTerminal::done[] = "\r\nOK\r\n";
Mike Fiore 1:e52ae6584f1c 31 const char CommandTerminal::error[] = "\r\nERROR\r\n";
Mike Fiore 1:e52ae6584f1c 32
Mike Fiore 1:e52ae6584f1c 33 // Escape sequence...
Mike Fiore 1:e52ae6584f1c 34 const char CommandTerminal::escape_sequence[] = "+++";
Mike Fiore 1:e52ae6584f1c 35
Mike Fiore 9:ff62b20f7000 36 mts::ATSerial* CommandTerminal::_serialp = NULL;
Mike Fiore 14:f9a77400b622 37 mDot* CommandTerminal::_dot = NULL;
Mike Fiore 14:f9a77400b622 38
Mike Fiore 14:f9a77400b622 39 CommandTerminal::RadioEvent* CommandTerminal::_events = new RadioEvent();
Mike Fiore 9:ff62b20f7000 40
Mike Fiore 9:ff62b20f7000 41 static bool serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 42 static bool peer_to_peer = false;
Mike Fiore 1:e52ae6584f1c 43
Mike Fiore 14:f9a77400b622 44 std::string CommandTerminal::_errorMessage = "";
Mike Fiore 14:f9a77400b622 45
jenkins@jenkinsdm1 18:63f098f042b2 46 static uint8_t _battery_level = 0xFF;
jenkins@jenkinsdm1 18:63f098f042b2 47
Jason Reiss 23:4f0a981c0349 48 static uint8_t f_data[252]; //max payload 242 plus 10 bytes for format
Jason Reiss 23:4f0a981c0349 49 static uint32_t _rxAddress = 0;
Jason Reiss 23:4f0a981c0349 50
Mike Fiore 14:f9a77400b622 51 void CommandTerminal::setErrorMessage(const char* message) {
Mike Fiore 14:f9a77400b622 52 _errorMessage.assign(message);
Mike Fiore 14:f9a77400b622 53 }
Mike Fiore 14:f9a77400b622 54
Mike Fiore 14:f9a77400b622 55 void CommandTerminal::setErrorMessage(const std::string& message) {
Mike Fiore 14:f9a77400b622 56 _errorMessage.assign(message);
Mike Fiore 1:e52ae6584f1c 57 }
Jason Reiss 23:4f0a981c0349 58
Mike Fiore 14:f9a77400b622 59 CommandTerminal::CommandTerminal(mts::ATSerial& serial) :
Mike Fiore 14:f9a77400b622 60 _serial(serial),
Mike Fiore 14:f9a77400b622 61 _mode(mDot::COMMAND_MODE),
Mike Fiore 14:f9a77400b622 62 _sleep_standby(true),
Mike Fiore 14:f9a77400b622 63 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 14:f9a77400b622 64 _xbee_on_sleep(XBEE_ON_SLEEP),
Mike Fiore 14:f9a77400b622 65 #else
Mike Fiore 14:f9a77400b622 66 _xbee_on_sleep(GPIO2),
Mike Fiore 14:f9a77400b622 67 #endif
Mike Fiore 14:f9a77400b622 68 _autoOTAEnabled(false)
Mike Fiore 14:f9a77400b622 69 {
Mike Fiore 14:f9a77400b622 70 _serialp = &serial;
Mike Fiore 14:f9a77400b622 71 }
Mike Fiore 14:f9a77400b622 72
Mike Fiore 14:f9a77400b622 73 void CommandTerminal::init() {
Mike Fiore 14:f9a77400b622 74 _dot->setEvents(_events);
Mike Fiore 1:e52ae6584f1c 75 }
Mike Fiore 1:e52ae6584f1c 76
Mike Fiore 1:e52ae6584f1c 77 void CommandTerminal::printHelp() {
Mike Fiore 1:e52ae6584f1c 78 const char* name = NULL;
Mike Fiore 1:e52ae6584f1c 79 const char* text = NULL;
Mike Fiore 1:e52ae6584f1c 80 const char* desc = NULL;
Mike Fiore 1:e52ae6584f1c 81 const char* tab = "\t";
Mike Fiore 1:e52ae6584f1c 82
Mike Fiore 1:e52ae6584f1c 83 std::string header("Command");
Mike Fiore 1:e52ae6584f1c 84 header.append(tab);
Mike Fiore 1:e52ae6584f1c 85 header.append(tab);
Mike Fiore 1:e52ae6584f1c 86 header.append("Name");
Mike Fiore 1:e52ae6584f1c 87 header.append(tab);
Mike Fiore 1:e52ae6584f1c 88 header.append(tab);
Mike Fiore 1:e52ae6584f1c 89 header.append(tab);
Mike Fiore 1:e52ae6584f1c 90 header.append("Description");
Mike Fiore 1:e52ae6584f1c 91
Mike Fiore 1:e52ae6584f1c 92 write(newline);
Mike Fiore 1:e52ae6584f1c 93 write(header.c_str());
Mike Fiore 1:e52ae6584f1c 94 write(newline);
Mike Fiore 1:e52ae6584f1c 95 write(newline);
Mike Fiore 14:f9a77400b622 96
jenkins@jenkinsdm1 18:63f098f042b2 97 Command *cmd = NULL;
jenkins@jenkinsdm1 18:63f098f042b2 98 for (int i = 0; i < CmdFactory::NUMBER_OF_CMDS; i++) {
jenkins@jenkinsdm1 18:63f098f042b2 99 cmd = CmdFactory::Create(static_cast<CmdFactory::CmdId_t>(i));
jenkins@jenkinsdm1 18:63f098f042b2 100 name = cmd->name();
jenkins@jenkinsdm1 18:63f098f042b2 101 text = cmd->text();
jenkins@jenkinsdm1 18:63f098f042b2 102 desc = cmd->desc();
Mike Fiore 1:e52ae6584f1c 103 write(text);
Mike Fiore 1:e52ae6584f1c 104 if (strlen(text) < 8)
Mike Fiore 1:e52ae6584f1c 105 write(tab);
Mike Fiore 1:e52ae6584f1c 106 write(tab);
Mike Fiore 1:e52ae6584f1c 107 write(name);
Mike Fiore 1:e52ae6584f1c 108 if (strlen(name) < 8)
Mike Fiore 1:e52ae6584f1c 109 write(tab);
Mike Fiore 1:e52ae6584f1c 110 if (strlen(name) < 16)
Mike Fiore 1:e52ae6584f1c 111 write(tab);
Mike Fiore 1:e52ae6584f1c 112 write(tab);
Mike Fiore 1:e52ae6584f1c 113 write(desc);
Mike Fiore 1:e52ae6584f1c 114 write(newline);
jenkins@jenkinsdm1 18:63f098f042b2 115
jenkins@jenkinsdm1 18:63f098f042b2 116 delete cmd;
Mike Fiore 1:e52ae6584f1c 117 }
Mike Fiore 1:e52ae6584f1c 118
Mike Fiore 1:e52ae6584f1c 119 write(newline);
Mike Fiore 1:e52ae6584f1c 120 }
Mike Fiore 1:e52ae6584f1c 121
Mike Fiore 1:e52ae6584f1c 122 bool CommandTerminal::writeable() {
Mike Fiore 14:f9a77400b622 123 return _serialp->writeable();
Mike Fiore 1:e52ae6584f1c 124 }
Mike Fiore 1:e52ae6584f1c 125
Mike Fiore 1:e52ae6584f1c 126 bool CommandTerminal::readable() {
Mike Fiore 14:f9a77400b622 127 return _serialp->readable();
Mike Fiore 1:e52ae6584f1c 128 }
Mike Fiore 1:e52ae6584f1c 129
Mike Fiore 1:e52ae6584f1c 130 char CommandTerminal::read() {
Mike Fiore 1:e52ae6584f1c 131 char ch;
Mike Fiore 14:f9a77400b622 132 _serialp->read(&ch, 1);
Mike Fiore 1:e52ae6584f1c 133 return ch;
Mike Fiore 1:e52ae6584f1c 134 }
Mike Fiore 1:e52ae6584f1c 135
Mike Fiore 1:e52ae6584f1c 136 void CommandTerminal::write(const char* message) {
Mike Fiore 1:e52ae6584f1c 137 while (!writeable())
Mike Fiore 1:e52ae6584f1c 138 ;
Mike Fiore 14:f9a77400b622 139 _serialp->write(message, strlen(message));
Mike Fiore 1:e52ae6584f1c 140 }
Mike Fiore 1:e52ae6584f1c 141
Mike Fiore 1:e52ae6584f1c 142 void CommandTerminal::writef(const char* format, ...) {
Mike Fiore 1:e52ae6584f1c 143 char buff[256];
Mike Fiore 1:e52ae6584f1c 144
Mike Fiore 1:e52ae6584f1c 145 va_list ap;
Mike Fiore 1:e52ae6584f1c 146 va_start(ap, format);
Mike Fiore 1:e52ae6584f1c 147 int size = vsnprintf(buff, 256, format, ap);
Mike Fiore 1:e52ae6584f1c 148 while (!writeable())
Mike Fiore 1:e52ae6584f1c 149 ;
Mike Fiore 14:f9a77400b622 150 _serialp->write(buff, size);
Mike Fiore 1:e52ae6584f1c 151 va_end(ap);
Mike Fiore 1:e52ae6584f1c 152 }
Mike Fiore 1:e52ae6584f1c 153
Mike Fiore 9:ff62b20f7000 154 void CommandTerminal::serialLoop() {
Mike Fiore 1:e52ae6584f1c 155 Timer serial_read_timer;
Mike Fiore 1:e52ae6584f1c 156 std::vector<uint8_t> serial_buffer;
Mike Fiore 9:ff62b20f7000 157 std::vector<uint8_t> data;
Mike Fiore 9:ff62b20f7000 158 int timeout = 0;
Mike Fiore 1:e52ae6584f1c 159
Mike Fiore 9:ff62b20f7000 160 serial_read_timer.start();
Mike Fiore 1:e52ae6584f1c 161
Mike Fiore 9:ff62b20f7000 162 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Mike Fiore 9:ff62b20f7000 163 _xbee_on_sleep = GPIO_PIN_SET;
Mike Fiore 1:e52ae6584f1c 164
Mike Fiore 9:ff62b20f7000 165 timeout = _dot->getWakeDelay();
Mike Fiore 1:e52ae6584f1c 166
Mike Fiore 9:ff62b20f7000 167 // wait for timeout or start of serial data
Mike Fiore 14:f9a77400b622 168 while (!readable() && serial_read_timer.read_ms() < timeout && !_serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 169 osDelay(2);
Mike Fiore 1:e52ae6584f1c 170 }
Mike Fiore 1:e52ae6584f1c 171 }
Mike Fiore 1:e52ae6584f1c 172
Mike Fiore 14:f9a77400b622 173 if (!readable() && _events->SendAck()) {
Mike Fiore 14:f9a77400b622 174 logDebug("SERIAL NOT READABLE and ACK REQUESTED");
Mike Fiore 14:f9a77400b622 175 goto L_SEND;
Mike Fiore 14:f9a77400b622 176 }
Mike Fiore 14:f9a77400b622 177
Mike Fiore 14:f9a77400b622 178 if (readable() && !_serialp->escaped()) {
Mike Fiore 6:e27eaad36a0c 179
Mike Fiore 6:e27eaad36a0c 180 serial_read_timer.reset();
Mike Fiore 6:e27eaad36a0c 181 timeout = _dot->getWakeTimeout();
Mike Fiore 9:ff62b20f7000 182
Jason Reiss 23:4f0a981c0349 183 while (serial_read_timer.read_ms() < timeout && serial_buffer.size() <= _dot->getNextTxMaxSize()) {
Jason Reiss 23:4f0a981c0349 184 while (readable() && serial_buffer.size() < _dot->getNextTxMaxSize()) {
Mike Fiore 1:e52ae6584f1c 185 serial_buffer.push_back(read());
Mike Fiore 1:e52ae6584f1c 186 serial_read_timer.reset();
Mike Fiore 9:ff62b20f7000 187
Mike Fiore 14:f9a77400b622 188 if (_serialp->escaped())
Mike Fiore 9:ff62b20f7000 189 break;
Mike Fiore 1:e52ae6584f1c 190 }
Mike Fiore 1:e52ae6584f1c 191 }
Mike Fiore 9:ff62b20f7000 192
Mike Fiore 1:e52ae6584f1c 193 serial_read_timer.stop(), serial_read_timer.reset();
Mike Fiore 1:e52ae6584f1c 194
Mike Fiore 1:e52ae6584f1c 195 if (!serial_buffer.empty()) {
Mike Fiore 9:ff62b20f7000 196 if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
Mike Fiore 14:f9a77400b622 197 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 9:ff62b20f7000 198
Mike Fiore 14:f9a77400b622 199 L_SEND:
Mike Fiore 9:ff62b20f7000 200 // wait for any duty cycle limit to expire
Mike Fiore 14:f9a77400b622 201 while (_dot->getNextTxMs() > 0 && !_serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 202 osDelay(10);
Mike Fiore 9:ff62b20f7000 203 }
Mike Fiore 9:ff62b20f7000 204
Mike Fiore 14:f9a77400b622 205 if (_dot->getIsIdle()) {
Mike Fiore 9:ff62b20f7000 206 logDebug("Received serial data, sending out radio.");
Jason Reiss 23:4f0a981c0349 207 if(_dot->getRxOutput() == mDot::EXTENDED) {
Jason Reiss 23:4f0a981c0349 208 formatPacketSDSend(serial_buffer);
Jason Reiss 23:4f0a981c0349 209 }
Mike Fiore 9:ff62b20f7000 210 if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 211 logDebug("Send failed.");
Mike Fiore 9:ff62b20f7000 212 // If the data should be tossed after send failure, clear buffer
Mike Fiore 9:ff62b20f7000 213 if (_dot->getSerialClearOnError()) {
Mike Fiore 9:ff62b20f7000 214 serial_buffer.clear();
Mike Fiore 9:ff62b20f7000 215 }
Mike Fiore 9:ff62b20f7000 216 } else {
Mike Fiore 1:e52ae6584f1c 217
Mike Fiore 9:ff62b20f7000 218 // wait for send to finish
Mike Fiore 14:f9a77400b622 219 while (!_dot->getIsIdle() && !_serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 220 osDelay(10);
Mike Fiore 14:f9a77400b622 221 }
Mike Fiore 9:ff62b20f7000 222
Mike Fiore 9:ff62b20f7000 223 // call recv to wait for any packet before sending again
Jason Reiss 23:4f0a981c0349 224 if (!_serialp->escaped()) {
Jason Reiss 23:4f0a981c0349 225 data.clear();
Mike Fiore 9:ff62b20f7000 226 _dot->recv(data);
Jason Reiss 23:4f0a981c0349 227 }
Mike Fiore 9:ff62b20f7000 228
Mike Fiore 9:ff62b20f7000 229 // Clear the serial buffer if send is success
Mike Fiore 9:ff62b20f7000 230 serial_buffer.clear();
Mike Fiore 14:f9a77400b622 231
Mike Fiore 14:f9a77400b622 232 // In class C mode pending data will be sent automatically without uplink
Jason Reiss 23:4f0a981c0349 233 if (_dot->getClass() == "A") {
Mike Fiore 14:f9a77400b622 234 if (_dot->getDataPending()) {
Mike Fiore 14:f9a77400b622 235 logDebug("Data is pending");
Mike Fiore 14:f9a77400b622 236 goto L_SEND;
Mike Fiore 14:f9a77400b622 237 }
Mike Fiore 14:f9a77400b622 238 if (_dot->getAckRequested()) {
Mike Fiore 14:f9a77400b622 239 logDebug("Ack requested");
Mike Fiore 14:f9a77400b622 240 goto L_SEND;
Mike Fiore 14:f9a77400b622 241 }
Jason Reiss 23:4f0a981c0349 242 if (_dot->hasMacCommands()) {
Jason Reiss 23:4f0a981c0349 243 logDebug("Pending MAC answers");
Jason Reiss 23:4f0a981c0349 244 goto L_SEND;
Jason Reiss 23:4f0a981c0349 245 }
Mike Fiore 14:f9a77400b622 246 }
Mike Fiore 9:ff62b20f7000 247 }
Mike Fiore 1:e52ae6584f1c 248 } else {
Mike Fiore 6:e27eaad36a0c 249 logDebug("Radio is busy, cannot send.\r\n");
Mike Fiore 9:ff62b20f7000 250 osDelay(10);
Mike Fiore 1:e52ae6584f1c 251 }
Mike Fiore 1:e52ae6584f1c 252
Mike Fiore 1:e52ae6584f1c 253 } else {
Mike Fiore 6:e27eaad36a0c 254 logDebug("No data received from serial to send.\r\n");
Mike Fiore 1:e52ae6584f1c 255 }
Mike Fiore 9:ff62b20f7000 256 }
Mike Fiore 9:ff62b20f7000 257
Mike Fiore 14:f9a77400b622 258 if (!_serialp->readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serialp->escaped()) {
Mike Fiore 14:f9a77400b622 259 sleep(true);
Mike Fiore 1:e52ae6584f1c 260 }
Mike Fiore 9:ff62b20f7000 261
Mike Fiore 14:f9a77400b622 262 if (_serialp->escaped()) {
Mike Fiore 14:f9a77400b622 263 _serialp->clearEscaped();
Mike Fiore 14:f9a77400b622 264 _serialp->rxClear();
Mike Fiore 9:ff62b20f7000 265 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 266 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 267 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 268 write(done);
Mike Fiore 9:ff62b20f7000 269 return;
Mike Fiore 9:ff62b20f7000 270 }
Mike Fiore 9:ff62b20f7000 271
Mike Fiore 9:ff62b20f7000 272 if (!_dot->getNetworkJoinStatus()) {
Mike Fiore 9:ff62b20f7000 273 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 274 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 275 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 276 write(no_carrier);
Mike Fiore 9:ff62b20f7000 277 return;
Mike Fiore 9:ff62b20f7000 278 }
Mike Fiore 1:e52ae6584f1c 279 }
Mike Fiore 1:e52ae6584f1c 280
Mike Fiore 1:e52ae6584f1c 281 bool CommandTerminal::autoJoinCheck() {
Mike Fiore 1:e52ae6584f1c 282
Mike Fiore 1:e52ae6584f1c 283 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 284 int sleep = 1000;
Mike Fiore 1:e52ae6584f1c 285 Timer tmr;
Mike Fiore 9:ff62b20f7000 286 tmr.start();
Mike Fiore 1:e52ae6584f1c 287 int cnt = 0;
Mike Fiore 1:e52ae6584f1c 288
Mike Fiore 1:e52ae6584f1c 289 while (!_dot->getNetworkJoinStatus()) {
Mike Fiore 14:f9a77400b622 290 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 291 write("\r\nJoining network... ");
Mike Fiore 14:f9a77400b622 292 }
Mike Fiore 14:f9a77400b622 293 logInfo("Joining network... ");
Mike Fiore 1:e52ae6584f1c 294
Mike Fiore 9:ff62b20f7000 295 if (_dot->getNextTxMs() > 0) {
Mike Fiore 14:f9a77400b622 296 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 297 writef("\r\nWaiting %lu s before next join attempt\r\n", _dot->getNextTxMs() / 1000);
Mike Fiore 14:f9a77400b622 298 }
Mike Fiore 14:f9a77400b622 299 logInfo("Waiting %lu s before next join attempt", _dot->getNextTxMs() / 1000);
Mike Fiore 9:ff62b20f7000 300
Mike Fiore 9:ff62b20f7000 301 tmr.reset();
Mike Fiore 9:ff62b20f7000 302 while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
Mike Fiore 14:f9a77400b622 303 osDelay(20);
Mike Fiore 1:e52ae6584f1c 304 }
Mike Fiore 1:e52ae6584f1c 305 }
Mike Fiore 1:e52ae6584f1c 306
Mike Fiore 9:ff62b20f7000 307 if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
Mike Fiore 14:f9a77400b622 308 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 309 write("Network Joined\r\n");
Mike Fiore 14:f9a77400b622 310 write(done);
Mike Fiore 14:f9a77400b622 311 }
Mike Fiore 14:f9a77400b622 312 logInfo("Network Joined");
Mike Fiore 1:e52ae6584f1c 313 return false;
Mike Fiore 1:e52ae6584f1c 314 }
Mike Fiore 1:e52ae6584f1c 315
Mike Fiore 14:f9a77400b622 316 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 317 write("Network Join failed\r\n");
Mike Fiore 14:f9a77400b622 318 write(error);
Mike Fiore 14:f9a77400b622 319 }
Mike Fiore 14:f9a77400b622 320 logInfo("Network Join failed");
Mike Fiore 1:e52ae6584f1c 321
Mike Fiore 14:f9a77400b622 322 if (!_serial.escaped() && _dot->getFrequencySubBand() != 0 && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
Mike Fiore 1:e52ae6584f1c 323 cnt = 0;
Mike Fiore 1:e52ae6584f1c 324
jenkins@jenkinsdm1 16:d5cf2af81a6d 325 if (lora::ChannelPlan::IsPlanFixed(_dot->getFrequencyBand())) {
Mike Fiore 1:e52ae6584f1c 326 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
Mike Fiore 9:ff62b20f7000 327 logWarning("Join retries exhausted, switching to sub band %u", band);
Mike Fiore 1:e52ae6584f1c 328 _dot->setFrequencySubBand(band);
Mike Fiore 1:e52ae6584f1c 329 }
Mike Fiore 1:e52ae6584f1c 330 }
Mike Fiore 1:e52ae6584f1c 331
Mike Fiore 1:e52ae6584f1c 332 tmr.reset();
Mike Fiore 9:ff62b20f7000 333 while (tmr.read_ms() < sleep && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 334 osDelay(10);
Mike Fiore 1:e52ae6584f1c 335 }
Mike Fiore 1:e52ae6584f1c 336
Mike Fiore 9:ff62b20f7000 337 if (_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 338 _serial.clearEscaped();
Mike Fiore 9:ff62b20f7000 339 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 340 _mode = mDot::COMMAND_MODE;
Mike Fiore 14:f9a77400b622 341 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 342 write("Join Canceled\r\n");
Mike Fiore 14:f9a77400b622 343 write(done);
Mike Fiore 14:f9a77400b622 344 }
Mike Fiore 14:f9a77400b622 345 logInfo("Join Canceled\r\n");
Mike Fiore 9:ff62b20f7000 346 return true;
Mike Fiore 9:ff62b20f7000 347 }
Mike Fiore 1:e52ae6584f1c 348 }
Mike Fiore 1:e52ae6584f1c 349
Mike Fiore 1:e52ae6584f1c 350 return false;
Mike Fiore 1:e52ae6584f1c 351 }
Mike Fiore 1:e52ae6584f1c 352
Mike Fiore 1:e52ae6584f1c 353 void CommandTerminal::start() {
Mike Fiore 1:e52ae6584f1c 354
Mike Fiore 1:e52ae6584f1c 355 char ch;
Mike Fiore 1:e52ae6584f1c 356 bool running = true;
Mike Fiore 1:e52ae6584f1c 357 bool echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 358 std::string command;
Mike Fiore 14:f9a77400b622 359 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 4:666017851052 360 std::deque<std::string> history;
Mike Fiore 4:666017851052 361 int history_index = -1;
Mike Fiore 14:f9a77400b622 362 #endif
Mike Fiore 1:e52ae6584f1c 363 std::vector<std::string> args;
Mike Fiore 9:ff62b20f7000 364 bool join_canceled = false;
Mike Fiore 1:e52ae6584f1c 365
Mike Fiore 14:f9a77400b622 366 _autoOTAEnabled = _dot->getJoinMode() == mDot::AUTO_OTA;
Mike Fiore 14:f9a77400b622 367
Mike Fiore 1:e52ae6584f1c 368 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Mike Fiore 9:ff62b20f7000 369
Mike Fiore 9:ff62b20f7000 370 serial_data_mode = true;
Mike Fiore 9:ff62b20f7000 371 _mode = mDot::SERIAL_MODE;
Mike Fiore 1:e52ae6584f1c 372
Mike Fiore 1:e52ae6584f1c 373 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 374 char ch;
Mike Fiore 1:e52ae6584f1c 375
Mike Fiore 9:ff62b20f7000 376 if (!_dot->getStandbyFlag()) {
Mike Fiore 9:ff62b20f7000 377 // wake up from power-on/reset
Mike Fiore 9:ff62b20f7000 378
Mike Fiore 9:ff62b20f7000 379 int escape_timeout = 1000;
Mike Fiore 9:ff62b20f7000 380 Timer tmr;
Mike Fiore 9:ff62b20f7000 381 Timer escape_tmr;
Mike Fiore 1:e52ae6584f1c 382
Mike Fiore 9:ff62b20f7000 383 // wait one second for possible escape by user pressing '+' key
Mike Fiore 9:ff62b20f7000 384 tmr.reset();
Mike Fiore 9:ff62b20f7000 385 tmr.start();
Mike Fiore 9:ff62b20f7000 386 escape_tmr.reset();
Mike Fiore 9:ff62b20f7000 387 escape_tmr.start();
Mike Fiore 9:ff62b20f7000 388 while (tmr.read_ms() < escape_timeout) {
Mike Fiore 9:ff62b20f7000 389 if (_serial.readable()) {
Mike Fiore 9:ff62b20f7000 390 _serial.read(&ch, 1);
Mike Fiore 9:ff62b20f7000 391 escape_buffer += ch;
Mike Fiore 9:ff62b20f7000 392 }
Mike Fiore 1:e52ae6584f1c 393
Mike Fiore 9:ff62b20f7000 394 if (escape_buffer.find("+") != std::string::npos) {
Mike Fiore 9:ff62b20f7000 395 logInfo("Escape detected");
Mike Fiore 9:ff62b20f7000 396 join_canceled = true;
Mike Fiore 9:ff62b20f7000 397 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 398 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 399 command.clear();
Mike Fiore 9:ff62b20f7000 400 break;
Mike Fiore 9:ff62b20f7000 401 }
Mike Fiore 9:ff62b20f7000 402
Mike Fiore 9:ff62b20f7000 403 if (escape_tmr.read_ms() > escape_timeout)
Mike Fiore 9:ff62b20f7000 404 escape_buffer.clear();
Mike Fiore 9:ff62b20f7000 405
Mike Fiore 9:ff62b20f7000 406 osDelay(1);
Mike Fiore 1:e52ae6584f1c 407 }
Mike Fiore 1:e52ae6584f1c 408 }
Mike Fiore 1:e52ae6584f1c 409
Mike Fiore 9:ff62b20f7000 410 if (_mode == mDot::SERIAL_MODE && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
Mike Fiore 9:ff62b20f7000 411 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 412 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 413 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 414
Mike Fiore 9:ff62b20f7000 415 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
Mike Fiore 9:ff62b20f7000 416 _serial.writef("Network Not Joined\r\n");
Mike Fiore 9:ff62b20f7000 417 _serial.writef(error);
Mike Fiore 9:ff62b20f7000 418 }
Mike Fiore 9:ff62b20f7000 419 }
Mike Fiore 1:e52ae6584f1c 420 }
Mike Fiore 1:e52ae6584f1c 421
Mike Fiore 9:ff62b20f7000 422 if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
Mike Fiore 9:ff62b20f7000 423 peer_to_peer = true;
Mike Fiore 9:ff62b20f7000 424 } else {
Mike Fiore 9:ff62b20f7000 425 peer_to_peer = false;
Mike Fiore 9:ff62b20f7000 426 }
Mike Fiore 1:e52ae6584f1c 427 //Run terminal session
Mike Fiore 1:e52ae6584f1c 428 while (running) {
jenkins@jenkinsdm1 18:63f098f042b2 429 // wait for input to reduce at command idle current
Mike Fiore 9:ff62b20f7000 430 while (!readable() || _mode == mDot::SERIAL_MODE) {
Mike Fiore 14:f9a77400b622 431 if (!join_canceled && _autoOTAEnabled) {
Mike Fiore 9:ff62b20f7000 432 join_canceled = autoJoinCheck();
Mike Fiore 9:ff62b20f7000 433 if (join_canceled)
Mike Fiore 9:ff62b20f7000 434 command.clear();
Mike Fiore 9:ff62b20f7000 435 }
Mike Fiore 1:e52ae6584f1c 436
Mike Fiore 14:f9a77400b622 437 if (!_autoOTAEnabled || (!join_canceled && _autoOTAEnabled)) {
Mike Fiore 9:ff62b20f7000 438 switch (_mode) {
Mike Fiore 9:ff62b20f7000 439 case mDot::SERIAL_MODE:
Mike Fiore 9:ff62b20f7000 440 // signal wakeup, read serial and output to radio
Mike Fiore 9:ff62b20f7000 441 serialLoop();
Mike Fiore 9:ff62b20f7000 442 continue;
Mike Fiore 9:ff62b20f7000 443 break;
Mike Fiore 9:ff62b20f7000 444 default:
Mike Fiore 9:ff62b20f7000 445 break;
Mike Fiore 9:ff62b20f7000 446 }
Mike Fiore 1:e52ae6584f1c 447 }
Mike Fiore 9:ff62b20f7000 448
Mike Fiore 9:ff62b20f7000 449 ch = '\0';
Mike Fiore 1:e52ae6584f1c 450
Mike Fiore 9:ff62b20f7000 451 wait(0.00001); // 10 us
Mike Fiore 9:ff62b20f7000 452 _serial.escaped();
Mike Fiore 9:ff62b20f7000 453 }
Mike Fiore 1:e52ae6584f1c 454
Mike Fiore 1:e52ae6584f1c 455 // read characters
Mike Fiore 1:e52ae6584f1c 456 if (readable()) {
Mike Fiore 1:e52ae6584f1c 457 ch = read();
Mike Fiore 1:e52ae6584f1c 458
Mike Fiore 4:666017851052 459 if (ch == '\b' || ch == 0x7f) {
Mike Fiore 1:e52ae6584f1c 460 if (!command.empty()) {
Mike Fiore 1:e52ae6584f1c 461 writef("\b \b");
Mike Fiore 1:e52ae6584f1c 462 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 463 }
Mike Fiore 1:e52ae6584f1c 464 continue;
Mike Fiore 4:666017851052 465 } else if (ch == 0x1b || ch == 0x09) {
Mike Fiore 4:666017851052 466 osDelay(20);
Mike Fiore 4:666017851052 467 // catch escape sequence, or tab
Mike Fiore 9:ff62b20f7000 468 char ch1 = 0x00, ch2 = 0x00;
Mike Fiore 4:666017851052 469
Mike Fiore 4:666017851052 470 if (readable()) {
Mike Fiore 4:666017851052 471 ch1 = read();
Mike Fiore 4:666017851052 472 if (readable())
Mike Fiore 4:666017851052 473 ch2 = read();
Mike Fiore 4:666017851052 474
Mike Fiore 14:f9a77400b622 475 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 4:666017851052 476 if (ch1 == 0x5b && ch2 == 0x41) {
Mike Fiore 4:666017851052 477 // up key
Mike Fiore 9:ff62b20f7000 478 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 479 writef("\b \b");
Mike Fiore 4:666017851052 480 }
Mike Fiore 4:666017851052 481 if (history.size() > 0) {
Mike Fiore 9:ff62b20f7000 482 if (++history_index >= int(history.size() - 1))
Mike Fiore 4:666017851052 483 history_index = history.size() - 1;
Mike Fiore 4:666017851052 484
Mike Fiore 4:666017851052 485 command = history[history_index];
Mike Fiore 4:666017851052 486 writef("%s", history[history_index].c_str());
Mike Fiore 4:666017851052 487 } else {
Mike Fiore 4:666017851052 488 command.clear();
Mike Fiore 4:666017851052 489 }
Mike Fiore 4:666017851052 490 } else if (ch1 == 0x5b && ch2 == 0x42) {
Mike Fiore 4:666017851052 491
Mike Fiore 4:666017851052 492 // down key
Mike Fiore 9:ff62b20f7000 493 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 494 writef("\b \b");
Mike Fiore 4:666017851052 495 }
Mike Fiore 4:666017851052 496
Mike Fiore 4:666017851052 497 if (--history_index < 0) {
Mike Fiore 4:666017851052 498 history_index = -1;
Mike Fiore 4:666017851052 499 command.clear();
Mike Fiore 4:666017851052 500 } else {
Mike Fiore 4:666017851052 501 command = history[history_index];
Mike Fiore 4:666017851052 502 writef("%s", history[history_index].c_str());
Mike Fiore 4:666017851052 503 }
Mike Fiore 4:666017851052 504 }
Mike Fiore 14:f9a77400b622 505 #endif
Mike Fiore 4:666017851052 506 }
Mike Fiore 9:ff62b20f7000 507 while (readable())
Mike Fiore 9:ff62b20f7000 508 read();
Mike Fiore 4:666017851052 509 continue;
Mike Fiore 1:e52ae6584f1c 510 } else {
Mike Fiore 1:e52ae6584f1c 511 command += ch;
Mike Fiore 1:e52ae6584f1c 512 }
Mike Fiore 1:e52ae6584f1c 513
Mike Fiore 1:e52ae6584f1c 514 // echo chars if enabled
Mike Fiore 1:e52ae6584f1c 515 if (echo && !(ch == '\r' || ch == '\n'))
Mike Fiore 1:e52ae6584f1c 516 writef("%c", ch);
Mike Fiore 1:e52ae6584f1c 517 }
Mike Fiore 1:e52ae6584f1c 518
Mike Fiore 1:e52ae6584f1c 519 // look for end of command line
Mike Fiore 1:e52ae6584f1c 520 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 521 // remove new line or cr character
Mike Fiore 1:e52ae6584f1c 522 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 523 write("\r"); // match standard modem output
Mike Fiore 1:e52ae6584f1c 524 write(newline);
Mike Fiore 1:e52ae6584f1c 525 } else {
Mike Fiore 1:e52ae6584f1c 526 continue;
Mike Fiore 1:e52ae6584f1c 527 }
Mike Fiore 1:e52ae6584f1c 528
Mike Fiore 1:e52ae6584f1c 529 // trim whitespace from command
Mike Fiore 1:e52ae6584f1c 530 mts::Text::trim(command, "\r\n\t ");
Mike Fiore 1:e52ae6584f1c 531
Mike Fiore 1:e52ae6584f1c 532 if (command.size() < 1) {
Mike Fiore 1:e52ae6584f1c 533 command.clear();
Mike Fiore 1:e52ae6584f1c 534 continue;
Mike Fiore 1:e52ae6584f1c 535 }
Mike Fiore 1:e52ae6584f1c 536
Mike Fiore 1:e52ae6584f1c 537 // parse command and args
Mike Fiore 1:e52ae6584f1c 538 args.clear();
Mike Fiore 1:e52ae6584f1c 539
Mike Fiore 1:e52ae6584f1c 540 // find first '=' character
Mike Fiore 1:e52ae6584f1c 541 size_t delim_index = command.find("=");
Mike Fiore 1:e52ae6584f1c 542 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 543 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 544 } else {
Mike Fiore 1:e52ae6584f1c 545 // find first ' ' character
Mike Fiore 1:e52ae6584f1c 546 delim_index = command.find(" ");
Mike Fiore 1:e52ae6584f1c 547 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 548 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 549 } else {
Mike Fiore 1:e52ae6584f1c 550 args.push_back(command);
Mike Fiore 1:e52ae6584f1c 551 }
Mike Fiore 1:e52ae6584f1c 552 }
Mike Fiore 1:e52ae6584f1c 553
Mike Fiore 1:e52ae6584f1c 554 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 555 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
Mike Fiore 1:e52ae6584f1c 556 args.insert(args.end(), params.begin(), params.end());
Mike Fiore 1:e52ae6584f1c 557 }
Mike Fiore 1:e52ae6584f1c 558
Mike Fiore 1:e52ae6584f1c 559 args[0] = mts::Text::toUpper(args[0]);
Mike Fiore 1:e52ae6584f1c 560
Mike Fiore 1:e52ae6584f1c 561 // print help
Mike Fiore 1:e52ae6584f1c 562 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
Mike Fiore 1:e52ae6584f1c 563 printHelp();
Mike Fiore 1:e52ae6584f1c 564 command.clear();
Mike Fiore 9:ff62b20f7000 565 } else if ((args[0].find("ATE?") == 0 && args[0].length() == 4) || (args[0].find("ATE") == 0 && args[0].length() == 3)) {
Mike Fiore 9:ff62b20f7000 566 writef("%d\r\n", _dot->getEcho());
Mike Fiore 9:ff62b20f7000 567 write(done);
Mike Fiore 1:e52ae6584f1c 568 } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 569 _dot->setEcho(false);
Mike Fiore 1:e52ae6584f1c 570 write(done);
Mike Fiore 1:e52ae6584f1c 571 echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 572 } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 573 _dot->setEcho(true);
Mike Fiore 1:e52ae6584f1c 574 write(done);
Mike Fiore 1:e52ae6584f1c 575 echo = _dot->getEcho();
Mike Fiore 9:ff62b20f7000 576 } else if ((args[0].find("ATV?") == 0 && args[0].length() == 4) || (args[0].find("ATV") == 0 && args[0].length() == 3)) {
Mike Fiore 9:ff62b20f7000 577 writef("%d\r\n", _dot->getVerbose());
Mike Fiore 9:ff62b20f7000 578 write(done);
Mike Fiore 1:e52ae6584f1c 579 } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 580 _dot->setVerbose(false);
Mike Fiore 1:e52ae6584f1c 581 write(done);
Mike Fiore 1:e52ae6584f1c 582 } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 583 _dot->setVerbose(true);
Mike Fiore 1:e52ae6584f1c 584 write(done);
Mike Fiore 9:ff62b20f7000 585 } else if ((args[0].find("AT&K?") == 0 && args[0].length() == 5) || (args[0].find("AT&K") == 0 && args[0].length() == 4)) {
Mike Fiore 9:ff62b20f7000 586 writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
Mike Fiore 9:ff62b20f7000 587 write(done);
Mike Fiore 9:ff62b20f7000 588 } else if (args[0].find("AT&K0") == 0 && args[0].length() == 5) {
Mike Fiore 9:ff62b20f7000 589 _dot->setFlowControl(false);
Mike Fiore 9:ff62b20f7000 590 write(done);
Mike Fiore 9:ff62b20f7000 591 } else if (args[0].find("AT&K3") == 0 && args[0].length() == 5) {
Mike Fiore 9:ff62b20f7000 592 _dot->setFlowControl(true);
Mike Fiore 9:ff62b20f7000 593 write(done);
Mike Fiore 1:e52ae6584f1c 594 } else if (args[0] == "AT+SD") {
Mike Fiore 9:ff62b20f7000 595 if (_dot->getNetworkJoinStatus()) {
Mike Fiore 9:ff62b20f7000 596 logDebug("Enter Serial Mode");
Mike Fiore 9:ff62b20f7000 597 write(connect);
Mike Fiore 9:ff62b20f7000 598 serial_data_mode = true;
Jason Reiss 23:4f0a981c0349 599 _serialp->clearEscaped();
Mike Fiore 9:ff62b20f7000 600 _mode = mDot::SERIAL_MODE;
Mike Fiore 9:ff62b20f7000 601 } else {
Mike Fiore 9:ff62b20f7000 602 logDebug("Network Not Joined");
Mike Fiore 9:ff62b20f7000 603 write("Network Not Joined\r\n");
Mike Fiore 9:ff62b20f7000 604 write(error);
Mike Fiore 9:ff62b20f7000 605 }
Mike Fiore 4:666017851052 606 } else if (args[0] == "AT+SLEEP") {
Mike Fiore 9:ff62b20f7000 607 if (args.size() > 2 && (args[1] != "?")) {
Mike Fiore 4:666017851052 608 write("Invalid argument\r\n");
Mike Fiore 4:666017851052 609 write(error);
Mike Fiore 4:666017851052 610 } else {
Mike Fiore 4:666017851052 611 if (args.size() > 1 && args[1] == "?") {
Mike Fiore 9:ff62b20f7000 612 write("(0:deepsleep,1:sleep)\r\n");
Mike Fiore 4:666017851052 613 write(done);
Mike Fiore 4:666017851052 614 } else {
Mike Fiore 4:666017851052 615 _sleep_standby = !(args.size() > 1 && args[1] == "1");
Mike Fiore 14:f9a77400b622 616 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 14:f9a77400b622 617 //Read the board ID. If all 0's, it is revision B. This hardware does not support deep sleep.
Mike Fiore 14:f9a77400b622 618 DigitalIn ID2(PC_4);
Mike Fiore 14:f9a77400b622 619 DigitalIn ID1(PC_5);
Mike Fiore 14:f9a77400b622 620 DigitalIn ID0(PD_2);
Mike Fiore 14:f9a77400b622 621 if(ID2 == 0 && ID1 == 0 && ID0 == 0 && _sleep_standby == 1){
Mike Fiore 14:f9a77400b622 622 _sleep_standby = 0;
Mike Fiore 14:f9a77400b622 623 logWarning("This hardware version does not support deep sleep. Using sleep mode instead.");
Mike Fiore 14:f9a77400b622 624 }
Jason Reiss 23:4f0a981c0349 625 #endif
Mike Fiore 9:ff62b20f7000 626 write(done);
Jason Reiss 23:4f0a981c0349 627 if (_dot->getBaud() < 9600)
Jason Reiss 23:4f0a981c0349 628 osDelay(20);
Jason Reiss 23:4f0a981c0349 629 else if (_dot->getBaud() > 57600)
Jason Reiss 23:4f0a981c0349 630 osDelay(2);
Jason Reiss 23:4f0a981c0349 631 else
Jason Reiss 23:4f0a981c0349 632 osDelay(5);
Mike Fiore 4:666017851052 633 this->sleep(_sleep_standby);
Mike Fiore 14:f9a77400b622 634 osDelay(1);
Mike Fiore 4:666017851052 635 }
Mike Fiore 4:666017851052 636 }
Mike Fiore 1:e52ae6584f1c 637 } else {
Mike Fiore 1:e52ae6584f1c 638 bool found = false;
Mike Fiore 1:e52ae6584f1c 639 bool query = false;
Mike Fiore 1:e52ae6584f1c 640
Mike Fiore 1:e52ae6584f1c 641 std::string lookfor = args[0];
Mike Fiore 1:e52ae6584f1c 642
Mike Fiore 1:e52ae6584f1c 643 // per command help
Mike Fiore 1:e52ae6584f1c 644 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0))
Mike Fiore 1:e52ae6584f1c 645 lookfor = mts::Text::toUpper(args[1]);
Mike Fiore 1:e52ae6584f1c 646
Mike Fiore 1:e52ae6584f1c 647 // trim off any trailing '?' and mark as a query command
Mike Fiore 1:e52ae6584f1c 648 if (args[0].rfind("?") == args[0].length() - 1) {
Mike Fiore 1:e52ae6584f1c 649 query = true;
Mike Fiore 1:e52ae6584f1c 650 lookfor = args[0].substr(0, args[0].length() - 1);
Mike Fiore 1:e52ae6584f1c 651 }
Mike Fiore 1:e52ae6584f1c 652
Mike Fiore 1:e52ae6584f1c 653 // search for command
jenkins@jenkinsdm1 18:63f098f042b2 654 Command *cmd = NULL;
jenkins@jenkinsdm1 18:63f098f042b2 655 for (int i = 0; i < CmdFactory::NUMBER_OF_CMDS; i++) {
jenkins@jenkinsdm1 18:63f098f042b2 656 cmd = CmdFactory::Create(static_cast<CmdFactory::CmdId_t>(i));
Mike Fiore 1:e52ae6584f1c 657
Mike Fiore 1:e52ae6584f1c 658 // match CMD or CMD? syntax if command is queryable
jenkins@jenkinsdm1 18:63f098f042b2 659 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
Mike Fiore 1:e52ae6584f1c 660 found = true;
Mike Fiore 1:e52ae6584f1c 661 if (args[0] == "HELP") {
jenkins@jenkinsdm1 18:63f098f042b2 662 writef("%s%s", cmd->help().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 663 write(done);
Mike Fiore 1:e52ae6584f1c 664 }
Mike Fiore 1:e52ae6584f1c 665
Mike Fiore 1:e52ae6584f1c 666 else if (args.size() > 1 && args[1] == "?") {
jenkins@jenkinsdm1 18:63f098f042b2 667 writef("%s%s", cmd->usage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 668 write(done);
jenkins@jenkinsdm1 18:63f098f042b2 669 } else if (!cmd->verify(args)) {
Mike Fiore 14:f9a77400b622 670 writef("%s%s", _errorMessage.c_str(), newline);
Mike Fiore 1:e52ae6584f1c 671 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 672 } else {
jenkins@jenkinsdm1 18:63f098f042b2 673 if (cmd->action(args) == 0) {
Mike Fiore 1:e52ae6584f1c 674 writef("%s", done);
Mike Fiore 1:e52ae6584f1c 675 } else {
Mike Fiore 14:f9a77400b622 676 writef("%s%s", _errorMessage.c_str(), newline);
Mike Fiore 1:e52ae6584f1c 677 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 678 }
Mike Fiore 1:e52ae6584f1c 679 }
Mike Fiore 1:e52ae6584f1c 680 }
jenkins@jenkinsdm1 18:63f098f042b2 681
jenkins@jenkinsdm1 18:63f098f042b2 682 delete cmd;
Mike Fiore 1:e52ae6584f1c 683 }
Mike Fiore 1:e52ae6584f1c 684
Mike Fiore 1:e52ae6584f1c 685 if (!found) {
Mike Fiore 1:e52ae6584f1c 686 writef("%s", command_error);
Mike Fiore 1:e52ae6584f1c 687 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 688 }
Mike Fiore 1:e52ae6584f1c 689 }
Mike Fiore 1:e52ae6584f1c 690
Mike Fiore 14:f9a77400b622 691 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 4:666017851052 692 if (history.size() == 0 || history.front() != command)
Mike Fiore 4:666017851052 693 history.push_front(command);
Mike Fiore 4:666017851052 694 history_index = -1;
Mike Fiore 1:e52ae6584f1c 695 command.clear();
Mike Fiore 1:e52ae6584f1c 696
Mike Fiore 4:666017851052 697 while (history.size() > 10)
Mike Fiore 4:666017851052 698 history.pop_back();
Mike Fiore 14:f9a77400b622 699 #else
Mike Fiore 14:f9a77400b622 700 command.clear();
Mike Fiore 14:f9a77400b622 701 #endif
Mike Fiore 1:e52ae6584f1c 702 }
Mike Fiore 1:e52ae6584f1c 703 }
Mike Fiore 1:e52ae6584f1c 704
Mike Fiore 1:e52ae6584f1c 705 void CommandTerminal::sleep(bool standby) {
Mike Fiore 1:e52ae6584f1c 706 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 1:e52ae6584f1c 707
Mike Fiore 4:666017851052 708 _serial.rxClear();
Mike Fiore 4:666017851052 709 _serial.txClear();
Mike Fiore 1:e52ae6584f1c 710
Mike Fiore 14:f9a77400b622 711 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 14:f9a77400b622 712 xdot_save_gpio_state();
Mike Fiore 14:f9a77400b622 713
Mike Fiore 14:f9a77400b622 714 /* GPIO Ports Clock Enable */
Mike Fiore 14:f9a77400b622 715 __GPIOA_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 716 __GPIOB_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 717 __GPIOC_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 718 __GPIOH_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 719
Mike Fiore 14:f9a77400b622 720 GPIO_InitTypeDef GPIO_InitStruct;
Mike Fiore 14:f9a77400b622 721
Mike Fiore 14:f9a77400b622 722 // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
Mike Fiore 14:f9a77400b622 723 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
Mike Fiore 14:f9a77400b622 724 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 725 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 726 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 727
Mike Fiore 14:f9a77400b622 728 // I2C_SDA & I2C_SCL to analog nopull
Mike Fiore 14:f9a77400b622 729 GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
Mike Fiore 14:f9a77400b622 730 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 731 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 732 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 733
Mike Fiore 14:f9a77400b622 734 // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
Mike Fiore 14:f9a77400b622 735 GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
Mike Fiore 14:f9a77400b622 736 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 737 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 738 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 739
Mike Fiore 14:f9a77400b622 740 // iterate through potential wake pins - leave the configured wake pin alone if one is needed
Mike Fiore 14:f9a77400b622 741 if (_dot->getWakePin() != WAKE || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 742 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 14:f9a77400b622 743 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 744 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 745 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 746 }
Mike Fiore 14:f9a77400b622 747 if (_dot->getWakePin() != GPIO0 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 748 GPIO_InitStruct.Pin = GPIO_PIN_4;
Mike Fiore 14:f9a77400b622 749 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 750 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 751 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 752 }
Mike Fiore 14:f9a77400b622 753 if (_dot->getWakePin() != GPIO1 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 754 GPIO_InitStruct.Pin = GPIO_PIN_5;
Mike Fiore 14:f9a77400b622 755 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 756 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 757 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 758 }
Mike Fiore 14:f9a77400b622 759 if (_dot->getWakePin() != GPIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 760 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 14:f9a77400b622 761 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 762 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 763 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 764 }
Mike Fiore 14:f9a77400b622 765 if (_dot->getWakePin() != GPIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 766 GPIO_InitStruct.Pin = GPIO_PIN_2;
Mike Fiore 14:f9a77400b622 767 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 768 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 769 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 770 }
Mike Fiore 14:f9a77400b622 771 if (_dot->getWakePin() != UART1_RX || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 772 GPIO_InitStruct.Pin = GPIO_PIN_10;
Mike Fiore 14:f9a77400b622 773 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 774 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 775 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 776 }
Mike Fiore 14:f9a77400b622 777 #else
Mike Fiore 14:f9a77400b622 778 uint32_t portA[6];
Mike Fiore 14:f9a77400b622 779 uint32_t portB[6];
Mike Fiore 14:f9a77400b622 780 uint32_t portC[6];
Mike Fiore 14:f9a77400b622 781 uint32_t portD[6];
Mike Fiore 14:f9a77400b622 782 uint32_t portH[6];
Mike Fiore 14:f9a77400b622 783
Mike Fiore 14:f9a77400b622 784 //Save the GPIO state.
Mike Fiore 14:f9a77400b622 785 portA[0] = GPIOA->MODER;
Mike Fiore 14:f9a77400b622 786 portA[1] = GPIOA->OTYPER;
Mike Fiore 14:f9a77400b622 787 portA[2] = GPIOA->OSPEEDR;
Mike Fiore 14:f9a77400b622 788 portA[3] = GPIOA->PUPDR;
Mike Fiore 14:f9a77400b622 789 portA[4] = GPIOA->AFR[0];
Mike Fiore 14:f9a77400b622 790 portA[5] = GPIOA->AFR[1];
Mike Fiore 14:f9a77400b622 791
Mike Fiore 14:f9a77400b622 792 portB[0] = GPIOB->MODER;
Mike Fiore 14:f9a77400b622 793 portB[1] = GPIOB->OTYPER;
Mike Fiore 14:f9a77400b622 794 portB[2] = GPIOB->OSPEEDR;
Mike Fiore 14:f9a77400b622 795 portB[3] = GPIOB->PUPDR;
Mike Fiore 14:f9a77400b622 796 portB[4] = GPIOB->AFR[0];
Mike Fiore 14:f9a77400b622 797 portB[5] = GPIOB->AFR[1];
Mike Fiore 14:f9a77400b622 798
Mike Fiore 14:f9a77400b622 799 portC[0] = GPIOC->MODER;
Mike Fiore 14:f9a77400b622 800 portC[1] = GPIOC->OTYPER;
Mike Fiore 14:f9a77400b622 801 portC[2] = GPIOC->OSPEEDR;
Mike Fiore 14:f9a77400b622 802 portC[3] = GPIOC->PUPDR;
Mike Fiore 14:f9a77400b622 803 portC[4] = GPIOC->AFR[0];
Mike Fiore 14:f9a77400b622 804 portC[5] = GPIOC->AFR[1];
Mike Fiore 14:f9a77400b622 805
Mike Fiore 14:f9a77400b622 806 portD[0] = GPIOD->MODER;
Mike Fiore 14:f9a77400b622 807 portD[1] = GPIOD->OTYPER;
Mike Fiore 14:f9a77400b622 808 portD[2] = GPIOD->OSPEEDR;
Mike Fiore 14:f9a77400b622 809 portD[3] = GPIOD->PUPDR;
Mike Fiore 14:f9a77400b622 810 portD[4] = GPIOD->AFR[0];
Mike Fiore 14:f9a77400b622 811 portD[5] = GPIOD->AFR[1];
Mike Fiore 14:f9a77400b622 812
Mike Fiore 14:f9a77400b622 813 portH[0] = GPIOH->MODER;
Mike Fiore 14:f9a77400b622 814 portH[1] = GPIOH->OTYPER;
Mike Fiore 14:f9a77400b622 815 portH[2] = GPIOH->OSPEEDR;
Mike Fiore 14:f9a77400b622 816 portH[3] = GPIOH->PUPDR;
Mike Fiore 14:f9a77400b622 817 portH[4] = GPIOH->AFR[0];
Mike Fiore 14:f9a77400b622 818 portH[5] = GPIOH->AFR[1];
Mike Fiore 14:f9a77400b622 819
Mike Fiore 14:f9a77400b622 820 /* GPIO Ports Clock Enable */
Mike Fiore 14:f9a77400b622 821 __GPIOA_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 822 __GPIOB_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 823 __GPIOC_CLK_ENABLE();
Mike Fiore 14:f9a77400b622 824
Mike Fiore 14:f9a77400b622 825 GPIO_InitTypeDef GPIO_InitStruct;
Mike Fiore 14:f9a77400b622 826
Mike Fiore 14:f9a77400b622 827 // Set port A pins to analog nopull
Jason Reiss 23:4f0a981c0349 828 GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10
Mike Fiore 14:f9a77400b622 829 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
Mike Fiore 14:f9a77400b622 830 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 831 GPIO_InitStruct.Pull = GPIO_NOPULL;
Jason Reiss 23:4f0a981c0349 832 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 833
Mike Fiore 14:f9a77400b622 834 // Set port B pins to analog nopull
Mike Fiore 14:f9a77400b622 835 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
Mike Fiore 14:f9a77400b622 836 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 837 GPIO_InitStruct.Pull = GPIO_NOPULL;
Jason Reiss 23:4f0a981c0349 838 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 839
Mike Fiore 14:f9a77400b622 840 // Set port C pins to analog nopull
Mike Fiore 14:f9a77400b622 841 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
Mike Fiore 14:f9a77400b622 842 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 843 GPIO_InitStruct.Pull = GPIO_NOPULL;
Jason Reiss 23:4f0a981c0349 844 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 845
Mike Fiore 14:f9a77400b622 846 // iterate through potential wake pins - leave the configured wake pin alone if one is needed
Mike Fiore 14:f9a77400b622 847 // XBEE_DIN - PA3
Mike Fiore 14:f9a77400b622 848 // XBEE_DIO2 - PA5
Mike Fiore 14:f9a77400b622 849 // XBEE_DIO3 - PA4
Mike Fiore 14:f9a77400b622 850 // XBEE_DIO4 - PA7
Mike Fiore 14:f9a77400b622 851 // XBEE_DIO5 - PC1
Mike Fiore 14:f9a77400b622 852 // XBEE_DIO6 - PA1
Mike Fiore 14:f9a77400b622 853 // XBEE_DIO7 - PA0
Mike Fiore 14:f9a77400b622 854 // XBEE_SLEEPRQ - PA11
Jason Reiss 23:4f0a981c0349 855
Mike Fiore 14:f9a77400b622 856 if (_dot->getWakePin() != XBEE_DIN || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 857 GPIO_InitStruct.Pin = GPIO_PIN_3;
Mike Fiore 14:f9a77400b622 858 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 859 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 860 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 861 }
Mike Fiore 14:f9a77400b622 862
Mike Fiore 14:f9a77400b622 863 if (_dot->getWakePin() != XBEE_DIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 864 GPIO_InitStruct.Pin = GPIO_PIN_5;
Mike Fiore 14:f9a77400b622 865 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 866 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 867 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 868 }
Mike Fiore 14:f9a77400b622 869
Mike Fiore 14:f9a77400b622 870 if (_dot->getWakePin() != XBEE_DIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 871 GPIO_InitStruct.Pin = GPIO_PIN_4;
Mike Fiore 14:f9a77400b622 872 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 873 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 874 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 875 }
Mike Fiore 14:f9a77400b622 876
Mike Fiore 14:f9a77400b622 877 if (_dot->getWakePin() != XBEE_DIO4 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 878 GPIO_InitStruct.Pin = GPIO_PIN_7;
Mike Fiore 14:f9a77400b622 879 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 880 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 881 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 882 }
Mike Fiore 14:f9a77400b622 883
Mike Fiore 14:f9a77400b622 884 if (_dot->getWakePin() != XBEE_DIO5 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 885 GPIO_InitStruct.Pin = GPIO_PIN_1;
Mike Fiore 14:f9a77400b622 886 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 887 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 888 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 889 }
Mike Fiore 14:f9a77400b622 890
Mike Fiore 14:f9a77400b622 891 if (_dot->getWakePin() != XBEE_DIO6 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 892 GPIO_InitStruct.Pin = GPIO_PIN_1;
Mike Fiore 14:f9a77400b622 893 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 894 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 895 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 896 }
Mike Fiore 14:f9a77400b622 897
Mike Fiore 14:f9a77400b622 898 if (_dot->getWakePin() != XBEE_DIO7 || _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 899 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 14:f9a77400b622 900 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 901 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 902 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 903 }
Mike Fiore 14:f9a77400b622 904
Mike Fiore 14:f9a77400b622 905 if (_dot->getWakePin() != XBEE_SLEEPRQ|| _dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 14:f9a77400b622 906 GPIO_InitStruct.Pin = GPIO_PIN_11;
Mike Fiore 14:f9a77400b622 907 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 14:f9a77400b622 908 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 14:f9a77400b622 909 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 14:f9a77400b622 910 }
Jason Reiss 23:4f0a981c0349 911
Mike Fiore 14:f9a77400b622 912 #endif
Mike Fiore 4:666017851052 913 _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
Mike Fiore 14:f9a77400b622 914
Mike Fiore 14:f9a77400b622 915 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 14:f9a77400b622 916 xdot_restore_gpio_state();
Mike Fiore 14:f9a77400b622 917 #else
Mike Fiore 14:f9a77400b622 918 //Restore the GPIO state.
Mike Fiore 14:f9a77400b622 919 GPIOA->MODER = portA[0];
Mike Fiore 14:f9a77400b622 920 GPIOA->OTYPER = portA[1];
Mike Fiore 14:f9a77400b622 921 GPIOA->OSPEEDR = portA[2];
Mike Fiore 14:f9a77400b622 922 GPIOA->PUPDR = portA[3];
Mike Fiore 14:f9a77400b622 923 GPIOA->AFR[0] = portA[4];
Mike Fiore 14:f9a77400b622 924 GPIOA->AFR[1] = portA[5];
Mike Fiore 14:f9a77400b622 925
Mike Fiore 14:f9a77400b622 926 GPIOB->MODER = portB[0];
Mike Fiore 14:f9a77400b622 927 GPIOB->OTYPER = portB[1];
Mike Fiore 14:f9a77400b622 928 GPIOB->OSPEEDR = portB[2];
Mike Fiore 14:f9a77400b622 929 GPIOB->PUPDR = portB[3];
Mike Fiore 14:f9a77400b622 930 GPIOB->AFR[0] = portB[4];
Mike Fiore 14:f9a77400b622 931 GPIOB->AFR[1] = portB[5];
Mike Fiore 14:f9a77400b622 932
Mike Fiore 14:f9a77400b622 933 GPIOC->MODER = portC[0];
Mike Fiore 14:f9a77400b622 934 GPIOC->OTYPER = portC[1];
Mike Fiore 14:f9a77400b622 935 GPIOC->OSPEEDR = portC[2];
Mike Fiore 14:f9a77400b622 936 GPIOC->PUPDR = portC[3];
Mike Fiore 14:f9a77400b622 937 GPIOC->AFR[0] = portC[4];
Mike Fiore 14:f9a77400b622 938 GPIOC->AFR[1] = portC[5];
Mike Fiore 14:f9a77400b622 939
Mike Fiore 14:f9a77400b622 940 GPIOD->MODER = portD[0];
Mike Fiore 14:f9a77400b622 941 GPIOD->OTYPER = portD[1];
Mike Fiore 14:f9a77400b622 942 GPIOD->OSPEEDR = portD[2];
Mike Fiore 14:f9a77400b622 943 GPIOD->PUPDR = portD[3];
Mike Fiore 14:f9a77400b622 944 GPIOD->AFR[0] = portD[4];
Mike Fiore 14:f9a77400b622 945 GPIOD->AFR[1] = portD[5];
Mike Fiore 14:f9a77400b622 946
Mike Fiore 14:f9a77400b622 947 GPIOH->MODER = portH[0];
Mike Fiore 14:f9a77400b622 948 GPIOH->OTYPER = portH[1];
Mike Fiore 14:f9a77400b622 949 GPIOH->OSPEEDR = portH[2];
Mike Fiore 14:f9a77400b622 950 GPIOH->PUPDR = portH[3];
Mike Fiore 14:f9a77400b622 951 GPIOH->AFR[0] = portH[4];
Mike Fiore 14:f9a77400b622 952 GPIOH->AFR[1] = portH[5];
Mike Fiore 14:f9a77400b622 953 #endif
Mike Fiore 14:f9a77400b622 954
Mike Fiore 14:f9a77400b622 955 _serial.rxClear();
Mike Fiore 14:f9a77400b622 956 _serial.txClear();
Jason Reiss 23:4f0a981c0349 957 Fota::getInstance()->fixEventQueue();
Mike Fiore 14:f9a77400b622 958 }
Mike Fiore 14:f9a77400b622 959
Mike Fiore 14:f9a77400b622 960 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
Jason Reiss 23:4f0a981c0349 961 switch(format) {
Jason Reiss 23:4f0a981c0349 962 case(mDot::HEXADECIMAL):
Jason Reiss 23:4f0a981c0349 963 return mts::Text::bin2hexString(data);
Jason Reiss 23:4f0a981c0349 964
Jason Reiss 23:4f0a981c0349 965 case(mDot::BINARY):
Jason Reiss 23:4f0a981c0349 966 return std::string(data.begin(), data.end());
Jason Reiss 23:4f0a981c0349 967
Jason Reiss 23:4f0a981c0349 968 case(mDot::EXTENDED):
Jason Reiss 23:4f0a981c0349 969 return formatPacket(data);
Jason Reiss 23:4f0a981c0349 970
Jason Reiss 23:4f0a981c0349 971 default:
Jason Reiss 23:4f0a981c0349 972 return "";
Jason Reiss 23:4f0a981c0349 973 }
Mike Fiore 1:e52ae6584f1c 974 }
Mike Fiore 1:e52ae6584f1c 975
Mike Fiore 1:e52ae6584f1c 976 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
Mike Fiore 1:e52ae6584f1c 977 Timer timer;
Mike Fiore 1:e52ae6584f1c 978
Mike Fiore 1:e52ae6584f1c 979 timer.start();
Mike Fiore 1:e52ae6584f1c 980 while (timer.read_ms() < timeout) {
Mike Fiore 1:e52ae6584f1c 981
Mike Fiore 1:e52ae6584f1c 982 if (dot != NULL) {
Mike Fiore 1:e52ae6584f1c 983 if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
Mike Fiore 1:e52ae6584f1c 984 return false;
Mike Fiore 1:e52ae6584f1c 985 }
Mike Fiore 1:e52ae6584f1c 986 }
Mike Fiore 1:e52ae6584f1c 987
Mike Fiore 9:ff62b20f7000 988 if (_serialp != NULL && _serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 989 _serialp->clearEscaped();
Mike Fiore 9:ff62b20f7000 990 return true;
Mike Fiore 1:e52ae6584f1c 991 }
Mike Fiore 1:e52ae6584f1c 992
Mike Fiore 1:e52ae6584f1c 993 osDelay(10);
Mike Fiore 1:e52ae6584f1c 994 }
Mike Fiore 1:e52ae6584f1c 995
Mike Fiore 1:e52ae6584f1c 996 return false;
Mike Fiore 1:e52ae6584f1c 997 }
Mike Fiore 1:e52ae6584f1c 998
Mike Fiore 9:ff62b20f7000 999 void CommandTerminal::wakeup(void) {
Mike Fiore 9:ff62b20f7000 1000 }
Mike Fiore 9:ff62b20f7000 1001
jenkins@jenkinsdm1 18:63f098f042b2 1002 void CommandTerminal::RadioEvent::PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries, uint32_t address, bool dupRx) {
jenkins@jenkinsdm1 18:63f098f042b2 1003 mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, slot, retries, address, dupRx);
jenkins@jenkinsdm1 18:63f098f042b2 1004 if(port == 200 || port == 201 || port == 202) {
Jason Reiss 23:4f0a981c0349 1005 Fota::getInstance()->processCmd(payload, port, size);
jenkins@jenkinsdm1 18:63f098f042b2 1006 }
jenkins@jenkinsdm1 18:63f098f042b2 1007 if (serial_data_mode && port != 0) {
Mike Fiore 14:f9a77400b622 1008 logDebug("Rx %d bytes", size);
Mike Fiore 14:f9a77400b622 1009 if (size > 0) {
Jason Reiss 23:4f0a981c0349 1010 if(CommandTerminal::Dot()->getRxOutput() == mDot::EXTENDED) {
Jason Reiss 23:4f0a981c0349 1011 formatPacket(RxPayload, size);
Jason Reiss 23:4f0a981c0349 1012 _rxAddress = address;
Jason Reiss 23:4f0a981c0349 1013 } else {
Jason Reiss 23:4f0a981c0349 1014 CommandTerminal::Serial()->write((char*) RxPayload, RxPayloadSize);
Jason Reiss 23:4f0a981c0349 1015 }
Mike Fiore 9:ff62b20f7000 1016 }
Jason Reiss 23:4f0a981c0349 1017 if (!CommandTerminal::Serial()->readable()
Jason Reiss 23:4f0a981c0349 1018 && (_dot->getAckRequested()
Jason Reiss 23:4f0a981c0349 1019 || _dot->hasMacCommands())
Jason Reiss 23:4f0a981c0349 1020 && (_dot->getClass() == "C" || _dot->getSettings()->Session.Class == lora::CLASS_B)) {
Mike Fiore 14:f9a77400b622 1021 _sendAck = true;
Mike Fiore 9:ff62b20f7000 1022 }
Mike Fiore 9:ff62b20f7000 1023 }
Mike Fiore 1:e52ae6584f1c 1024 }
Mike Fiore 9:ff62b20f7000 1025
jenkins@jenkinsdm1 18:63f098f042b2 1026 uint8_t CommandTerminal::getBatteryLevel() {
jenkins@jenkinsdm1 18:63f098f042b2 1027 return _battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1028 }
jenkins@jenkinsdm1 18:63f098f042b2 1029
Jason Reiss 23:4f0a981c0349 1030 void CommandTerminal::setBatteryLevel(uint8_t battery_level) {
jenkins@jenkinsdm1 18:63f098f042b2 1031 _battery_level = battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1032 }
jenkins@jenkinsdm1 18:63f098f042b2 1033
Jason Reiss 23:4f0a981c0349 1034 void CommandTerminal::formatPacket(uint8_t* payload, uint16_t size) {
Jason Reiss 23:4f0a981c0349 1035 uint32_t fcnt = _dot->getDownLinkCounter();
Jason Reiss 23:4f0a981c0349 1036
Jason Reiss 23:4f0a981c0349 1037 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1038 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1039 } else {
Jason Reiss 23:4f0a981c0349 1040 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1041 }
Jason Reiss 23:4f0a981c0349 1042
Jason Reiss 23:4f0a981c0349 1043 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1044 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1045 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1046 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1047 f_data[5] = fcnt & 0xFF;
Jason Reiss 23:4f0a981c0349 1048 f_data[6] = (fcnt >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1049 f_data[7] = (fcnt >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1050 f_data[8] = (fcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1051 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1052
Jason Reiss 23:4f0a981c0349 1053 for(int i = 0; i < size; i++)
Jason Reiss 23:4f0a981c0349 1054 f_data[i+10] = payload[i];
Jason Reiss 23:4f0a981c0349 1055
Jason Reiss 23:4f0a981c0349 1056 CommandTerminal::Serial()->write((char*)f_data, size + 10);
Jason Reiss 23:4f0a981c0349 1057 }
Jason Reiss 23:4f0a981c0349 1058
Jason Reiss 23:4f0a981c0349 1059
Jason Reiss 23:4f0a981c0349 1060 std::string CommandTerminal::formatPacket(std::vector<uint8_t> payload) {
Jason Reiss 23:4f0a981c0349 1061 uint32_t fcnt = _dot->getDownLinkCounter();
Jason Reiss 23:4f0a981c0349 1062
Jason Reiss 23:4f0a981c0349 1063 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1064 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1065 } else {
Jason Reiss 23:4f0a981c0349 1066 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1067 }
Jason Reiss 23:4f0a981c0349 1068
Jason Reiss 23:4f0a981c0349 1069 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1070 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1071 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1072 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1073 f_data[5] = fcnt & 0xFF;
Jason Reiss 23:4f0a981c0349 1074 f_data[6] = (fcnt >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1075 f_data[7] = (fcnt >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1076 f_data[8] = (fcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1077 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1078
Jason Reiss 23:4f0a981c0349 1079 for(int i = 0; i < payload.size(); i++)
Jason Reiss 23:4f0a981c0349 1080 f_data[i+10] = payload.at(i);
Jason Reiss 23:4f0a981c0349 1081
Jason Reiss 23:4f0a981c0349 1082 std::string ret((char*)f_data, payload.size() + 10);
Jason Reiss 23:4f0a981c0349 1083 return ret;
Jason Reiss 23:4f0a981c0349 1084 }
Jason Reiss 23:4f0a981c0349 1085
Jason Reiss 23:4f0a981c0349 1086
Jason Reiss 23:4f0a981c0349 1087
Jason Reiss 23:4f0a981c0349 1088 void CommandTerminal::formatPacketSDSend(std::vector<uint8_t> &payload) {
Jason Reiss 23:4f0a981c0349 1089 if(payload.size() >= 3) {
Jason Reiss 23:4f0a981c0349 1090 _dot->setAppPort(payload[0]);
Jason Reiss 23:4f0a981c0349 1091 _dot->setRepeat(0);
Jason Reiss 23:4f0a981c0349 1092 _dot->setAck(0);
Jason Reiss 23:4f0a981c0349 1093 switch(payload[1]) {
Jason Reiss 23:4f0a981c0349 1094 case 0:
Jason Reiss 23:4f0a981c0349 1095 _dot->setAck(payload[2]);
Jason Reiss 23:4f0a981c0349 1096 break;
Jason Reiss 23:4f0a981c0349 1097 case 1:
Jason Reiss 23:4f0a981c0349 1098 _dot->setRepeat(payload[2]);
Jason Reiss 23:4f0a981c0349 1099 break;
Jason Reiss 23:4f0a981c0349 1100 default:
Jason Reiss 23:4f0a981c0349 1101 break;
Jason Reiss 23:4f0a981c0349 1102 }
Jason Reiss 23:4f0a981c0349 1103 payload.erase(payload.begin(), payload.begin()+3);
Jason Reiss 23:4f0a981c0349 1104 }
Jason Reiss 23:4f0a981c0349 1105 }
Jason Reiss 23:4f0a981c0349 1106
Jason Reiss 23:4f0a981c0349 1107
Jason Reiss 23:4f0a981c0349 1108
Mike Fiore 9:ff62b20f7000 1109 CommandTerminal::~CommandTerminal() {
Mike Fiore 9:ff62b20f7000 1110 delete _events;
Mike Fiore 9:ff62b20f7000 1111 }