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:
Mike Fiore
Date:
Fri Jul 10 09:43:56 2015 -0500
Revision:
2:e5eebd74d36d
Parent:
1:e52ae6584f1c
Child:
4:666017851052
update from rev 6d77074fdfa315ba86bedecc44515b11bfa6e9a0 - add support for commas in payloads of +SEND and +SENDI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike Fiore 1:e52ae6584f1c 1 #include "ctype.h"
Mike Fiore 1:e52ae6584f1c 2 #include "CommandTerminal.h"
Mike Fiore 1:e52ae6584f1c 3 #include "Command.h"
Mike Fiore 1:e52ae6584f1c 4 #include <cstdarg>
Mike Fiore 1:e52ae6584f1c 5
Mike Fiore 1:e52ae6584f1c 6 extern "C" {
Mike Fiore 1:e52ae6584f1c 7 #include "wakeup.h"
Mike Fiore 1:e52ae6584f1c 8 extern void pin_function(PinName pin, int data);
Mike Fiore 1:e52ae6584f1c 9 }
Mike Fiore 1:e52ae6584f1c 10
Mike Fiore 1:e52ae6584f1c 11 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
Mike Fiore 1:e52ae6584f1c 12 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
Mike Fiore 1:e52ae6584f1c 13
Mike Fiore 1:e52ae6584f1c 14 const char CommandTerminal::newline[] = "\r\n";
Mike Fiore 1:e52ae6584f1c 15
Mike Fiore 1:e52ae6584f1c 16 // Command error text...
Mike Fiore 1:e52ae6584f1c 17 const char CommandTerminal::command_error[] = "Command not found!\r\n";
Mike Fiore 1:e52ae6584f1c 18
Mike Fiore 1:e52ae6584f1c 19 // Response texts...
Mike Fiore 1:e52ae6584f1c 20 const char CommandTerminal::help[] = "\r\nHelp\r\n";
Mike Fiore 1:e52ae6584f1c 21 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
Mike Fiore 1:e52ae6584f1c 22 const char CommandTerminal::done[] = "\r\nOK\r\n";
Mike Fiore 1:e52ae6584f1c 23 const char CommandTerminal::error[] = "\r\nERROR\r\n";
Mike Fiore 1:e52ae6584f1c 24
Mike Fiore 1:e52ae6584f1c 25 // Escape sequence...
Mike Fiore 1:e52ae6584f1c 26 const char CommandTerminal::escape_sequence[] = "+++";
Mike Fiore 1:e52ae6584f1c 27
Mike Fiore 1:e52ae6584f1c 28 mts::MTSSerial* CommandTerminal::_serialp = NULL;
Mike Fiore 1:e52ae6584f1c 29
Mike Fiore 1:e52ae6584f1c 30 void CommandTerminal::addCommand(Command* cmd) {
Mike Fiore 1:e52ae6584f1c 31 _commands.push_back(cmd);
Mike Fiore 1:e52ae6584f1c 32 }
Mike Fiore 1:e52ae6584f1c 33
Mike Fiore 1:e52ae6584f1c 34 CommandTerminal::CommandTerminal(mts::MTSSerial& serial, mDot* dot)
Mike Fiore 1:e52ae6584f1c 35 :
Mike Fiore 1:e52ae6584f1c 36 _serial(serial),
Mike Fiore 1:e52ae6584f1c 37 _dot(dot),
Mike Fiore 1:e52ae6584f1c 38 _mode(mDot::COMMAND_MODE),
Mike Fiore 1:e52ae6584f1c 39 _sleep_standby(false),
Mike Fiore 1:e52ae6584f1c 40 _xbee_on_sleep(XBEE_ON_SLEEP),
Mike Fiore 1:e52ae6584f1c 41 _serial_up(false) {
Mike Fiore 1:e52ae6584f1c 42
Mike Fiore 1:e52ae6584f1c 43 _serialp = &serial;
Mike Fiore 1:e52ae6584f1c 44
Mike Fiore 1:e52ae6584f1c 45 wakeup_init(_dot->getSerialWakeInterval());
Mike Fiore 1:e52ae6584f1c 46
Mike Fiore 1:e52ae6584f1c 47 addCommand(new CmdAttention(_dot));
Mike Fiore 1:e52ae6584f1c 48 addCommand(new CmdIdentification(_dot, serial));
Mike Fiore 1:e52ae6584f1c 49 addCommand(new CmdResetCpu(_dot, serial));
Mike Fiore 1:e52ae6584f1c 50 addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE0/1", "ATE0: disable, ATE1: enable"));
Mike Fiore 1:e52ae6584f1c 51 addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV0/1", "ATV0: disable, ATV1: enable"));
Mike Fiore 1:e52ae6584f1c 52
Mike Fiore 1:e52ae6584f1c 53 addCommand(new CmdFactoryDefault(_dot));
Mike Fiore 1:e52ae6584f1c 54 addCommand(new CmdSaveConfig(_dot));
Mike Fiore 1:e52ae6584f1c 55 addCommand(new CmdDisplayConfig(_dot, serial));
Mike Fiore 1:e52ae6584f1c 56 addCommand(new CmdDisplayStats(_dot, serial));
Mike Fiore 1:e52ae6584f1c 57 addCommand(new CmdSerialBaudRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 58 addCommand(new CmdDebugBaudRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 59 addCommand(new CmdStartUpMode(_dot, serial));
Mike Fiore 1:e52ae6584f1c 60
Mike Fiore 1:e52ae6584f1c 61 addCommand(new CmdFrequencyBand(_dot, serial));
Mike Fiore 1:e52ae6584f1c 62 addCommand(new CmdFrequencySubBand(_dot, serial));
Mike Fiore 1:e52ae6584f1c 63 addCommand(new CmdPublicNetwork(_dot, serial));
Mike Fiore 1:e52ae6584f1c 64 addCommand(new CmdDeviceId(_dot, serial));
Mike Fiore 1:e52ae6584f1c 65
Mike Fiore 1:e52ae6584f1c 66 addCommand(new CmdNetworkAddress(_dot, serial));
Mike Fiore 1:e52ae6584f1c 67 addCommand(new CmdNetworkSessionKey(_dot, serial));
Mike Fiore 1:e52ae6584f1c 68 addCommand(new CmdDataSessionKey(_dot, serial));
Mike Fiore 1:e52ae6584f1c 69 addCommand(new CmdNetworkKey(_dot, serial));
Mike Fiore 1:e52ae6584f1c 70 addCommand(new CmdNetworkId(_dot, serial));
Mike Fiore 1:e52ae6584f1c 71
Mike Fiore 1:e52ae6584f1c 72 addCommand(new CmdJoinRequest(_dot, serial));
Mike Fiore 1:e52ae6584f1c 73 addCommand(new CmdJoinRetries(_dot, serial));
Mike Fiore 1:e52ae6584f1c 74 addCommand(new CmdNetworkJoinMode(_dot, serial));
Mike Fiore 1:e52ae6584f1c 75 addCommand(new CmdNetworkJoinStatus(_dot, serial));
Mike Fiore 1:e52ae6584f1c 76 addCommand(new CmdNetworkLinkCheck(_dot, serial));
Mike Fiore 1:e52ae6584f1c 77 addCommand(new CmdLinkCheckCount(_dot, serial));
Mike Fiore 1:e52ae6584f1c 78 addCommand(new CmdLinkCheckThreshold(_dot, serial));
Mike Fiore 1:e52ae6584f1c 79 addCommand(new CmdEncryption(_dot, serial));
Mike Fiore 1:e52ae6584f1c 80
Mike Fiore 1:e52ae6584f1c 81 addCommand(new CmdRssi(_dot, serial));
Mike Fiore 1:e52ae6584f1c 82 addCommand(new CmdSnr(_dot, serial));
Mike Fiore 1:e52ae6584f1c 83 addCommand(new CmdDataPending(_dot, serial));
Mike Fiore 1:e52ae6584f1c 84
Mike Fiore 1:e52ae6584f1c 85 addCommand(new CmdTxDataRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 86 addCommand(new CmdTxPower(_dot, serial));
Mike Fiore 1:e52ae6584f1c 87 addCommand(new CmdTxFrequency(_dot, serial));
Mike Fiore 1:e52ae6584f1c 88 addCommand(new CmdTxInverted(_dot, serial));
Mike Fiore 1:e52ae6584f1c 89 addCommand(new CmdTxWait(_dot, serial));
Mike Fiore 1:e52ae6584f1c 90 addCommand(new CmdTxChannel(_dot, serial));
Mike Fiore 1:e52ae6584f1c 91 addCommand(new CmdTxNextMs(_dot, serial));
Mike Fiore 1:e52ae6584f1c 92 addCommand(new CmdTimeOnAir(_dot, serial));
Mike Fiore 1:e52ae6584f1c 93
Mike Fiore 1:e52ae6584f1c 94 addCommand(new CmdRxDataRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 95 addCommand(new CmdRxFrequency(_dot, serial));
Mike Fiore 1:e52ae6584f1c 96 addCommand(new CmdRxOutput(_dot, serial));
Mike Fiore 1:e52ae6584f1c 97 addCommand(new CmdRxInverted(_dot, serial));
Mike Fiore 1:e52ae6584f1c 98
Mike Fiore 1:e52ae6584f1c 99 addCommand(new CmdErrorCorrection(_dot, serial));
Mike Fiore 1:e52ae6584f1c 100 addCommand(new CmdCRC(_dot, serial));
Mike Fiore 1:e52ae6584f1c 101 addCommand(new CmdAdaptiveDataRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 102
Mike Fiore 1:e52ae6584f1c 103 addCommand(new CmdACKAttempts(_dot, serial));
Mike Fiore 1:e52ae6584f1c 104
Mike Fiore 1:e52ae6584f1c 105 addCommand(new CmdSendString(_dot, serial));
Mike Fiore 1:e52ae6584f1c 106 addCommand(new CmdSendStringHighBW(_dot, serial));
Mike Fiore 1:e52ae6584f1c 107 addCommand(new CmdSendBinary(_dot, serial));
Mike Fiore 1:e52ae6584f1c 108 addCommand(new CmdSendStringOnInterval(_dot, serial));
Mike Fiore 1:e52ae6584f1c 109 addCommand(new CmdReceiveOnce(_dot, serial));
Mike Fiore 1:e52ae6584f1c 110 addCommand(new CmdReceiveContinuous(_dot, serial));
Mike Fiore 1:e52ae6584f1c 111
Mike Fiore 1:e52ae6584f1c 112 addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Reads serial data and sends Lora packets (escape sequence: +++)"));
Mike Fiore 1:e52ae6584f1c 113 addCommand(new CmdSerialWakeInterval(_dot, serial));
Mike Fiore 1:e52ae6584f1c 114 addCommand(new CmdSerialWakeDelay(_dot, serial));
Mike Fiore 1:e52ae6584f1c 115 addCommand(new CmdSerialReceiveTimeout(_dot, serial));
Mike Fiore 1:e52ae6584f1c 116 addCommand(new CmdPing(_dot, serial));
Mike Fiore 1:e52ae6584f1c 117 addCommand(new CmdLogLevel(_dot, serial));
Mike Fiore 1:e52ae6584f1c 118 }
Mike Fiore 1:e52ae6584f1c 119
Mike Fiore 1:e52ae6584f1c 120 void CommandTerminal::printHelp() {
Mike Fiore 1:e52ae6584f1c 121 const char* name = NULL;
Mike Fiore 1:e52ae6584f1c 122 const char* text = NULL;
Mike Fiore 1:e52ae6584f1c 123 const char* desc = NULL;
Mike Fiore 1:e52ae6584f1c 124 const char* tab = "\t";
Mike Fiore 1:e52ae6584f1c 125
Mike Fiore 1:e52ae6584f1c 126 std::string header("Command");
Mike Fiore 1:e52ae6584f1c 127 header.append(tab);
Mike Fiore 1:e52ae6584f1c 128 header.append(tab);
Mike Fiore 1:e52ae6584f1c 129 header.append("Name");
Mike Fiore 1:e52ae6584f1c 130 header.append(tab);
Mike Fiore 1:e52ae6584f1c 131 header.append(tab);
Mike Fiore 1:e52ae6584f1c 132 header.append(tab);
Mike Fiore 1:e52ae6584f1c 133 header.append("Description");
Mike Fiore 1:e52ae6584f1c 134
Mike Fiore 1:e52ae6584f1c 135 write(newline);
Mike Fiore 1:e52ae6584f1c 136 write(header.c_str());
Mike Fiore 1:e52ae6584f1c 137 write(newline);
Mike Fiore 1:e52ae6584f1c 138 write(newline);
Mike Fiore 1:e52ae6584f1c 139 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) {
Mike Fiore 1:e52ae6584f1c 140 name = (*it)->name();
Mike Fiore 1:e52ae6584f1c 141 text = (*it)->text();
Mike Fiore 1:e52ae6584f1c 142 desc = (*it)->desc();
Mike Fiore 1:e52ae6584f1c 143 write(text);
Mike Fiore 1:e52ae6584f1c 144 if (strlen(text) < 8)
Mike Fiore 1:e52ae6584f1c 145 write(tab);
Mike Fiore 1:e52ae6584f1c 146 write(tab);
Mike Fiore 1:e52ae6584f1c 147 write(name);
Mike Fiore 1:e52ae6584f1c 148 if (strlen(name) < 8)
Mike Fiore 1:e52ae6584f1c 149 write(tab);
Mike Fiore 1:e52ae6584f1c 150 if (strlen(name) < 16)
Mike Fiore 1:e52ae6584f1c 151 write(tab);
Mike Fiore 1:e52ae6584f1c 152 write(tab);
Mike Fiore 1:e52ae6584f1c 153 write(desc);
Mike Fiore 1:e52ae6584f1c 154 write(newline);
Mike Fiore 1:e52ae6584f1c 155 }
Mike Fiore 1:e52ae6584f1c 156
Mike Fiore 1:e52ae6584f1c 157 write(newline);
Mike Fiore 1:e52ae6584f1c 158 }
Mike Fiore 1:e52ae6584f1c 159
Mike Fiore 1:e52ae6584f1c 160 bool CommandTerminal::writeable() {
Mike Fiore 1:e52ae6584f1c 161 return _serial.writeable();
Mike Fiore 1:e52ae6584f1c 162 }
Mike Fiore 1:e52ae6584f1c 163
Mike Fiore 1:e52ae6584f1c 164 bool CommandTerminal::readable() {
Mike Fiore 1:e52ae6584f1c 165 return _serial.readable();
Mike Fiore 1:e52ae6584f1c 166 }
Mike Fiore 1:e52ae6584f1c 167
Mike Fiore 1:e52ae6584f1c 168 char CommandTerminal::read() {
Mike Fiore 1:e52ae6584f1c 169 char ch;
Mike Fiore 1:e52ae6584f1c 170 _serial.read(&ch, 1);
Mike Fiore 1:e52ae6584f1c 171 return ch;
Mike Fiore 1:e52ae6584f1c 172 }
Mike Fiore 1:e52ae6584f1c 173
Mike Fiore 1:e52ae6584f1c 174 void CommandTerminal::write(const char* message) {
Mike Fiore 1:e52ae6584f1c 175 while (!writeable())
Mike Fiore 1:e52ae6584f1c 176 ;
Mike Fiore 1:e52ae6584f1c 177 _serial.write(message, strlen(message));
Mike Fiore 1:e52ae6584f1c 178 }
Mike Fiore 1:e52ae6584f1c 179
Mike Fiore 1:e52ae6584f1c 180 void CommandTerminal::writef(const char* format, ...) {
Mike Fiore 1:e52ae6584f1c 181 char buff[256];
Mike Fiore 1:e52ae6584f1c 182
Mike Fiore 1:e52ae6584f1c 183 va_list ap;
Mike Fiore 1:e52ae6584f1c 184 va_start(ap, format);
Mike Fiore 1:e52ae6584f1c 185 int size = vsnprintf(buff, 256, format, ap);
Mike Fiore 1:e52ae6584f1c 186 while (!writeable())
Mike Fiore 1:e52ae6584f1c 187 ;
Mike Fiore 1:e52ae6584f1c 188 _serial.write(buff, size);
Mike Fiore 1:e52ae6584f1c 189 va_end(ap);
Mike Fiore 1:e52ae6584f1c 190 }
Mike Fiore 1:e52ae6584f1c 191
Mike Fiore 1:e52ae6584f1c 192 void CommandTerminal::serial_loop() {
Mike Fiore 1:e52ae6584f1c 193 Timer serial_read_timer;
Mike Fiore 1:e52ae6584f1c 194 std::vector<uint8_t> serial_buffer;
Mike Fiore 1:e52ae6584f1c 195 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 196 Timer escape_timer;
Mike Fiore 1:e52ae6584f1c 197 int escape_delay = 100;
Mike Fiore 1:e52ae6584f1c 198 uint8_t max_send_size;
Mike Fiore 1:e52ae6584f1c 199
Mike Fiore 1:e52ae6584f1c 200 _serial_up = true;
Mike Fiore 1:e52ae6584f1c 201 _xbee_on_sleep = GPIO_PIN_SET;
Mike Fiore 1:e52ae6584f1c 202
Mike Fiore 1:e52ae6584f1c 203 if (_dot->getFrequencyBand() == mDot::FB_915)
Mike Fiore 1:e52ae6584f1c 204 max_send_size = mDot::MaxLengths_915[_dot->getTxDataRate()];
Mike Fiore 1:e52ae6584f1c 205 else
Mike Fiore 1:e52ae6584f1c 206 max_send_size = mDot::MaxLengths_868[_dot->getTxDataRate()];
Mike Fiore 1:e52ae6584f1c 207
Mike Fiore 1:e52ae6584f1c 208 DEBUG_PRINTF("Awake\r\n");
Mike Fiore 1:e52ae6584f1c 209 wakeup(_sleep_standby);
Mike Fiore 1:e52ae6584f1c 210
Mike Fiore 1:e52ae6584f1c 211 char ch;
Mike Fiore 1:e52ae6584f1c 212
Mike Fiore 1:e52ae6584f1c 213 if (readable()) {
Mike Fiore 1:e52ae6584f1c 214 ch = read();
Mike Fiore 1:e52ae6584f1c 215 serial_buffer.push_back(ch);
Mike Fiore 1:e52ae6584f1c 216
Mike Fiore 1:e52ae6584f1c 217 if (escape_timer.read_ms() > escape_delay && ch == '+') {
Mike Fiore 1:e52ae6584f1c 218 escape_buffer += ch;
Mike Fiore 1:e52ae6584f1c 219 escape_timer.reset();
Mike Fiore 1:e52ae6584f1c 220 } else {
Mike Fiore 1:e52ae6584f1c 221 _serial_up = true;
Mike Fiore 1:e52ae6584f1c 222 escape_buffer.clear();
Mike Fiore 1:e52ae6584f1c 223 }
Mike Fiore 1:e52ae6584f1c 224
Mike Fiore 1:e52ae6584f1c 225 if (escape_buffer.length() == 3 && escape_buffer.find(escape_sequence) == 0) {
Mike Fiore 1:e52ae6584f1c 226 _mode = mDot::COMMAND_MODE;
Mike Fiore 1:e52ae6584f1c 227 DEBUG_PRINTF("Exit serial mode\r\n");
Mike Fiore 1:e52ae6584f1c 228 escape_timer.stop();
Mike Fiore 1:e52ae6584f1c 229 escape_buffer.clear();
Mike Fiore 1:e52ae6584f1c 230 write(done);
Mike Fiore 1:e52ae6584f1c 231 return;
Mike Fiore 1:e52ae6584f1c 232 }
Mike Fiore 1:e52ae6584f1c 233 }
Mike Fiore 1:e52ae6584f1c 234
Mike Fiore 1:e52ae6584f1c 235 if (_serial_up) {
Mike Fiore 1:e52ae6584f1c 236 osDelay(_dot->getSerialWakeDelay());
Mike Fiore 1:e52ae6584f1c 237
Mike Fiore 1:e52ae6584f1c 238 serial_read_timer.start();
Mike Fiore 1:e52ae6584f1c 239 while (_serial_up && serial_read_timer.read_ms() < _dot->getSerialReceiveTimeout()) {
Mike Fiore 1:e52ae6584f1c 240 while (readable() && serial_buffer.size() < max_send_size) {
Mike Fiore 1:e52ae6584f1c 241 serial_buffer.push_back(read());
Mike Fiore 1:e52ae6584f1c 242 serial_read_timer.reset();
Mike Fiore 1:e52ae6584f1c 243 }
Mike Fiore 1:e52ae6584f1c 244 }
Mike Fiore 1:e52ae6584f1c 245 serial_read_timer.stop(), serial_read_timer.reset();
Mike Fiore 1:e52ae6584f1c 246
Mike Fiore 1:e52ae6584f1c 247 if (!serial_buffer.empty()) {
Mike Fiore 1:e52ae6584f1c 248 _serial_up = false;
Mike Fiore 1:e52ae6584f1c 249 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 1:e52ae6584f1c 250 if (!_dot->getIsTransmitting()) {
Mike Fiore 1:e52ae6584f1c 251 std::vector<uint8_t> recv_buffer;
Mike Fiore 1:e52ae6584f1c 252 DEBUG_PRINTF("Received serial data, sending out radio.\r\n");
Mike Fiore 1:e52ae6584f1c 253
Mike Fiore 1:e52ae6584f1c 254 if (!_dot->send(serial_buffer))
Mike Fiore 1:e52ae6584f1c 255 DEBUG_PRINTF("Send failed.\r\n");
Mike Fiore 1:e52ae6584f1c 256 if (_dot->recv(recv_buffer))
Mike Fiore 1:e52ae6584f1c 257 _serial.writef("%s\r\n", formatPacketData(recv_buffer, _dot->getRxOutput()).c_str());
Mike Fiore 1:e52ae6584f1c 258 } else {
Mike Fiore 1:e52ae6584f1c 259 DEBUG_PRINTF("Radio is busy, cannot send.\r\n");
Mike Fiore 1:e52ae6584f1c 260 }
Mike Fiore 1:e52ae6584f1c 261
Mike Fiore 1:e52ae6584f1c 262 serial_buffer.clear();
Mike Fiore 1:e52ae6584f1c 263 } else {
Mike Fiore 1:e52ae6584f1c 264 DEBUG_PRINTF("No data received from serial to send.\r\n");
Mike Fiore 1:e52ae6584f1c 265 }
Mike Fiore 1:e52ae6584f1c 266 _serial_up = false;
Mike Fiore 1:e52ae6584f1c 267 }
Mike Fiore 1:e52ae6584f1c 268 sleep(_sleep_standby);
Mike Fiore 1:e52ae6584f1c 269 }
Mike Fiore 1:e52ae6584f1c 270
Mike Fiore 1:e52ae6584f1c 271 bool CommandTerminal::autoJoinCheck() {
Mike Fiore 1:e52ae6584f1c 272
Mike Fiore 1:e52ae6584f1c 273 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 274 char ch;
Mike Fiore 1:e52ae6584f1c 275 int sleep = 1000;
Mike Fiore 1:e52ae6584f1c 276 int escape_timeout = 1000;
Mike Fiore 1:e52ae6584f1c 277 Timer tmr;
Mike Fiore 1:e52ae6584f1c 278 Timer escape_tmr;
Mike Fiore 1:e52ae6584f1c 279 int cnt = 0;
Mike Fiore 1:e52ae6584f1c 280
Mike Fiore 1:e52ae6584f1c 281 while (!_dot->getNetworkJoinStatus()) {
Mike Fiore 1:e52ae6584f1c 282 wakeup(_sleep_standby);
Mike Fiore 1:e52ae6584f1c 283 write("\r\nJoining network... ");
Mike Fiore 1:e52ae6584f1c 284
Mike Fiore 1:e52ae6584f1c 285 // wait one second for possible escape
Mike Fiore 1:e52ae6584f1c 286 tmr.reset();
Mike Fiore 1:e52ae6584f1c 287 tmr.start();
Mike Fiore 1:e52ae6584f1c 288 escape_tmr.reset();
Mike Fiore 1:e52ae6584f1c 289 escape_tmr.start();
Mike Fiore 1:e52ae6584f1c 290 while (tmr.read_ms() < 1000) {
Mike Fiore 1:e52ae6584f1c 291 if (_serial.readable()) {
Mike Fiore 1:e52ae6584f1c 292 _serial.read(&ch, 1);
Mike Fiore 1:e52ae6584f1c 293 escape_buffer += ch;
Mike Fiore 1:e52ae6584f1c 294 }
Mike Fiore 1:e52ae6584f1c 295
Mike Fiore 1:e52ae6584f1c 296 if (escape_buffer.find(escape_sequence) != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 297 _mode = mDot::COMMAND_MODE;
Mike Fiore 1:e52ae6584f1c 298 write("Join Canceled\r\n");
Mike Fiore 1:e52ae6584f1c 299 write(done);
Mike Fiore 1:e52ae6584f1c 300 return true;
Mike Fiore 1:e52ae6584f1c 301 }
Mike Fiore 1:e52ae6584f1c 302
Mike Fiore 1:e52ae6584f1c 303 if (escape_tmr.read_ms() > escape_timeout)
Mike Fiore 1:e52ae6584f1c 304 escape_buffer.clear();
Mike Fiore 1:e52ae6584f1c 305 }
Mike Fiore 1:e52ae6584f1c 306
Mike Fiore 1:e52ae6584f1c 307 if (_dot->joinNetworkOnce() == mDot::MDOT_OK) {
Mike Fiore 1:e52ae6584f1c 308 write("Network Joined\r\n");
Mike Fiore 1:e52ae6584f1c 309 write(done);
Mike Fiore 1:e52ae6584f1c 310 return false;
Mike Fiore 1:e52ae6584f1c 311 }
Mike Fiore 1:e52ae6584f1c 312
Mike Fiore 1:e52ae6584f1c 313 write("Network Join failed\r\n");
Mike Fiore 1:e52ae6584f1c 314 write(error);
Mike Fiore 1:e52ae6584f1c 315
Mike Fiore 1:e52ae6584f1c 316 if (cnt++ > _dot->getJoinRetries()) {
Mike Fiore 1:e52ae6584f1c 317 cnt = 0;
Mike Fiore 1:e52ae6584f1c 318
Mike Fiore 1:e52ae6584f1c 319 if (_dot->getFrequencyBand() == mDot::FB_915) {
Mike Fiore 1:e52ae6584f1c 320 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
Mike Fiore 1:e52ae6584f1c 321 DEBUG_PRINTF("Join retries exhausted, switching to sub band %u\r\n", band);
Mike Fiore 1:e52ae6584f1c 322 _dot->setFrequencySubBand(band);
Mike Fiore 1:e52ae6584f1c 323 }
Mike Fiore 1:e52ae6584f1c 324
Mike Fiore 1:e52ae6584f1c 325 if (sleep < 60 * 60 * 1000)
Mike Fiore 1:e52ae6584f1c 326 sleep *= 2;
Mike Fiore 1:e52ae6584f1c 327 }
Mike Fiore 1:e52ae6584f1c 328
Mike Fiore 1:e52ae6584f1c 329 tmr.reset();
Mike Fiore 1:e52ae6584f1c 330 tmr.start();
Mike Fiore 1:e52ae6584f1c 331 escape_tmr.reset();
Mike Fiore 1:e52ae6584f1c 332 escape_tmr.start();
Mike Fiore 1:e52ae6584f1c 333 while (tmr.read_ms() < sleep) {
Mike Fiore 1:e52ae6584f1c 334 if (_serial.readable()) {
Mike Fiore 1:e52ae6584f1c 335 _serial.read(&ch, 1);
Mike Fiore 1:e52ae6584f1c 336 escape_buffer += ch;
Mike Fiore 1:e52ae6584f1c 337 }
Mike Fiore 1:e52ae6584f1c 338
Mike Fiore 1:e52ae6584f1c 339 if (escape_buffer.find(escape_sequence) != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 340 _mode = mDot::COMMAND_MODE;
Mike Fiore 1:e52ae6584f1c 341 return true;
Mike Fiore 1:e52ae6584f1c 342 }
Mike Fiore 1:e52ae6584f1c 343
Mike Fiore 1:e52ae6584f1c 344 if (escape_tmr.read_ms() > escape_timeout)
Mike Fiore 1:e52ae6584f1c 345 escape_buffer.clear();
Mike Fiore 1:e52ae6584f1c 346 }
Mike Fiore 1:e52ae6584f1c 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 _dot->resetNetworkSession();
Mike Fiore 1:e52ae6584f1c 356
Mike Fiore 1:e52ae6584f1c 357 char ch;
Mike Fiore 1:e52ae6584f1c 358 bool running = true;
Mike Fiore 1:e52ae6584f1c 359 bool echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 360 std::string command;
Mike Fiore 1:e52ae6584f1c 361 std::vector<std::string> args;
Mike Fiore 1:e52ae6584f1c 362
Mike Fiore 1:e52ae6584f1c 363 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Mike Fiore 1:e52ae6584f1c 364 command = "AT+SD\n";
Mike Fiore 1:e52ae6584f1c 365
Mike Fiore 1:e52ae6584f1c 366 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 367 char ch;
Mike Fiore 1:e52ae6584f1c 368
Mike Fiore 1:e52ae6584f1c 369 int escape_timeout = 1000;
Mike Fiore 1:e52ae6584f1c 370 Timer tmr;
Mike Fiore 1:e52ae6584f1c 371 Timer escape_tmr;
Mike Fiore 1:e52ae6584f1c 372
Mike Fiore 1:e52ae6584f1c 373 // wait one second for possible escape
Mike Fiore 1:e52ae6584f1c 374 tmr.reset();
Mike Fiore 1:e52ae6584f1c 375 tmr.start();
Mike Fiore 1:e52ae6584f1c 376 escape_tmr.reset();
Mike Fiore 1:e52ae6584f1c 377 escape_tmr.start();
Mike Fiore 1:e52ae6584f1c 378 while (tmr.read_ms() < escape_timeout) {
Mike Fiore 1:e52ae6584f1c 379 if (_serial.readable()) {
Mike Fiore 1:e52ae6584f1c 380 _serial.read(&ch, 1);
Mike Fiore 1:e52ae6584f1c 381 escape_buffer += ch;
Mike Fiore 1:e52ae6584f1c 382 }
Mike Fiore 1:e52ae6584f1c 383
Mike Fiore 1:e52ae6584f1c 384 if (escape_buffer.find(escape_sequence) != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 385 _mode = mDot::COMMAND_MODE;
Mike Fiore 1:e52ae6584f1c 386 command.clear();
Mike Fiore 1:e52ae6584f1c 387 break;
Mike Fiore 1:e52ae6584f1c 388 }
Mike Fiore 1:e52ae6584f1c 389
Mike Fiore 1:e52ae6584f1c 390 if (escape_tmr.read_ms() > escape_timeout)
Mike Fiore 1:e52ae6584f1c 391 escape_buffer.clear();
Mike Fiore 1:e52ae6584f1c 392
Mike Fiore 1:e52ae6584f1c 393 osDelay(1);
Mike Fiore 1:e52ae6584f1c 394 }
Mike Fiore 1:e52ae6584f1c 395
Mike Fiore 1:e52ae6584f1c 396 }
Mike Fiore 1:e52ae6584f1c 397
Mike Fiore 1:e52ae6584f1c 398 bool join_canceled = false;
Mike Fiore 1:e52ae6584f1c 399
Mike Fiore 1:e52ae6584f1c 400 //Run terminal session
Mike Fiore 1:e52ae6584f1c 401 while (running) {
Mike Fiore 1:e52ae6584f1c 402 if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) {
Mike Fiore 1:e52ae6584f1c 403 join_canceled = autoJoinCheck();
Mike Fiore 1:e52ae6584f1c 404 if (join_canceled)
Mike Fiore 1:e52ae6584f1c 405 command.clear();
Mike Fiore 1:e52ae6584f1c 406 }
Mike Fiore 1:e52ae6584f1c 407
Mike Fiore 1:e52ae6584f1c 408 if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) {
Mike Fiore 1:e52ae6584f1c 409 switch (_mode) {
Mike Fiore 1:e52ae6584f1c 410 case mDot::SERIAL_MODE:
Mike Fiore 1:e52ae6584f1c 411 // signal wakeup, read serial and output to radio
Mike Fiore 1:e52ae6584f1c 412 serial_loop();
Mike Fiore 1:e52ae6584f1c 413 continue;
Mike Fiore 1:e52ae6584f1c 414 break;
Mike Fiore 1:e52ae6584f1c 415 default:
Mike Fiore 1:e52ae6584f1c 416 break;
Mike Fiore 1:e52ae6584f1c 417 }
Mike Fiore 1:e52ae6584f1c 418 }
Mike Fiore 1:e52ae6584f1c 419
Mike Fiore 1:e52ae6584f1c 420 ch = '\0';
Mike Fiore 1:e52ae6584f1c 421
Mike Fiore 1:e52ae6584f1c 422 // read characters
Mike Fiore 1:e52ae6584f1c 423 if (readable()) {
Mike Fiore 1:e52ae6584f1c 424 ch = read();
Mike Fiore 1:e52ae6584f1c 425
Mike Fiore 1:e52ae6584f1c 426 if (ch == '\b') {
Mike Fiore 1:e52ae6584f1c 427 if (!command.empty()) {
Mike Fiore 1:e52ae6584f1c 428 writef("\b \b");
Mike Fiore 1:e52ae6584f1c 429 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 430 }
Mike Fiore 1:e52ae6584f1c 431 continue;
Mike Fiore 1:e52ae6584f1c 432 } else {
Mike Fiore 1:e52ae6584f1c 433 command += ch;
Mike Fiore 1:e52ae6584f1c 434 }
Mike Fiore 1:e52ae6584f1c 435
Mike Fiore 1:e52ae6584f1c 436 // echo chars if enabled
Mike Fiore 1:e52ae6584f1c 437 if (echo && !(ch == '\r' || ch == '\n'))
Mike Fiore 1:e52ae6584f1c 438 writef("%c", ch);
Mike Fiore 1:e52ae6584f1c 439 }
Mike Fiore 1:e52ae6584f1c 440
Mike Fiore 1:e52ae6584f1c 441 // look for end of command line
Mike Fiore 1:e52ae6584f1c 442 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 443 // remove new line or cr character
Mike Fiore 1:e52ae6584f1c 444 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 445 write("\r"); // match standard modem output
Mike Fiore 1:e52ae6584f1c 446 write(newline);
Mike Fiore 1:e52ae6584f1c 447 } else {
Mike Fiore 1:e52ae6584f1c 448 continue;
Mike Fiore 1:e52ae6584f1c 449 }
Mike Fiore 1:e52ae6584f1c 450
Mike Fiore 1:e52ae6584f1c 451 // trim whitespace from command
Mike Fiore 1:e52ae6584f1c 452 mts::Text::trim(command, "\r\n\t ");
Mike Fiore 1:e52ae6584f1c 453
Mike Fiore 1:e52ae6584f1c 454 if (command.size() < 1) {
Mike Fiore 1:e52ae6584f1c 455 command.clear();
Mike Fiore 1:e52ae6584f1c 456 continue;
Mike Fiore 1:e52ae6584f1c 457 }
Mike Fiore 1:e52ae6584f1c 458
Mike Fiore 1:e52ae6584f1c 459 // parse command and args
Mike Fiore 1:e52ae6584f1c 460 args.clear();
Mike Fiore 1:e52ae6584f1c 461
Mike Fiore 1:e52ae6584f1c 462 // find first '=' character
Mike Fiore 1:e52ae6584f1c 463 size_t delim_index = command.find("=");
Mike Fiore 1:e52ae6584f1c 464 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 465 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 466 } else {
Mike Fiore 1:e52ae6584f1c 467 // find first ' ' character
Mike Fiore 1:e52ae6584f1c 468 delim_index = command.find(" ");
Mike Fiore 1:e52ae6584f1c 469 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 470 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 471 } else {
Mike Fiore 1:e52ae6584f1c 472 args.push_back(command);
Mike Fiore 1:e52ae6584f1c 473 }
Mike Fiore 1:e52ae6584f1c 474 }
Mike Fiore 1:e52ae6584f1c 475
Mike Fiore 1:e52ae6584f1c 476 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 477 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
Mike Fiore 1:e52ae6584f1c 478 args.insert(args.end(), params.begin(), params.end());
Mike Fiore 1:e52ae6584f1c 479 }
Mike Fiore 1:e52ae6584f1c 480
Mike Fiore 1:e52ae6584f1c 481 args[0] = mts::Text::toUpper(args[0]);
Mike Fiore 1:e52ae6584f1c 482
Mike Fiore 1:e52ae6584f1c 483 // print help
Mike Fiore 1:e52ae6584f1c 484 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
Mike Fiore 1:e52ae6584f1c 485 printHelp();
Mike Fiore 1:e52ae6584f1c 486 command.clear();
Mike Fiore 1:e52ae6584f1c 487 } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 488 _dot->setEcho(false);
Mike Fiore 1:e52ae6584f1c 489 write(done);
Mike Fiore 1:e52ae6584f1c 490 echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 491 } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 492 _dot->setEcho(true);
Mike Fiore 1:e52ae6584f1c 493 write(done);
Mike Fiore 1:e52ae6584f1c 494 echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 495 } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 496 _dot->setVerbose(false);
Mike Fiore 1:e52ae6584f1c 497 write(done);
Mike Fiore 1:e52ae6584f1c 498 } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 499 _dot->setVerbose(true);
Mike Fiore 1:e52ae6584f1c 500 write(done);
Mike Fiore 1:e52ae6584f1c 501 } else if (args[0] == "AT+SD") {
Mike Fiore 1:e52ae6584f1c 502 DEBUG_PRINTF("Enter Serial Mode\r\n");
Mike Fiore 1:e52ae6584f1c 503 _mode = mDot::SERIAL_MODE;
Mike Fiore 1:e52ae6584f1c 504 } else {
Mike Fiore 1:e52ae6584f1c 505 bool found = false;
Mike Fiore 1:e52ae6584f1c 506 bool query = false;
Mike Fiore 1:e52ae6584f1c 507
Mike Fiore 1:e52ae6584f1c 508 std::string lookfor = args[0];
Mike Fiore 1:e52ae6584f1c 509
Mike Fiore 1:e52ae6584f1c 510 // per command help
Mike Fiore 1:e52ae6584f1c 511 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0))
Mike Fiore 1:e52ae6584f1c 512 lookfor = mts::Text::toUpper(args[1]);
Mike Fiore 1:e52ae6584f1c 513
Mike Fiore 1:e52ae6584f1c 514 // trim off any trailing '?' and mark as a query command
Mike Fiore 1:e52ae6584f1c 515 if (args[0].rfind("?") == args[0].length() - 1) {
Mike Fiore 1:e52ae6584f1c 516 query = true;
Mike Fiore 1:e52ae6584f1c 517 lookfor = args[0].substr(0, args[0].length() - 1);
Mike Fiore 1:e52ae6584f1c 518 }
Mike Fiore 1:e52ae6584f1c 519
Mike Fiore 1:e52ae6584f1c 520 // search for command
Mike Fiore 1:e52ae6584f1c 521 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) {
Mike Fiore 1:e52ae6584f1c 522 Command* cmd = *it;
Mike Fiore 1:e52ae6584f1c 523
Mike Fiore 1:e52ae6584f1c 524 // match CMD or CMD? syntax if command is queryable
Mike Fiore 1:e52ae6584f1c 525 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
Mike Fiore 1:e52ae6584f1c 526 found = true;
Mike Fiore 1:e52ae6584f1c 527 if (args[0] == "HELP") {
Mike Fiore 1:e52ae6584f1c 528 writef("%s%s", cmd->help(), newline);
Mike Fiore 1:e52ae6584f1c 529 write(done);
Mike Fiore 1:e52ae6584f1c 530 }
Mike Fiore 1:e52ae6584f1c 531
Mike Fiore 1:e52ae6584f1c 532 else if (args.size() > 1 && args[1] == "?") {
Mike Fiore 1:e52ae6584f1c 533 writef("%s%s", cmd->usage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 534 write(done);
Mike Fiore 1:e52ae6584f1c 535 } else if (!cmd->verify(args)) {
Mike Fiore 1:e52ae6584f1c 536 writef("%s%s", cmd->errorMessage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 537 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 538 } else {
Mike Fiore 1:e52ae6584f1c 539 if (cmd->action(args) == 0) {
Mike Fiore 1:e52ae6584f1c 540 writef("%s", done);
Mike Fiore 1:e52ae6584f1c 541 } else {
Mike Fiore 1:e52ae6584f1c 542 writef("%s%s", cmd->errorMessage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 543 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 544 }
Mike Fiore 1:e52ae6584f1c 545 }
Mike Fiore 1:e52ae6584f1c 546 }
Mike Fiore 1:e52ae6584f1c 547 }
Mike Fiore 1:e52ae6584f1c 548
Mike Fiore 1:e52ae6584f1c 549 if (!found) {
Mike Fiore 1:e52ae6584f1c 550 writef("%s", command_error);
Mike Fiore 1:e52ae6584f1c 551 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 552 }
Mike Fiore 1:e52ae6584f1c 553 }
Mike Fiore 1:e52ae6584f1c 554
Mike Fiore 1:e52ae6584f1c 555 command.clear();
Mike Fiore 1:e52ae6584f1c 556
Mike Fiore 1:e52ae6584f1c 557 }
Mike Fiore 1:e52ae6584f1c 558 }
Mike Fiore 1:e52ae6584f1c 559
Mike Fiore 1:e52ae6584f1c 560 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
Mike Fiore 2:e5eebd74d36d 561 if (format == mDot::HEXADECIMAL)
Mike Fiore 1:e52ae6584f1c 562 return mts::Text::bin2hexString(data);
Mike Fiore 2:e5eebd74d36d 563 else
Mike Fiore 2:e5eebd74d36d 564 return std::string(data.begin(), data.end());
Mike Fiore 1:e52ae6584f1c 565 }
Mike Fiore 1:e52ae6584f1c 566
Mike Fiore 1:e52ae6584f1c 567 void CommandTerminal::sleep(bool standby) {
Mike Fiore 1:e52ae6584f1c 568 _serial_up = false;
Mike Fiore 1:e52ae6584f1c 569 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 1:e52ae6584f1c 570
Mike Fiore 1:e52ae6584f1c 571 HAL_PWREx_EnableMainRegulatorLowVoltage();
Mike Fiore 1:e52ae6584f1c 572 HAL_PWREx_EnableFlashPowerDown();
Mike Fiore 1:e52ae6584f1c 573 HAL_PWREx_EnableLowRegulatorLowVoltage();
Mike Fiore 1:e52ae6584f1c 574
Mike Fiore 1:e52ae6584f1c 575 DEBUG_PRINTF("Sleep\r\n");
Mike Fiore 1:e52ae6584f1c 576 _dot->sleep();
Mike Fiore 1:e52ae6584f1c 577
Mike Fiore 1:e52ae6584f1c 578 if (standby) {
Mike Fiore 1:e52ae6584f1c 579
Mike Fiore 1:e52ae6584f1c 580 DEBUG_PRINTF("RECORD UPLINK: %lu\r\n", _dot->getUpLinkCounter());
Mike Fiore 1:e52ae6584f1c 581
Mike Fiore 1:e52ae6584f1c 582 RTC_WriteBackupRegister(RTC_BKP_DR0, _dot->getUpLinkCounter());
Mike Fiore 1:e52ae6584f1c 583
Mike Fiore 1:e52ae6584f1c 584 HAL_PWR_EnableBkUpAccess();
Mike Fiore 1:e52ae6584f1c 585
Mike Fiore 1:e52ae6584f1c 586 HAL_EnableDBGStandbyMode();
Mike Fiore 1:e52ae6584f1c 587
Mike Fiore 1:e52ae6584f1c 588 HAL_PWR_DisableWakeUpPin (PWR_WAKEUP_PIN1);
Mike Fiore 1:e52ae6584f1c 589
Mike Fiore 1:e52ae6584f1c 590 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // InterruptIn wakeon_serial(XBEE_DIN);
Mike Fiore 1:e52ae6584f1c 591 // Application is reloaded after wake-up from standby
Mike Fiore 1:e52ae6584f1c 592 HAL_PWR_EnterSTANDBYMode ();
Mike Fiore 1:e52ae6584f1c 593
Mike Fiore 1:e52ae6584f1c 594 } else {
Mike Fiore 1:e52ae6584f1c 595 pin_function(PA_0, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 596 pin_function(PA_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 597 // pin_function(PA_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 598 // pin_function(PA_3, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 599 pin_function(PA_4, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 600 pin_function(PA_5, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 601 pin_function(PA_6, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 602 pin_function(PA_7, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 603 // pin_function(PA_8, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 604 // pin_function(PA_9, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 605 // pin_function(PA_10, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 606 pin_function(PA_11, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 607 pin_function(PA_12, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 608 pin_function(PA_15, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 609
Mike Fiore 1:e52ae6584f1c 610 pin_function(PB_0, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 611 pin_function(PB_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 612 pin_function(PB_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 613
Mike Fiore 1:e52ae6584f1c 614 pin_function(PC_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 615 pin_function(PC_4, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 616 pin_function(PC_5, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 617 pin_function(PC_9, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 618 // pin_function(PC_13, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 619
Mike Fiore 1:e52ae6584f1c 620 pin_function(PD_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
Mike Fiore 1:e52ae6584f1c 621
Mike Fiore 1:e52ae6584f1c 622 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
Mike Fiore 1:e52ae6584f1c 623 }
Mike Fiore 1:e52ae6584f1c 624
Mike Fiore 1:e52ae6584f1c 625 wakeup_clear();
Mike Fiore 1:e52ae6584f1c 626 EXTI->PR = (1 << 22);
Mike Fiore 1:e52ae6584f1c 627
Mike Fiore 1:e52ae6584f1c 628 // After wake-up from STOP reconfigure the PLL
Mike Fiore 1:e52ae6584f1c 629 SetSysClock();
Mike Fiore 1:e52ae6584f1c 630 }
Mike Fiore 1:e52ae6584f1c 631
Mike Fiore 1:e52ae6584f1c 632 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
Mike Fiore 1:e52ae6584f1c 633 Timer timer;
Mike Fiore 1:e52ae6584f1c 634 Timer escape_timer;
Mike Fiore 1:e52ae6584f1c 635 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 636 int escape_timeout = 1000;
Mike Fiore 1:e52ae6584f1c 637
Mike Fiore 1:e52ae6584f1c 638 timer.start();
Mike Fiore 1:e52ae6584f1c 639 while (timer.read_ms() < timeout) {
Mike Fiore 1:e52ae6584f1c 640
Mike Fiore 1:e52ae6584f1c 641 if (dot != NULL) {
Mike Fiore 1:e52ae6584f1c 642 if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
Mike Fiore 1:e52ae6584f1c 643 return false;
Mike Fiore 1:e52ae6584f1c 644 }
Mike Fiore 1:e52ae6584f1c 645 }
Mike Fiore 1:e52ae6584f1c 646
Mike Fiore 1:e52ae6584f1c 647 if (_serialp != NULL && _serialp->readable()) {
Mike Fiore 1:e52ae6584f1c 648 if (escape_buffer == "")
Mike Fiore 1:e52ae6584f1c 649 escape_timer.start();
Mike Fiore 1:e52ae6584f1c 650 char ch;
Mike Fiore 1:e52ae6584f1c 651 _serialp->read(&ch, 1);
Mike Fiore 1:e52ae6584f1c 652 escape_buffer += ch;
Mike Fiore 1:e52ae6584f1c 653 if (escape_buffer == CommandTerminal::escape_sequence)
Mike Fiore 1:e52ae6584f1c 654 return true;
Mike Fiore 1:e52ae6584f1c 655 }
Mike Fiore 1:e52ae6584f1c 656 if (escape_timer.read_ms() > escape_timeout) {
Mike Fiore 1:e52ae6584f1c 657 escape_buffer = "";
Mike Fiore 1:e52ae6584f1c 658 escape_timer.stop(), escape_timer.reset();
Mike Fiore 1:e52ae6584f1c 659 }
Mike Fiore 1:e52ae6584f1c 660
Mike Fiore 1:e52ae6584f1c 661 osDelay(10);
Mike Fiore 1:e52ae6584f1c 662 }
Mike Fiore 1:e52ae6584f1c 663
Mike Fiore 1:e52ae6584f1c 664 return false;
Mike Fiore 1:e52ae6584f1c 665 }
Mike Fiore 1:e52ae6584f1c 666
Mike Fiore 1:e52ae6584f1c 667 void CommandTerminal::wakeup(bool standby) {
Mike Fiore 1:e52ae6584f1c 668 HAL_PWREx_DisableMainRegulatorLowVoltage();
Mike Fiore 1:e52ae6584f1c 669 HAL_PWREx_DisableFlashPowerDown();
Mike Fiore 1:e52ae6584f1c 670 HAL_PWREx_DisableLowRegulatorLowVoltage();
Mike Fiore 1:e52ae6584f1c 671
Mike Fiore 1:e52ae6584f1c 672 if (standby) {
Mike Fiore 1:e52ae6584f1c 673 HAL_DisableDBGStandbyMode();
Mike Fiore 1:e52ae6584f1c 674
Mike Fiore 1:e52ae6584f1c 675 HAL_PWR_EnableWakeUpPin (PWR_WAKEUP_PIN1);
Mike Fiore 1:e52ae6584f1c 676 }
Mike Fiore 1:e52ae6584f1c 677
Mike Fiore 1:e52ae6584f1c 678 _dot->wakeup();
Mike Fiore 1:e52ae6584f1c 679
Mike Fiore 1:e52ae6584f1c 680 }