MicroLabo / Mbed OS mbed-Dot-AT-Firmware

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