Peter Ferland / Mbed OS Dot-AT-Firmware-USB

Dependencies:   MTS-Serial libmDot-mbed5

Fork of Dot-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 "MTSLog.h"
00005 #include "ChannelPlan.h"
00006 #include <cstdarg>
00007 #include <deque>
00008 #if defined(TARGET_XDOT_L151CC)
00009 #include "xdot_low_power.h"
00010 #endif
00011 
00012 #if defined(TARGET_MTS_MDOT_F411RE)
00013 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
00014 #else
00015 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa xDot Module\r\n\n";
00016 #endif
00017 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
00018 
00019 const char CommandTerminal::newline[] = "\r\n";
00020 
00021 // Command error text...
00022 const char CommandTerminal::command_error[] = "Command not found!\r\n";
00023 
00024 // Response texts...
00025 const char CommandTerminal::help[] = "\r\nHelp\r\n";
00026 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
00027 const char CommandTerminal::connect[] = "\r\nCONNECT\r\n";
00028 const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n";
00029 const char CommandTerminal::done[] = "\r\nOK\r\n";
00030 const char CommandTerminal::error[] = "\r\nERROR\r\n";
00031 
00032 // Escape sequence...
00033 const char CommandTerminal::escape_sequence[] = "+++";
00034 
00035 mts::ATSerial* CommandTerminal::_serialp = NULL;
00036 mDot* CommandTerminal::_dot = NULL;
00037 
00038 CommandTerminal::RadioEvent* CommandTerminal::_events = new RadioEvent();
00039 
00040 static bool serial_data_mode = false;
00041 static bool peer_to_peer = false;
00042 
00043 std::string CommandTerminal::_errorMessage = "";
00044 
00045 void CommandTerminal::setErrorMessage(const char* message) {
00046     _errorMessage.assign(message);
00047 }
00048 
00049 void CommandTerminal::setErrorMessage(const std::string& message) {
00050     _errorMessage.assign(message);
00051 }
00052 
00053 const Command CommandTerminal::_commands[NO_OF_COMMANDS] = {
00054     CmdAttention(),
00055     CmdIdentification(),
00056     CmdResetCpu(),
00057     CmdDummy("Enable/Disable Echo", "ATE", "ATE0: disable, ATE1: enable", "(0,1)"),
00058     CmdDummy("Enable/Disable Verbose", "ATV", "ATV0: disable, ATV1: enable", "(0,1)"),
00059     CmdDummy("Hardware Flow Control", "AT&K", "AT&K0: disable, AT&K3: enable", "(0,3)"),
00060 
00061     CmdFactoryDefault(),
00062     CmdSaveConfig(),
00063     CmdDisplayConfig(),
00064     CmdDisplayStats(),
00065     CmdResetStats(),
00066     CmdSerialBaudRate(),
00067     CmdDebugBaudRate(),
00068     CmdStartUpMode(),
00069 
00070     CmdDefaultFrequencyBand(),
00071     CmdFrequencyBand(),
00072     CmdFrequencySubBand(),
00073     CmdPublicNetwork(),
00074     CmdDeviceId(),
00075     CmdDeviceClass(),
00076     CmdLbt(),
00077 
00078     CmdAppPort(),
00079     CmdNetworkAddress(),
00080     CmdNetworkSessionKey(),
00081     CmdDataSessionKey(),
00082     CmdUplinkCounter(),
00083     CmdDownlinkCounter(),
00084     CmdSaveSession(),
00085     CmdRestoreSession(),
00086     CmdNetworkKey(),
00087     CmdNetworkId(),
00088 
00089     CmdJoinDelay(),
00090 // Remove join settings commands until valid case for changing default settings
00091 //    CmdJoinRx1Offset(),
00092 //    CmdJoinRx2Datarate(),
00093 //    CmdJoinRx2Frequency(),
00094     CmdJoinRequest(),
00095     CmdJoinRetries(),
00096     CmdJoinByteOrder(),
00097     CmdNetworkJoinMode(),
00098     CmdPreserveSession(),
00099     CmdNetworkJoinStatus(),
00100     CmdNetworkLinkCheck(),
00101     CmdLinkCheckCount(),
00102     CmdLinkCheckThreshold(),
00103     CmdEncryption(),
00104 
00105     CmdRssi(),
00106     CmdSnr(),
00107     CmdDataPending(),
00108 
00109     CmdSessionDataRate(),
00110     CmdChannelMask(),
00111 
00112     CmdTxDataRate(),
00113     CmdTxPower(),
00114     CmdAntennaGain(),
00115     CmdTxFrequency(),
00116     CmdTxInverted(),
00117     CmdTxWait(),
00118     CmdTxChannel(),
00119     CmdTxNextMs(),
00120     CmdTimeOnAir(),
00121 
00122     CmdRxDelay(),
00123     CmdRxOutput(),
00124     CmdRxInverted(),
00125 
00126     CmdErrorCorrection(),
00127     CmdCRC(),
00128     CmdAdaptiveDataRate(),
00129 
00130     CmdACKAttempts(),
00131     CmdRepeat(),
00132     CmdMacCmd(),
00133 
00134     CmdSendString(),
00135     CmdSendBinary(),
00136     CmdReceiveOnce(),
00137 
00138     CmdDummy("Serial Data Mode", "AT+SD", "Enter serial data mode, exit with '+++'", "NONE"),
00139     CmdDummy("Sleep Mode", "AT+SLEEP", "Enter sleep mode (0:deepsleep,1:sleep)", "(0,1)"),
00140     CmdSerialClearOnError(),
00141     CmdWakeMode(),
00142     CmdWakeInterval(),
00143     CmdWakePin(),
00144     CmdWakeDelay(),
00145     CmdWakeTimeout(),
00146     CmdPing(),
00147     CmdLogLevel(),
00148 
00149     CmdDummy("***** Test Commands *****", "", "", ""),
00150     CmdRxDataRate(),
00151     CmdRxFrequency(),
00152     CmdReceiveContinuous(),
00153     CmdSendStringOnInterval(),
00154 
00155 #ifdef MTS_RADIO_DEBUG_COMMANDS
00156     CmdDummy("***** Debug Commands *****", "", "", ""),
00157     CmdSendContinuous(),
00158     CmdWriteProtectedConfig(),
00159     CmdDumpRegisters(),
00160     CmdEraseFlash(),
00161     CmdDisableDutyCycle(),
00162     CmdLBTRSSI(),
00163 #endif
00164 
00165 };
00166 
00167 const verify_ptr_t CommandTerminal::_verify[NO_OF_COMMANDS] = {
00168     CmdDummy::verify,
00169     CmdDummy::verify,
00170     CmdDummy::verify,
00171     CmdDummy::verify,
00172     CmdDummy::verify,
00173     CmdDummy::verify,
00174 
00175     CmdDummy::verify,
00176     CmdDummy::verify,
00177     CmdDummy::verify,
00178     CmdDummy::verify,
00179     CmdDummy::verify,
00180     CmdSerialBaudRate::verify,
00181     CmdDebugBaudRate::verify,
00182     CmdStartUpMode::verify,
00183 
00184     CmdDefaultFrequencyBand::verify,
00185     CmdFrequencyBand::verify,
00186     CmdFrequencySubBand::verify,
00187     CmdPublicNetwork::verify,
00188     CmdDeviceId::verify,
00189     CmdDeviceClass::verify,
00190     CmdLbt::verify,
00191 
00192     CmdAppPort::verify,
00193     CmdNetworkAddress::verify,
00194     CmdNetworkSessionKey::verify,
00195     CmdDataSessionKey::verify,
00196     CmdUplinkCounter::verify,
00197     CmdDownlinkCounter::verify,
00198     CmdDummy::verify,
00199     CmdDummy::verify,
00200     CmdNetworkKey::verify,
00201     CmdNetworkId::verify,
00202 
00203     CmdJoinDelay::verify,
00204 // Remove join settings commands until valid case for changing default settings
00205 //    CmdJoinRx1Offset::verify,
00206 //    CmdJoinRx2Datarate::verify,
00207 //    CmdJoinRx2Frequency::verify,
00208     CmdJoinRequest::verify,
00209     CmdJoinRetries::verify,
00210     CmdJoinByteOrder::verify,
00211     CmdNetworkJoinMode::verify,
00212     CmdPreserveSession::verify,
00213     CmdDummy::verify,
00214     CmdDummy::verify,
00215     CmdLinkCheckCount::verify,
00216     CmdLinkCheckThreshold::verify,
00217     CmdEncryption::verify,
00218 
00219     CmdDummy::verify,
00220     CmdDummy::verify,
00221     CmdDummy::verify,
00222 
00223     CmdSessionDataRate::verify,
00224     CmdChannelMask::verify,
00225 
00226     CmdTxDataRate::verify,
00227     CmdTxPower::verify,
00228     CmdAntennaGain::verify,
00229     CmdTxFrequency::verify,
00230     CmdTxInverted::verify,
00231     CmdTxWait::verify,
00232     CmdTxChannel::verify,
00233     CmdTxNextMs::verify,
00234     CmdTimeOnAir::verify,
00235 
00236     CmdRxDelay::verify,
00237     CmdRxOutput::verify,
00238     CmdRxInverted::verify,
00239 
00240     CmdErrorCorrection::verify,
00241     CmdCRC::verify,
00242     CmdAdaptiveDataRate::verify,
00243 
00244     CmdACKAttempts::verify,
00245     CmdRepeat::verify,
00246     CmdMacCmd::verify,
00247 
00248     CmdSendString::verify,
00249     CmdSendBinary::verify,
00250     CmdReceiveOnce::verify,
00251 
00252     CmdDummy::verify,
00253     CmdDummy::verify,
00254     CmdSerialClearOnError::verify,
00255     CmdWakeMode::verify,
00256     CmdWakeInterval::verify,
00257     CmdWakePin::verify,
00258     CmdWakeDelay::verify,
00259     CmdWakeTimeout::verify,
00260     CmdDummy::verify,
00261     CmdLogLevel::verify,
00262 
00263     CmdDummy::verify,
00264     CmdRxDataRate::verify,
00265     CmdRxFrequency::verify,
00266     CmdReceiveContinuous::verify,
00267     CmdSendStringOnInterval::verify,
00268 
00269 #ifdef MTS_RADIO_DEBUG_COMMANDS
00270     CmdDummy::verify,
00271     CmdSendContinuous::verify,
00272     CmdDummy::verify,
00273     CmdDummy::verify,
00274     CmdEraseFlash::verify,
00275     CmdDisableDutyCycle::verify,
00276     CmdLBTRSSI::verify,
00277 #endif
00278 
00279 };
00280 
00281 const action_ptr_t CommandTerminal::_action[NO_OF_COMMANDS] = {
00282     CmdAttention::action,
00283     CmdIdentification::action,
00284     CmdResetCpu::action,
00285     CmdDummy::action,
00286     CmdDummy::action,
00287     CmdDummy::action,
00288 
00289     CmdFactoryDefault::action,
00290     CmdSaveConfig::action,
00291     CmdDisplayConfig::action,
00292     CmdDisplayStats::action,
00293     CmdResetStats::action,
00294     CmdSerialBaudRate::action,
00295     CmdDebugBaudRate::action,
00296     CmdStartUpMode::action,
00297 
00298     CmdDefaultFrequencyBand::action,
00299     CmdFrequencyBand::action,
00300     CmdFrequencySubBand::action,
00301     CmdPublicNetwork::action,
00302     CmdDeviceId::action,
00303     CmdDeviceClass::action,
00304     CmdLbt::action,
00305 
00306     CmdAppPort::action,
00307     CmdNetworkAddress::action,
00308     CmdNetworkSessionKey::action,
00309     CmdDataSessionKey::action,
00310     CmdUplinkCounter::action,
00311     CmdDownlinkCounter::action,
00312     CmdSaveSession::action,
00313     CmdRestoreSession::action,
00314     CmdNetworkKey::action,
00315     CmdNetworkId::action,
00316 
00317     CmdJoinDelay::action,
00318 // Remove join settings commands until valid case for changing default settings
00319 //    CmdJoinRx1Offset::action,
00320 //    CmdJoinRx2Datarate::action,
00321 //    CmdJoinRx2Frequency::action,
00322     CmdJoinRequest::action,
00323     CmdJoinRetries::action,
00324     CmdJoinByteOrder::action,
00325     CmdNetworkJoinMode::action,
00326     CmdPreserveSession::action,
00327     CmdNetworkJoinStatus::action,
00328     CmdNetworkLinkCheck::action,
00329     CmdLinkCheckCount::action,
00330     CmdLinkCheckThreshold::action,
00331     CmdEncryption::action,
00332 
00333     CmdRssi::action,
00334     CmdSnr::action,
00335     CmdDataPending::action,
00336 
00337     CmdSessionDataRate::action,
00338     CmdChannelMask::action,
00339 
00340     CmdTxDataRate::action,
00341     CmdTxPower::action,
00342     CmdAntennaGain::action,
00343     CmdTxFrequency::action,
00344     CmdTxInverted::action,
00345     CmdTxWait::action,
00346     CmdTxChannel::action,
00347     CmdTxNextMs::action,
00348     CmdTimeOnAir::action,
00349 
00350     CmdRxDelay::action,
00351     CmdRxOutput::action,
00352     CmdRxInverted::action,
00353 
00354     CmdErrorCorrection::action,
00355     CmdCRC::action,
00356     CmdAdaptiveDataRate::action,
00357 
00358     CmdACKAttempts::action,
00359     CmdRepeat::action,
00360     CmdMacCmd::action,
00361 
00362     CmdSendString::action,
00363     CmdSendBinary::action,
00364     CmdReceiveOnce::action,
00365 
00366     CmdDummy::action,
00367     CmdDummy::action,
00368     CmdSerialClearOnError::action,
00369     CmdWakeMode::action,
00370     CmdWakeInterval::action,
00371     CmdWakePin::action,
00372     CmdWakeDelay::action,
00373     CmdWakeTimeout::action,
00374     CmdPing::action,
00375     CmdLogLevel::action,
00376 
00377     CmdDummy::action,
00378     CmdRxDataRate::action,
00379     CmdRxFrequency::action,
00380     CmdReceiveContinuous::action,
00381     CmdSendStringOnInterval::action,
00382 
00383 #ifdef MTS_RADIO_DEBUG_COMMANDS
00384     CmdDummy::action,
00385     CmdSendContinuous::action,
00386     CmdWriteProtectedConfig::action,
00387     CmdDumpRegisters::action,
00388     CmdEraseFlash::action,
00389     CmdDisableDutyCycle::action,
00390     CmdLBTRSSI::action,
00391 #endif
00392 
00393 };
00394 
00395 CommandTerminal::CommandTerminal(mts::ATSerial& serial) :
00396   _serial(serial),
00397   _mode(mDot::COMMAND_MODE),
00398   _sleep_standby(true),
00399 #if defined(TARGET_MTS_MDOT_F411RE)
00400   _xbee_on_sleep(XBEE_ON_SLEEP),
00401 #else
00402   _xbee_on_sleep(GPIO2),
00403 #endif
00404   _autoOTAEnabled(false)
00405 {
00406     _serialp = &serial;
00407 }
00408 
00409 void CommandTerminal::init() {
00410     _dot->setEvents(_events);
00411 }
00412 
00413 void CommandTerminal::printHelp() {
00414     const char* name = NULL;
00415     const char* text = NULL;
00416     const char* desc = NULL;
00417     const char* tab = "\t";
00418 
00419     std::string header("Command");
00420     header.append(tab);
00421     header.append(tab);
00422     header.append("Name");
00423     header.append(tab);
00424     header.append(tab);
00425     header.append(tab);
00426     header.append("Description");
00427 
00428     write(newline);
00429     write(header.c_str());
00430     write(newline);
00431     write(newline);
00432 
00433     for (int i = 0; i < NO_OF_COMMANDS; i++) {
00434         name = _commands[i].name();
00435         text = _commands[i].text();
00436         desc = _commands[i].desc();
00437         write(text);
00438         if (strlen(text) < 8)
00439             write(tab);
00440         write(tab);
00441         write(name);
00442         if (strlen(name) < 8)
00443             write(tab);
00444         if (strlen(name) < 16)
00445             write(tab);
00446         write(tab);
00447         write(desc);
00448         write(newline);
00449     }
00450 
00451     write(newline);
00452 }
00453 
00454 bool CommandTerminal::writeable() {
00455     return _serialp->writeable();
00456 }
00457 
00458 bool CommandTerminal::readable() {
00459     return _serialp->readable();
00460 }
00461 
00462 char CommandTerminal::read() {
00463     char ch;
00464     _serialp->read(&ch, 1);
00465     return ch;
00466 }
00467 
00468 void CommandTerminal::write(const char* message) {
00469     while (!writeable())
00470         ;
00471     _serialp->write(message, strlen(message));
00472 }
00473 
00474 void CommandTerminal::writef(const char* format, ...) {
00475     char buff[256];
00476 
00477     va_list ap;
00478     va_start(ap, format);
00479     int size = vsnprintf(buff, 256, format, ap);
00480     while (!writeable())
00481         ;
00482     _serialp->write(buff, size);
00483     va_end(ap);
00484 }
00485 
00486 void CommandTerminal::serialLoop() {
00487     Timer serial_read_timer;
00488     std::vector<uint8_t> serial_buffer;
00489     std::vector<uint8_t> data;
00490     int timeout = 0;
00491 
00492     serial_read_timer.start();
00493 
00494     if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
00495         _xbee_on_sleep = GPIO_PIN_SET;
00496 
00497         timeout = _dot->getWakeDelay();
00498 
00499         // wait for timeout or start of serial data
00500         while (!readable() && serial_read_timer.read_ms() < timeout && !_serialp->escaped()) {
00501             osDelay(2);
00502         }
00503     }
00504 
00505     if (!readable() && _events->SendAck()) {
00506         logDebug("SERIAL NOT READABLE and ACK REQUESTED");
00507         goto L_SEND;
00508     }
00509 
00510     if (readable() && !_serialp->escaped()) {
00511 
00512         serial_read_timer.reset();
00513         timeout = _dot->getWakeTimeout();
00514 
00515         while (serial_read_timer.read_ms() < timeout && serial_buffer.size() <= _dot->getMaxPacketLength()) {
00516             while (readable() && serial_buffer.size() < _dot->getMaxPacketLength()) {
00517                 serial_buffer.push_back(read());
00518                 serial_read_timer.reset();
00519 
00520                 if (_serialp->escaped())
00521                     break;
00522             }
00523         }
00524 
00525         serial_read_timer.stop(), serial_read_timer.reset();
00526 
00527         if (!serial_buffer.empty()) {
00528             if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
00529                  _xbee_on_sleep = GPIO_PIN_RESET;
00530 
00531 L_SEND:
00532             // wait for any duty cycle limit to expire
00533             while (_dot->getNextTxMs() > 0 && !_serialp->escaped()) {
00534                 osDelay(10);
00535             }
00536 
00537             if (_dot->getIsIdle()) {
00538                 logDebug("Received serial data, sending out radio.");
00539 
00540                 if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
00541                     logDebug("Send failed.");
00542                     // If the data should be tossed after send failure, clear buffer
00543                     if (_dot->getSerialClearOnError()) {
00544                         serial_buffer.clear();
00545                     }
00546                 } else {
00547 
00548                     // wait for send to finish
00549                     while (!_dot->getIsIdle() && !_serialp->escaped()) {
00550                         osDelay(10);
00551                     }
00552 
00553                     // call recv to wait for any packet before sending again
00554                     if (!_serialp->escaped())
00555                         _dot->recv(data);
00556 
00557                     // Clear the serial buffer if send is success
00558                     serial_buffer.clear();
00559 
00560                     // In class C mode pending data will be sent automatically without uplink
00561                     if (_dot->getClass() != "C") {
00562                         if (_dot->getDataPending()) {
00563                             logDebug("Data is pending");
00564                             goto L_SEND;
00565                         }
00566                         if (_dot->getAckRequested()) {
00567                             logDebug("Ack requested");
00568                             goto L_SEND;
00569                         }
00570                     }
00571                 }
00572             } else {
00573                 logDebug("Radio is busy, cannot send.\r\n");
00574                 osDelay(10);
00575             }
00576 
00577         } else {
00578             logDebug("No data received from serial to send.\r\n");
00579         }
00580     }
00581 
00582     if (!_serialp->readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serialp->escaped()) {
00583         sleep(true);
00584     }
00585 
00586     if (_serialp->escaped()) {
00587         _serialp->clearEscaped();
00588         _serialp->rxClear();
00589         serial_data_mode = false;
00590         _mode = mDot::COMMAND_MODE;
00591         logDebug("Exit Serial Mode");
00592         write(done);
00593         return;
00594     }
00595 
00596     if (!_dot->getNetworkJoinStatus()) {
00597         serial_data_mode = false;
00598         _mode = mDot::COMMAND_MODE;
00599         logDebug("Exit Serial Mode");
00600         write(no_carrier);
00601         return;
00602     }
00603 }
00604 
00605 bool CommandTerminal::autoJoinCheck() {
00606 
00607     std::string escape_buffer;
00608     int sleep = 1000;
00609     Timer tmr;
00610     tmr.start();
00611     int cnt = 0;
00612 
00613     while (!_dot->getNetworkJoinStatus()) {
00614         if (!serial_data_mode) {
00615             write("\r\nJoining network... ");
00616         }
00617         logInfo("Joining network... ");
00618 
00619         if (_dot->getNextTxMs() > 0) {
00620             if (!serial_data_mode) {
00621                 writef("\r\nWaiting %lu s before next join attempt\r\n", _dot->getNextTxMs() / 1000);
00622             }
00623             logInfo("Waiting %lu s before next join attempt", _dot->getNextTxMs() / 1000);
00624 
00625             tmr.reset();
00626             while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
00627                 osDelay(20);
00628             }
00629         }
00630 
00631         if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
00632             if (!serial_data_mode) {
00633                 write("Network Joined\r\n");
00634                 write(done);
00635             }
00636             logInfo("Network Joined");
00637             return false;
00638         }
00639 
00640         if (!serial_data_mode) {
00641             write("Network Join failed\r\n");
00642             write(error);
00643         }
00644         logInfo("Network Join failed");
00645 
00646         if (!_serial.escaped() && _dot->getFrequencySubBand() != 0 && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
00647             cnt = 0;
00648 
00649             if (lora::ChannelPlan::IsPlanFixed(_dot->getFrequencyBand())) {
00650                 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
00651                 logWarning("Join retries exhausted, switching to sub band %u", band);
00652                 _dot->setFrequencySubBand(band);
00653             }
00654         }
00655 
00656         tmr.reset();
00657         while (tmr.read_ms() < sleep && !_serial.escaped()) {
00658             osDelay(10);
00659         }
00660 
00661         if (_serial.escaped()) {
00662             _serial.clearEscaped();
00663             serial_data_mode = false;
00664             _mode = mDot::COMMAND_MODE;
00665             if (!serial_data_mode) {
00666                 write("Join Canceled\r\n");
00667                 write(done);
00668             }
00669             logInfo("Join Canceled\r\n");
00670             return true;
00671         }
00672     }
00673 
00674     return false;
00675 }
00676 
00677 void CommandTerminal::start() {
00678 
00679     char ch;
00680     bool running = true;
00681     bool echo = _dot->getEcho();
00682     std::string command;
00683 #if defined(TARGET_MTS_MDOT_F411RE)
00684     std::deque<std::string> history;
00685     int history_index = -1;
00686 #endif
00687     std::vector<std::string> args;
00688     bool join_canceled = false;
00689 
00690     _autoOTAEnabled = _dot->getJoinMode() == mDot::AUTO_OTA;
00691 
00692     if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
00693 
00694         serial_data_mode = true;
00695         _mode = mDot::SERIAL_MODE;
00696 
00697         std::string escape_buffer;
00698         char ch;
00699 
00700         if (!_dot->getStandbyFlag()) {
00701             // wake up from power-on/reset
00702 
00703             int escape_timeout = 1000;
00704             Timer tmr;
00705             Timer escape_tmr;
00706 
00707             // wait one second for possible escape by user pressing '+' key
00708             tmr.reset();
00709             tmr.start();
00710             escape_tmr.reset();
00711             escape_tmr.start();
00712             while (tmr.read_ms() < escape_timeout) {
00713                 if (_serial.readable()) {
00714                     _serial.read(&ch, 1);
00715                     escape_buffer += ch;
00716                 }
00717 
00718                 if (escape_buffer.find("+") != std::string::npos) {
00719                     logInfo("Escape detected");
00720                     join_canceled = true;
00721                     serial_data_mode = false;
00722                     _mode = mDot::COMMAND_MODE;
00723                     command.clear();
00724                     break;
00725                 }
00726 
00727                 if (escape_tmr.read_ms() > escape_timeout)
00728                     escape_buffer.clear();
00729 
00730                 osDelay(1);
00731             }
00732         }
00733 
00734         if (_mode == mDot::SERIAL_MODE && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
00735             if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
00736                 serial_data_mode = false;
00737                 _mode = mDot::COMMAND_MODE;
00738 
00739                 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
00740                 _serial.writef("Network Not Joined\r\n");
00741                 _serial.writef(error);
00742             }
00743         }
00744     }
00745 
00746     if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
00747         peer_to_peer = true;
00748     } else {
00749         peer_to_peer = false;
00750     }
00751 
00752     //Run terminal session
00753     while (running) {
00754 
00755         // wait for input to reduce at command idle current
00756         while (!readable() || _mode == mDot::SERIAL_MODE) {
00757             if (!join_canceled && _autoOTAEnabled) {
00758                 join_canceled = autoJoinCheck();
00759                 if (join_canceled)
00760                     command.clear();
00761             }
00762 
00763             if (!_autoOTAEnabled || (!join_canceled && _autoOTAEnabled)) {
00764                 switch (_mode) {
00765                     case mDot::SERIAL_MODE:
00766                         // signal wakeup, read serial and output to radio
00767                         serialLoop();
00768                         continue;
00769                         break;
00770                     default:
00771                         break;
00772                 }
00773             }
00774 
00775             ch = '\0';
00776 
00777             wait(0.00001); // 10 us
00778             _serial.escaped();
00779         }
00780 
00781         // read characters
00782         if (readable()) {
00783             ch = read();
00784 
00785             if (ch == '\b' || ch == 0x7f) {
00786                 if (!command.empty()) {
00787                     writef("\b \b");
00788                     command.erase(command.size() - 1);
00789                 }
00790                 continue;
00791             } else if (ch == 0x1b || ch == 0x09) {
00792                 osDelay(20);
00793                 // catch escape sequence, or tab
00794                 char ch1 = 0x00, ch2 = 0x00;
00795 
00796                 if (readable()) {
00797                     ch1 = read();
00798                     if (readable())
00799                         ch2 = read();
00800 
00801 #if defined(TARGET_MTS_MDOT_F411RE)
00802                     if (ch1 == 0x5b && ch2 == 0x41) {
00803                         // up key
00804                         for (size_t i = 0; i < command.size() + 1; i++) {
00805                             writef("\b \b");
00806                         }
00807                         if (history.size() > 0) {
00808                             if (++history_index >= int(history.size() - 1))
00809                                 history_index = history.size() - 1;
00810 
00811                             command = history[history_index];
00812                             writef("%s", history[history_index].c_str());
00813                         } else {
00814                             command.clear();
00815                         }
00816                     } else if (ch1 == 0x5b && ch2 == 0x42) {
00817 
00818                         // down key
00819                         for (size_t i = 0; i < command.size() + 1; i++) {
00820                             writef("\b \b");
00821                         }
00822 
00823                         if (--history_index < 0) {
00824                             history_index = -1;
00825                             command.clear();
00826                         } else {
00827                             command = history[history_index];
00828                             writef("%s", history[history_index].c_str());
00829                         }
00830                     }
00831 #endif
00832                 }
00833                 while (readable())
00834                     read();
00835                 continue;
00836             } else {
00837                 command += ch;
00838             }
00839 
00840             // echo chars if enabled
00841             if (echo && !(ch == '\r' || ch == '\n'))
00842                 writef("%c", ch);
00843         }
00844 
00845         // look for end of command line
00846         if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
00847             // remove new line or cr character
00848             command.erase(command.size() - 1);
00849             write("\r"); // match standard modem output
00850             write(newline);
00851         } else {
00852             continue;
00853         }
00854 
00855         // trim whitespace from command
00856         mts::Text::trim(command, "\r\n\t ");
00857 
00858         if (command.size() < 1) {
00859             command.clear();
00860             continue;
00861         }
00862 
00863         // parse command and args
00864         args.clear();
00865 
00866         // find first '=' character
00867         size_t delim_index = command.find("=");
00868         if (delim_index != std::string::npos) {
00869             args.push_back(command.substr(0, delim_index));
00870         } else {
00871             // find first ' ' character
00872             delim_index = command.find(" ");
00873             if (delim_index != std::string::npos) {
00874                 args.push_back(command.substr(0, delim_index));
00875             } else {
00876                 args.push_back(command);
00877             }
00878         }
00879 
00880         if (delim_index != std::string::npos) {
00881             std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
00882             args.insert(args.end(), params.begin(), params.end());
00883         }
00884 
00885         args[0] = mts::Text::toUpper(args[0]);
00886 
00887         // print help
00888         if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
00889             printHelp();
00890             command.clear();
00891         } else if ((args[0].find("ATE?") == 0 && args[0].length() == 4) || (args[0].find("ATE") == 0 && args[0].length() == 3)) {
00892             writef("%d\r\n", _dot->getEcho());
00893             write(done);
00894         } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) {
00895             _dot->setEcho(false);
00896             write(done);
00897             echo = _dot->getEcho();
00898         } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) {
00899             _dot->setEcho(true);
00900             write(done);
00901             echo = _dot->getEcho();
00902         } else if ((args[0].find("ATV?") == 0 && args[0].length() == 4) || (args[0].find("ATV") == 0 && args[0].length() == 3)) {
00903             writef("%d\r\n", _dot->getVerbose());
00904             write(done);
00905         } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) {
00906             _dot->setVerbose(false);
00907             write(done);
00908         } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) {
00909             _dot->setVerbose(true);
00910             write(done);
00911         } else if ((args[0].find("AT&K?") == 0 && args[0].length() == 5) || (args[0].find("AT&K") == 0 && args[0].length() == 4)) {
00912             writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
00913             write(done);
00914         } else if (args[0].find("AT&K0") == 0 && args[0].length() == 5) {
00915             _dot->setFlowControl(false);
00916             write(done);
00917         } else if (args[0].find("AT&K3") == 0 && args[0].length() == 5) {
00918             _dot->setFlowControl(true);
00919             write(done);
00920         } else if (args[0] == "AT+SD") {
00921             if (_dot->getNetworkJoinStatus()) {
00922                 logDebug("Enter Serial Mode");
00923                 write(connect);
00924                 serial_data_mode = true;
00925                 _mode = mDot::SERIAL_MODE;
00926             } else {
00927                 logDebug("Network Not Joined");
00928                 write("Network Not Joined\r\n");
00929                 write(error);
00930             }
00931         } else if (args[0] == "AT+SLEEP") {
00932             if (args.size() > 2 && (args[1] != "?")) {
00933                 write("Invalid argument\r\n");
00934                 write(error);
00935             } else {
00936                 if (args.size() > 1 && args[1] == "?") {
00937                     write("(0:deepsleep,1:sleep)\r\n");
00938                     write(done);
00939                 } else {
00940                     _sleep_standby = !(args.size() > 1 && args[1] == "1");
00941 #if defined(TARGET_MTS_MDOT_F411RE)
00942                     //Read the board ID. If all 0's, it is revision B. This hardware does not support deep sleep.
00943                     DigitalIn ID2(PC_4);
00944                     DigitalIn ID1(PC_5);
00945                     DigitalIn ID0(PD_2);
00946                     if(ID2 == 0 && ID1 == 0 && ID0 == 0 && _sleep_standby == 1){
00947                         _sleep_standby = 0;
00948                         logWarning("This hardware version does not support deep sleep. Using sleep mode instead.");
00949                     }
00950 #endif                    
00951                     write(done);
00952                     osDelay(5);
00953                     this->sleep(_sleep_standby);
00954                     osDelay(1);
00955                 }
00956             }
00957         } else {
00958             bool found = false;
00959             bool query = false;
00960 
00961             std::string lookfor = args[0];
00962 
00963             // per command help
00964             if ((args[0].find("?") == 0 || args[0].find("HELP") == 0))
00965                 lookfor = mts::Text::toUpper(args[1]);
00966 
00967             // trim off any trailing '?' and mark as a query command
00968             if (args[0].rfind("?") == args[0].length() - 1) {
00969                 query = true;
00970                 lookfor = args[0].substr(0, args[0].length() - 1);
00971             }
00972 
00973             // search for command
00974             for (int i = 0; i < NO_OF_COMMANDS; i++) {
00975 
00976                 // match CMD or CMD? syntax if command is queryable
00977                 if (lookfor == _commands[i].text() && (!query || (query && _commands[i].queryable()))) {
00978                     found = true;
00979                     if (args[0] == "HELP") {
00980                         writef("%s%s", _commands[i].help().c_str(), newline);
00981                         write(done);
00982                     }
00983 
00984                     else if (args.size() > 1 && args[1] == "?") {
00985                         writef("%s%s", _commands[i].usage().c_str(), newline);
00986                         write(done);
00987                     } else if (!_verify[i](args)) {
00988                         writef("%s%s", _errorMessage.c_str(), newline);
00989                         writef("%s", error);
00990                     } else {
00991                         if (_action[i](args) == 0) {
00992                             writef("%s", done);
00993                         } else {
00994                             writef("%s%s", _errorMessage.c_str(), newline);
00995                             writef("%s", error);
00996                         }
00997                     }
00998                 }
00999             }
01000 
01001             if (!found) {
01002                 writef("%s", command_error);
01003                 writef("%s", error);
01004             }
01005         }
01006 
01007 #if defined(TARGET_MTS_MDOT_F411RE)
01008         if (history.size() == 0 || history.front() != command)
01009             history.push_front(command);
01010         history_index = -1;
01011         command.clear();
01012 
01013         while (history.size() > 10)
01014             history.pop_back();
01015 #else
01016         command.clear();
01017 #endif
01018     }
01019 }
01020 
01021 void CommandTerminal::sleep(bool standby) {
01022     _xbee_on_sleep = GPIO_PIN_RESET;
01023 
01024     _serial.rxClear();
01025     _serial.txClear();
01026 
01027 #if defined(TARGET_XDOT_L151CC)
01028     xdot_save_gpio_state();
01029 
01030     /* GPIO Ports Clock Enable */
01031     __GPIOA_CLK_ENABLE();
01032     __GPIOB_CLK_ENABLE();
01033     __GPIOC_CLK_ENABLE();
01034     __GPIOH_CLK_ENABLE();
01035 
01036     GPIO_InitTypeDef GPIO_InitStruct;
01037 
01038     // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
01039     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
01040     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01041     GPIO_InitStruct.Pull = GPIO_NOPULL;
01042     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01043 
01044     // I2C_SDA & I2C_SCL to analog nopull
01045     GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
01046     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01047     GPIO_InitStruct.Pull = GPIO_NOPULL;
01048     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01049 
01050     // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
01051     GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
01052     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01053     GPIO_InitStruct.Pull = GPIO_NOPULL;
01054     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01055 
01056     // iterate through potential wake pins - leave the configured wake pin alone if one is needed
01057     if (_dot->getWakePin() != WAKE || _dot->getWakeMode() == mDot::RTC_ALARM) {
01058         GPIO_InitStruct.Pin = GPIO_PIN_0;
01059         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01060         GPIO_InitStruct.Pull = GPIO_NOPULL;
01061         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01062     }
01063     if (_dot->getWakePin() != GPIO0 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01064         GPIO_InitStruct.Pin = GPIO_PIN_4;
01065         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01066         GPIO_InitStruct.Pull = GPIO_NOPULL;
01067         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01068     }
01069     if (_dot->getWakePin() != GPIO1 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01070         GPIO_InitStruct.Pin = GPIO_PIN_5;
01071         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01072         GPIO_InitStruct.Pull = GPIO_NOPULL;
01073         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01074     }
01075     if (_dot->getWakePin() != GPIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01076         GPIO_InitStruct.Pin = GPIO_PIN_0;
01077         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01078         GPIO_InitStruct.Pull = GPIO_NOPULL;
01079         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01080     }
01081     if (_dot->getWakePin() != GPIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01082         GPIO_InitStruct.Pin = GPIO_PIN_2;
01083         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01084         GPIO_InitStruct.Pull = GPIO_NOPULL;
01085         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01086     }
01087     if (_dot->getWakePin() != UART1_RX || _dot->getWakeMode() == mDot::RTC_ALARM) {
01088         GPIO_InitStruct.Pin = GPIO_PIN_10;
01089         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01090         GPIO_InitStruct.Pull = GPIO_NOPULL;
01091         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01092     }
01093 #else
01094     uint32_t portA[6];
01095     uint32_t portB[6];
01096     uint32_t portC[6];
01097     uint32_t portD[6];
01098     uint32_t portH[6];
01099 
01100     //Save the GPIO state.
01101     portA[0] = GPIOA->MODER;
01102     portA[1] = GPIOA->OTYPER;
01103     portA[2] = GPIOA->OSPEEDR;
01104     portA[3] = GPIOA->PUPDR;
01105     portA[4] = GPIOA->AFR[0];
01106     portA[5] = GPIOA->AFR[1];
01107 
01108     portB[0] = GPIOB->MODER;
01109     portB[1] = GPIOB->OTYPER;
01110     portB[2] = GPIOB->OSPEEDR;
01111     portB[3] = GPIOB->PUPDR;
01112     portB[4] = GPIOB->AFR[0];
01113     portB[5] = GPIOB->AFR[1];
01114 
01115     portC[0] = GPIOC->MODER;
01116     portC[1] = GPIOC->OTYPER;
01117     portC[2] = GPIOC->OSPEEDR;
01118     portC[3] = GPIOC->PUPDR;
01119     portC[4] = GPIOC->AFR[0];
01120     portC[5] = GPIOC->AFR[1];
01121 
01122     portD[0] = GPIOD->MODER;
01123     portD[1] = GPIOD->OTYPER;
01124     portD[2] = GPIOD->OSPEEDR;
01125     portD[3] = GPIOD->PUPDR;
01126     portD[4] = GPIOD->AFR[0];
01127     portD[5] = GPIOD->AFR[1];
01128 
01129     portH[0] = GPIOH->MODER;
01130     portH[1] = GPIOH->OTYPER;
01131     portH[2] = GPIOH->OSPEEDR;
01132     portH[3] = GPIOH->PUPDR;
01133     portH[4] = GPIOH->AFR[0];
01134     portH[5] = GPIOH->AFR[1];
01135 
01136     /* GPIO Ports Clock Enable */
01137     __GPIOA_CLK_ENABLE();
01138     __GPIOB_CLK_ENABLE();
01139     __GPIOC_CLK_ENABLE();
01140 
01141     GPIO_InitTypeDef GPIO_InitStruct;
01142 
01143     // Set port A pins to analog nopull
01144     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 
01145                 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
01146     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01147     GPIO_InitStruct.Pull = GPIO_NOPULL;
01148     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    
01149 
01150     // Set port B pins to analog nopull
01151     GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
01152     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01153     GPIO_InitStruct.Pull = GPIO_NOPULL;
01154     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
01155 
01156     // Set port C pins to analog nopull
01157     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
01158     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01159     GPIO_InitStruct.Pull = GPIO_NOPULL;
01160     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
01161 
01162     // iterate through potential wake pins - leave the configured wake pin alone if one is needed
01163     // XBEE_DIN - PA3
01164     // XBEE_DIO2 - PA5
01165     // XBEE_DIO3 - PA4
01166     // XBEE_DIO4 - PA7
01167     // XBEE_DIO5 - PC1
01168     // XBEE_DIO6 - PA1
01169     // XBEE_DIO7 - PA0
01170     // XBEE_SLEEPRQ - PA11
01171                 
01172     if (_dot->getWakePin() != XBEE_DIN || _dot->getWakeMode() == mDot::RTC_ALARM) {
01173         GPIO_InitStruct.Pin = GPIO_PIN_3;
01174         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01175         GPIO_InitStruct.Pull = GPIO_NOPULL;
01176         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01177     }
01178 
01179     if (_dot->getWakePin() != XBEE_DIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01180         GPIO_InitStruct.Pin = GPIO_PIN_5;
01181         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01182         GPIO_InitStruct.Pull = GPIO_NOPULL;
01183         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01184     }
01185 
01186     if (_dot->getWakePin() != XBEE_DIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01187         GPIO_InitStruct.Pin = GPIO_PIN_4;
01188         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01189         GPIO_InitStruct.Pull = GPIO_NOPULL;
01190         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01191     }
01192 
01193          if (_dot->getWakePin() != XBEE_DIO4 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01194         GPIO_InitStruct.Pin = GPIO_PIN_7;
01195         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01196         GPIO_InitStruct.Pull = GPIO_NOPULL;
01197         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01198     }
01199 
01200      if (_dot->getWakePin() != XBEE_DIO5 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01201         GPIO_InitStruct.Pin = GPIO_PIN_1;
01202         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01203         GPIO_InitStruct.Pull = GPIO_NOPULL;
01204         HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
01205     }
01206 
01207      if (_dot->getWakePin() != XBEE_DIO6 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01208         GPIO_InitStruct.Pin = GPIO_PIN_1;
01209         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01210         GPIO_InitStruct.Pull = GPIO_NOPULL;
01211         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01212     }
01213 
01214      if (_dot->getWakePin() != XBEE_DIO7 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01215         GPIO_InitStruct.Pin = GPIO_PIN_0;
01216         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01217         GPIO_InitStruct.Pull = GPIO_NOPULL;
01218         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01219     }
01220 
01221      if (_dot->getWakePin() != XBEE_SLEEPRQ|| _dot->getWakeMode() == mDot::RTC_ALARM) {
01222         GPIO_InitStruct.Pin = GPIO_PIN_11;
01223         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01224         GPIO_InitStruct.Pull = GPIO_NOPULL;
01225         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01226     }
01227  
01228 #endif
01229     _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
01230 
01231 #if defined(TARGET_XDOT_L151CC)
01232     xdot_restore_gpio_state();
01233 #else
01234     //Restore the GPIO state.
01235     GPIOA->MODER = portA[0];
01236     GPIOA->OTYPER = portA[1];
01237     GPIOA->OSPEEDR = portA[2];
01238     GPIOA->PUPDR = portA[3];
01239     GPIOA->AFR[0] = portA[4];
01240     GPIOA->AFR[1] = portA[5];
01241 
01242     GPIOB->MODER = portB[0];
01243     GPIOB->OTYPER = portB[1];
01244     GPIOB->OSPEEDR = portB[2];
01245     GPIOB->PUPDR = portB[3];
01246     GPIOB->AFR[0] = portB[4];
01247     GPIOB->AFR[1] = portB[5];
01248 
01249     GPIOC->MODER = portC[0];
01250     GPIOC->OTYPER = portC[1];
01251     GPIOC->OSPEEDR = portC[2];
01252     GPIOC->PUPDR = portC[3];
01253     GPIOC->AFR[0] = portC[4];
01254     GPIOC->AFR[1] = portC[5];
01255 
01256     GPIOD->MODER = portD[0];
01257     GPIOD->OTYPER = portD[1];
01258     GPIOD->OSPEEDR = portD[2];
01259     GPIOD->PUPDR = portD[3];
01260     GPIOD->AFR[0] = portD[4];
01261     GPIOD->AFR[1] = portD[5];
01262 
01263     GPIOH->MODER = portH[0];
01264     GPIOH->OTYPER = portH[1];
01265     GPIOH->OSPEEDR = portH[2];
01266     GPIOH->PUPDR = portH[3];
01267     GPIOH->AFR[0] = portH[4];
01268     GPIOH->AFR[1] = portH[5];
01269 #endif
01270 
01271     _serial.rxClear();
01272     _serial.txClear();
01273 }
01274 
01275 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
01276     if (format == mDot::HEXADECIMAL)
01277         return mts::Text::bin2hexString(data);
01278     else
01279         return std::string(data.begin(), data.end());
01280 }
01281 
01282 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
01283     Timer timer;
01284 
01285     timer.start();
01286     while (timer.read_ms() < timeout) {
01287 
01288         if (dot != NULL) {
01289             if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
01290                 return false;
01291             }
01292         }
01293 
01294         if (_serialp != NULL && _serialp->escaped()) {
01295             _serialp->clearEscaped();
01296             return true;
01297         }
01298 
01299         osDelay(10);
01300     }
01301 
01302     return false;
01303 }
01304 
01305 void CommandTerminal::wakeup(void) {
01306 }
01307 
01308 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) {
01309     mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, retries);
01310 
01311     if (serial_data_mode) {
01312         logDebug("Rx %d bytes", size);
01313         if (size > 0) {
01314             CommandTerminal::Serial()->write((char*) RxPayload, RxPayloadSize);
01315         }
01316         if (!CommandTerminal::Serial()->readable() && _dot->getAckRequested() && _dot->getClass() == "C") {
01317             _sendAck = true;
01318         }
01319     }
01320 }
01321 
01322 CommandTerminal::~CommandTerminal() {
01323     delete _events;
01324 }