DeepPass / mDot_AT_firmware

Dependencies:   MTS-Serial libmDot mbed-rtos mbed-src

Fork of mDot_AT_firmware by MultiTech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CommandTerminal.cpp Source File

CommandTerminal.cpp

00001 #include "ctype.h"
00002 #include "CommandTerminal.h"
00003 #include "Command.h"
00004 #include <cstdarg>
00005 
00006 extern "C" {
00007 #include "wakeup.h"
00008     extern void pin_function(PinName pin, int data);
00009 }
00010 
00011 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
00012 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
00013 
00014 const char CommandTerminal::newline[] = "\r\n";
00015 
00016 // Command error text...
00017 const char CommandTerminal::command_error[] = "Command not found!\r\n";
00018 
00019 // Response texts...
00020 const char CommandTerminal::help[] = "\r\nHelp\r\n";
00021 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
00022 const char CommandTerminal::done[] = "\r\nOK\r\n";
00023 const char CommandTerminal::error[] = "\r\nERROR\r\n";
00024 
00025 // Escape sequence...
00026 const char CommandTerminal::escape_sequence[] = "+++";
00027 
00028 mts::MTSSerial* CommandTerminal::_serialp = NULL;
00029 
00030 void CommandTerminal::addCommand(Command* cmd) {
00031     _commands.push_back(cmd);
00032 }
00033 
00034 CommandTerminal::CommandTerminal(mts::MTSSerial& serial, mDot* dot)
00035 :
00036   _serial(serial),
00037   _dot(dot),
00038   _mode(mDot::COMMAND_MODE),
00039   _sleep_standby(false),
00040   _xbee_on_sleep(XBEE_ON_SLEEP),
00041   _serial_up(false) {
00042 
00043     _serialp = &serial;
00044 
00045     wakeup_init(_dot->getSerialWakeInterval());
00046 
00047     addCommand(new CmdAttention(_dot));
00048     addCommand(new CmdIdentification(_dot, serial));
00049     addCommand(new CmdResetCpu(_dot, serial));
00050     addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE0/1", "ATE0: disable, ATE1: enable"));
00051     addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV0/1", "ATV0: disable, ATV1: enable"));
00052 
00053     addCommand(new CmdFactoryDefault(_dot));
00054     addCommand(new CmdSaveConfig(_dot));
00055     addCommand(new CmdDisplayConfig(_dot, serial));
00056     addCommand(new CmdDisplayStats(_dot, serial));
00057     addCommand(new CmdSerialBaudRate(_dot, serial));
00058     addCommand(new CmdDebugBaudRate(_dot, serial));
00059     addCommand(new CmdStartUpMode(_dot, serial));
00060 
00061     addCommand(new CmdFrequencyBand(_dot, serial));
00062     addCommand(new CmdFrequencySubBand(_dot, serial));
00063     addCommand(new CmdPublicNetwork(_dot, serial));
00064     addCommand(new CmdDeviceId(_dot, serial));
00065 
00066     addCommand(new CmdNetworkAddress(_dot, serial));
00067     addCommand(new CmdNetworkSessionKey(_dot, serial));
00068     addCommand(new CmdDataSessionKey(_dot, serial));
00069     addCommand(new CmdNetworkKey(_dot, serial));
00070     addCommand(new CmdNetworkId(_dot, serial));
00071 
00072     addCommand(new CmdJoinRequest(_dot, serial));
00073     addCommand(new CmdJoinRetries(_dot, serial));
00074     addCommand(new CmdNetworkJoinMode(_dot, serial));
00075     addCommand(new CmdNetworkJoinStatus(_dot, serial));
00076     addCommand(new CmdNetworkLinkCheck(_dot, serial));
00077     addCommand(new CmdLinkCheckCount(_dot, serial));
00078     addCommand(new CmdLinkCheckThreshold(_dot, serial));
00079     addCommand(new CmdEncryption(_dot, serial));
00080 
00081     addCommand(new CmdRssi(_dot, serial));
00082     addCommand(new CmdSnr(_dot, serial));
00083     addCommand(new CmdDataPending(_dot, serial));
00084 
00085     addCommand(new CmdTxDataRate(_dot, serial));
00086     addCommand(new CmdTxPower(_dot, serial));
00087     addCommand(new CmdTxFrequency(_dot, serial));
00088     addCommand(new CmdTxInverted(_dot, serial));
00089     addCommand(new CmdTxWait(_dot, serial));
00090     addCommand(new CmdTxChannel(_dot, serial));
00091     addCommand(new CmdTxNextMs(_dot, serial));
00092     addCommand(new CmdTimeOnAir(_dot, serial));
00093 
00094     addCommand(new CmdRxDataRate(_dot, serial));
00095     addCommand(new CmdRxFrequency(_dot, serial));
00096     addCommand(new CmdRxOutput(_dot, serial));
00097     addCommand(new CmdRxInverted(_dot, serial));
00098 
00099     addCommand(new CmdErrorCorrection(_dot, serial));
00100     addCommand(new CmdCRC(_dot, serial));
00101     addCommand(new CmdAdaptiveDataRate(_dot, serial));
00102 
00103     addCommand(new CmdACKAttempts(_dot, serial));
00104 
00105     addCommand(new CmdSendString(_dot, serial));
00106     addCommand(new CmdSendStringHighBW(_dot, serial));
00107     addCommand(new CmdSendBinary(_dot, serial));
00108     addCommand(new CmdSendStringOnInterval(_dot, serial));
00109     addCommand(new CmdReceiveOnce(_dot, serial));
00110     addCommand(new CmdReceiveContinuous(_dot, serial));
00111 
00112     addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Reads serial data and sends Lora packets (escape sequence: +++)"));
00113     addCommand(new CmdSerialWakeInterval(_dot, serial));
00114     addCommand(new CmdSerialWakeDelay(_dot, serial));
00115     addCommand(new CmdSerialReceiveTimeout(_dot, serial));
00116     addCommand(new CmdPing(_dot, serial));
00117     addCommand(new CmdLogLevel(_dot, serial));
00118 }
00119 
00120 void CommandTerminal::printHelp() {
00121     const char* name = NULL;
00122     const char* text = NULL;
00123     const char* desc = NULL;
00124     const char* tab = "\t";
00125 
00126     std::string header("Command");
00127     header.append(tab);
00128     header.append(tab);
00129     header.append("Name");
00130     header.append(tab);
00131     header.append(tab);
00132     header.append(tab);
00133     header.append("Description");
00134 
00135     write(newline);
00136     write(header.c_str());
00137     write(newline);
00138     write(newline);
00139     for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) {
00140         name = (*it)->name();
00141         text = (*it)->text();
00142         desc = (*it)->desc();
00143         write(text);
00144         if (strlen(text) < 8)
00145             write(tab);
00146         write(tab);
00147         write(name);
00148         if (strlen(name) < 8)
00149             write(tab);
00150         if (strlen(name) < 16)
00151             write(tab);
00152         write(tab);
00153         write(desc);
00154         write(newline);
00155     }
00156 
00157     write(newline);
00158 }
00159 
00160 bool CommandTerminal::writeable() {
00161     return _serial.writeable();
00162 }
00163 
00164 bool CommandTerminal::readable() {
00165     return _serial.readable();
00166 }
00167 
00168 char CommandTerminal::read() {
00169     char ch;
00170     _serial.read(&ch, 1);
00171     return ch;
00172 }
00173 
00174 void CommandTerminal::write(const char* message) {
00175     while (!writeable())
00176         ;
00177     _serial.write(message, strlen(message));
00178 }
00179 
00180 void CommandTerminal::writef(const char* format, ...) {
00181     char buff[256];
00182 
00183     va_list ap;
00184     va_start(ap, format);
00185     int size = vsnprintf(buff, 256, format, ap);
00186     while (!writeable())
00187         ;
00188     _serial.write(buff, size);
00189     va_end(ap);
00190 }
00191 
00192 void CommandTerminal::serial_loop() {
00193     Timer serial_read_timer;
00194     std::vector<uint8_t> serial_buffer;
00195     std::string escape_buffer;
00196     Timer escape_timer;
00197     int escape_delay = 100;
00198     uint8_t max_send_size;
00199 
00200     _serial_up = true;
00201     _xbee_on_sleep = GPIO_PIN_SET;
00202 
00203     if (_dot->getFrequencyBand() == mDot::FB_915)
00204         max_send_size = mDot::MaxLengths_915[_dot->getTxDataRate()];
00205     else
00206         max_send_size = mDot::MaxLengths_868[_dot->getTxDataRate()];
00207 
00208     DEBUG_PRINTF("Awake\r\n");
00209     wakeup(_sleep_standby);
00210 
00211     char ch;
00212 
00213     if (readable()) {
00214         ch = read();
00215         serial_buffer.push_back(ch);
00216 
00217         if (escape_timer.read_ms() > escape_delay && ch == '+') {
00218             escape_buffer += ch;
00219             escape_timer.reset();
00220         } else {
00221             _serial_up = true;
00222             escape_buffer.clear();
00223         }
00224 
00225         if (escape_buffer.length() == 3 && escape_buffer.find(escape_sequence) == 0) {
00226             _mode = mDot::COMMAND_MODE;
00227             DEBUG_PRINTF("Exit serial mode\r\n");
00228             escape_timer.stop();
00229             escape_buffer.clear();
00230             write(done);
00231             return;
00232         }
00233     }
00234 
00235     if (_serial_up) {
00236         osDelay(_dot->getSerialWakeDelay());
00237 
00238         serial_read_timer.start();
00239         while (_serial_up && serial_read_timer.read_ms() < _dot->getSerialReceiveTimeout()) {
00240             while (readable() && serial_buffer.size() < max_send_size) {
00241                 serial_buffer.push_back(read());
00242                 serial_read_timer.reset();
00243             }
00244         }
00245         serial_read_timer.stop(), serial_read_timer.reset();
00246 
00247         if (!serial_buffer.empty()) {
00248             _serial_up = false;
00249             _xbee_on_sleep = GPIO_PIN_RESET;
00250             if (!_dot->getIsTransmitting()) {
00251                 std::vector<uint8_t> recv_buffer;
00252                 DEBUG_PRINTF("Received serial data, sending out radio.\r\n");
00253 
00254                 if (!_dot->send(serial_buffer))
00255                     DEBUG_PRINTF("Send failed.\r\n");
00256                 if (_dot->recv(recv_buffer))
00257                     _serial.writef("%s\r\n", formatPacketData(recv_buffer, _dot->getRxOutput()).c_str());
00258             } else {
00259                 DEBUG_PRINTF("Radio is busy, cannot send.\r\n");
00260             }
00261 
00262             serial_buffer.clear();
00263         } else {
00264             DEBUG_PRINTF("No data received from serial to send.\r\n");
00265         }
00266         _serial_up = false;
00267     }
00268     sleep(_sleep_standby);
00269 }
00270 
00271 bool CommandTerminal::autoJoinCheck() {
00272 
00273     std::string escape_buffer;
00274     char ch;
00275     int sleep = 1000;
00276     int escape_timeout = 1000;
00277     Timer tmr;
00278     Timer escape_tmr;
00279     int cnt = 0;
00280 
00281     while (!_dot->getNetworkJoinStatus()) {
00282         wakeup(_sleep_standby);
00283         write("\r\nJoining network... ");
00284 
00285         // wait one second for possible escape
00286         tmr.reset();
00287         tmr.start();
00288         escape_tmr.reset();
00289         escape_tmr.start();
00290         while (tmr.read_ms() < 1000) {
00291             if (_serial.readable()) {
00292                 _serial.read(&ch, 1);
00293                 escape_buffer += ch;
00294             }
00295 
00296             if (escape_buffer.find(escape_sequence) != std::string::npos) {
00297                 _mode = mDot::COMMAND_MODE;
00298                 write("Join Canceled\r\n");
00299                 write(done);
00300                 return true;
00301             }
00302 
00303             if (escape_tmr.read_ms() > escape_timeout)
00304                 escape_buffer.clear();
00305         }
00306 
00307         if (_dot->joinNetworkOnce() == mDot::MDOT_OK) {
00308             write("Network Joined\r\n");
00309             write(done);
00310             return false;
00311         }
00312 
00313         write("Network Join failed\r\n");
00314         write(error);
00315 
00316         if (cnt++ > _dot->getJoinRetries()) {
00317             cnt = 0;
00318 
00319             if (_dot->getFrequencyBand() == mDot::FB_915) {
00320                 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
00321                 DEBUG_PRINTF("Join retries exhausted, switching to sub band %u\r\n", band);
00322                 _dot->setFrequencySubBand(band);
00323             }
00324 
00325             if (sleep < 60 * 60 * 1000)
00326                 sleep *= 2;
00327         }
00328 
00329         tmr.reset();
00330         tmr.start();
00331         escape_tmr.reset();
00332         escape_tmr.start();
00333         while (tmr.read_ms() < sleep) {
00334             if (_serial.readable()) {
00335                 _serial.read(&ch, 1);
00336                 escape_buffer += ch;
00337             }
00338 
00339             if (escape_buffer.find(escape_sequence) != std::string::npos) {
00340                 _mode = mDot::COMMAND_MODE;
00341                 return true;
00342             }
00343 
00344             if (escape_tmr.read_ms() > escape_timeout)
00345                 escape_buffer.clear();
00346         }
00347 
00348     }
00349 
00350     return false;
00351 }
00352 
00353 void CommandTerminal::start() {
00354 
00355     _dot->resetNetworkSession();
00356 
00357     char ch;
00358     bool running = true;
00359     bool echo = _dot->getEcho();
00360     std::string command;
00361     std::vector<std::string> args;
00362 
00363     if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
00364         command = "AT+SD\n";
00365 
00366         std::string escape_buffer;
00367         char ch;
00368 
00369         int escape_timeout = 1000;
00370         Timer tmr;
00371         Timer escape_tmr;
00372 
00373         // wait one second for possible escape
00374         tmr.reset();
00375         tmr.start();
00376         escape_tmr.reset();
00377         escape_tmr.start();
00378         while (tmr.read_ms() < escape_timeout) {
00379             if (_serial.readable()) {
00380                 _serial.read(&ch, 1);
00381                 escape_buffer += ch;
00382             }
00383 
00384             if (escape_buffer.find(escape_sequence) != std::string::npos) {
00385                 _mode = mDot::COMMAND_MODE;
00386                 command.clear();
00387                 break;
00388             }
00389 
00390             if (escape_tmr.read_ms() > escape_timeout)
00391                 escape_buffer.clear();
00392 
00393             osDelay(1);
00394         }
00395 
00396     }
00397 
00398     bool join_canceled = false;
00399 
00400     //Run terminal session
00401     while (running) {
00402         if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) {
00403             join_canceled = autoJoinCheck();
00404             if (join_canceled)
00405                 command.clear();
00406         }
00407 
00408         if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) {
00409             switch (_mode) {
00410                 case mDot::SERIAL_MODE:
00411                     // signal wakeup, read serial and output to radio
00412                     serial_loop();
00413                     continue;
00414                     break;
00415                 default:
00416                     break;
00417             }
00418         }
00419 
00420         ch = '\0';
00421 
00422         // read characters
00423         if (readable()) {
00424             ch = read();
00425 
00426             if (ch == '\b') {
00427                 if (!command.empty()) {
00428                     writef("\b \b");
00429                     command.erase(command.size() - 1);
00430                 }
00431                 continue;
00432             } else {
00433                 command += ch;
00434             }
00435 
00436             // echo chars if enabled
00437             if (echo && !(ch == '\r' || ch == '\n'))
00438                 writef("%c", ch);
00439         }
00440 
00441         // look for end of command line
00442         if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
00443             // remove new line or cr character
00444             command.erase(command.size() - 1);
00445             write("\r"); // match standard modem output
00446             write(newline);
00447         } else {
00448             continue;
00449         }
00450 
00451         // trim whitespace from command
00452         mts::Text::trim(command, "\r\n\t ");
00453 
00454         if (command.size() < 1) {
00455             command.clear();
00456             continue;
00457         }
00458 
00459         // parse command and args
00460         args.clear();
00461 
00462         // find first '=' character
00463         size_t delim_index = command.find("=");
00464         if (delim_index != std::string::npos) {
00465             args.push_back(command.substr(0, delim_index));
00466         } else {
00467             // find first ' ' character
00468             delim_index = command.find(" ");
00469             if (delim_index != std::string::npos) {
00470                 args.push_back(command.substr(0, delim_index));
00471             } else {
00472                 args.push_back(command);
00473             }
00474         }
00475 
00476         if (delim_index != std::string::npos) {
00477             std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
00478             args.insert(args.end(), params.begin(), params.end());
00479         }
00480 
00481         args[0] = mts::Text::toUpper(args[0]);
00482 
00483         // print help
00484         if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
00485             printHelp();
00486             command.clear();
00487         } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) {
00488             _dot->setEcho(false);
00489             write(done);
00490             echo = _dot->getEcho();
00491         } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) {
00492             _dot->setEcho(true);
00493             write(done);
00494             echo = _dot->getEcho();
00495         } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) {
00496             _dot->setVerbose(false);
00497             write(done);
00498         } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) {
00499             _dot->setVerbose(true);
00500             write(done);
00501         } else if (args[0] == "AT+SD") {
00502             DEBUG_PRINTF("Enter Serial Mode\r\n");
00503             _mode = mDot::SERIAL_MODE;
00504         } else {
00505             bool found = false;
00506             bool query = false;
00507 
00508             std::string lookfor = args[0];
00509 
00510             // per command help
00511             if ((args[0].find("?") == 0 || args[0].find("HELP") == 0))
00512                 lookfor = mts::Text::toUpper(args[1]);
00513 
00514             // trim off any trailing '?' and mark as a query command
00515             if (args[0].rfind("?") == args[0].length() - 1) {
00516                 query = true;
00517                 lookfor = args[0].substr(0, args[0].length() - 1);
00518             }
00519 
00520             // search for command
00521             for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) {
00522                 Command* cmd = *it;
00523 
00524                 // match CMD or CMD? syntax if command is queryable
00525                 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
00526                     found = true;
00527                     if (args[0] == "HELP") {
00528                         writef("%s%s", cmd->help(), newline);
00529                         write(done);
00530                     }
00531 
00532                     else if (args.size() > 1 && args[1] == "?") {
00533                         writef("%s%s", cmd->usage().c_str(), newline);
00534                         write(done);
00535                     } else if (!cmd->verify(args)) {
00536                         writef("%s%s", cmd->errorMessage().c_str(), newline);
00537                         writef("%s", error);
00538                     } else {
00539                         if (cmd->action(args) == 0) {
00540                             writef("%s", done);
00541                         } else {
00542                             writef("%s%s", cmd->errorMessage().c_str(), newline);
00543                             writef("%s", error);
00544                         }
00545                     }
00546                 }
00547             }
00548 
00549             if (!found) {
00550                 writef("%s", command_error);
00551                 writef("%s", error);
00552             }
00553         }
00554 
00555         command.clear();
00556 
00557     }
00558 }
00559 
00560 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
00561     if (format == mDot::HEXADECIMAL)
00562         return mts::Text::bin2hexString(data);
00563     else
00564         return std::string(data.begin(), data.end());
00565 }
00566 
00567 void CommandTerminal::sleep(bool standby) {
00568     _serial_up = false;
00569     _xbee_on_sleep = GPIO_PIN_RESET;
00570 
00571     HAL_PWREx_EnableMainRegulatorLowVoltage();
00572     HAL_PWREx_EnableFlashPowerDown();
00573     HAL_PWREx_EnableLowRegulatorLowVoltage();
00574 
00575     DEBUG_PRINTF("Sleep\r\n");
00576     _dot->sleep();
00577 
00578     if (standby) {
00579 
00580         DEBUG_PRINTF("RECORD UPLINK: %lu\r\n", _dot->getUpLinkCounter());
00581 
00582         RTC_WriteBackupRegister(RTC_BKP_DR0, _dot->getUpLinkCounter());
00583 
00584         HAL_PWR_EnableBkUpAccess();
00585 
00586         HAL_EnableDBGStandbyMode();
00587 
00588         HAL_PWR_DisableWakeUpPin (PWR_WAKEUP_PIN1);
00589 
00590         __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // InterruptIn wakeon_serial(XBEE_DIN);
00591         // Application is reloaded after wake-up from standby
00592 HAL_PWR_EnterSTANDBYMode        ();
00593 
00594     } else {
00595         pin_function(PA_0, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00596         pin_function(PA_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00597         // pin_function(PA_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00598         // pin_function(PA_3, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00599         pin_function(PA_4, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00600         pin_function(PA_5, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00601         pin_function(PA_6, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00602         pin_function(PA_7, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00603         // pin_function(PA_8, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00604         // pin_function(PA_9, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00605         // pin_function(PA_10, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00606         pin_function(PA_11, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00607         pin_function(PA_12, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00608         pin_function(PA_15, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00609 
00610         pin_function(PB_0, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00611         pin_function(PB_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00612         pin_function(PB_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00613 
00614         pin_function(PC_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00615         pin_function(PC_4, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00616         pin_function(PC_5, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00617         pin_function(PC_9, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00618         // pin_function(PC_13, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00619 
00620         pin_function(PD_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0));
00621 
00622         HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
00623     }
00624 
00625     wakeup_clear();
00626     EXTI->PR = (1 << 22);
00627 
00628     // After wake-up from STOP reconfigure the PLL
00629     SetSysClock();
00630 }
00631 
00632 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
00633     Timer timer;
00634     Timer escape_timer;
00635     std::string escape_buffer;
00636     int escape_timeout = 1000;
00637 
00638     timer.start();
00639     while (timer.read_ms() < timeout) {
00640 
00641         if (dot != NULL) {
00642             if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
00643                 return false;
00644             }
00645         }
00646 
00647         if (_serialp != NULL && _serialp->readable()) {
00648             if (escape_buffer == "")
00649                 escape_timer.start();
00650             char ch;
00651             _serialp->read(&ch, 1);
00652             escape_buffer += ch;
00653             if (escape_buffer == CommandTerminal::escape_sequence)
00654                 return true;
00655         }
00656         if (escape_timer.read_ms() > escape_timeout) {
00657             escape_buffer = "";
00658             escape_timer.stop(), escape_timer.reset();
00659         }
00660 
00661         osDelay(10);
00662     }
00663 
00664     return false;
00665 }
00666 
00667 void CommandTerminal::wakeup(bool standby) {
00668     HAL_PWREx_DisableMainRegulatorLowVoltage();
00669     HAL_PWREx_DisableFlashPowerDown();
00670     HAL_PWREx_DisableLowRegulatorLowVoltage();
00671 
00672     if (standby) {
00673         HAL_DisableDBGStandbyMode();
00674 
00675         HAL_PWR_EnableWakeUpPin (PWR_WAKEUP_PIN1);
00676     }
00677 
00678     _dot->wakeup();
00679 
00680 }