Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MTS-Serial libxDot-mbed5
Diff: CommandTerminal/CommandTerminal.cpp
- Revision:
- 14:f9a77400b622
- Parent:
- 11:05e0f30c03a6
- Child:
- 16:d5cf2af81a6d
--- a/CommandTerminal/CommandTerminal.cpp Fri Nov 04 19:10:24 2016 +0000
+++ b/CommandTerminal/CommandTerminal.cpp Fri Nov 04 14:25:43 2016 -0500
@@ -4,8 +4,15 @@
#include "MTSLog.h"
#include <cstdarg>
#include <deque>
+#if defined(TARGET_XDOT_L151CC)
+#include "xdot_low_power.h"
+#endif
+#if defined(TARGET_MTS_MDOT_F411RE)
const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
+#else
+const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa xDot Module\r\n\n";
+#endif
const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
const char CommandTerminal::newline[] = "\r\n";
@@ -25,120 +32,372 @@
const char CommandTerminal::escape_sequence[] = "+++";
mts::ATSerial* CommandTerminal::_serialp = NULL;
+mDot* CommandTerminal::_dot = NULL;
+
+CommandTerminal::RadioEvent* CommandTerminal::_events = new RadioEvent();
static bool serial_data_mode = false;
static bool peer_to_peer = false;
-void CommandTerminal::addCommand(Command* cmd) {
- _commands.push_back(cmd);
+std::string CommandTerminal::_errorMessage = "";
+
+void CommandTerminal::setErrorMessage(const char* message) {
+ _errorMessage.assign(message);
+}
+
+void CommandTerminal::setErrorMessage(const std::string& message) {
+ _errorMessage.assign(message);
}
-CommandTerminal::CommandTerminal(mts::ATSerial& serial, mDot* dot)
-:
- _serial(serial),
- _dot(dot),
- _events(new RadioEvent(serial)),
- _mode(mDot::COMMAND_MODE),
- _idle_thread(idle, NULL, osPriorityLow),
- _sleep_standby(true),
- _xbee_on_sleep(XBEE_ON_SLEEP) {
+const Command CommandTerminal::_commands[NO_OF_COMMANDS] = {
+ CmdAttention(),
+ CmdIdentification(),
+ CmdResetCpu(),
+ CmdDummy("Enable/Disable Echo", "ATE", "ATE0: disable, ATE1: enable", "(0,1)"),
+ CmdDummy("Enable/Disable Verbose", "ATV", "ATV0: disable, ATV1: enable", "(0,1)"),
+ CmdDummy("Hardware Flow Control", "AT&K", "AT&K0: disable, AT&K3: enable", "(0,3)"),
+
+ CmdFactoryDefault(),
+ CmdSaveConfig(),
+ CmdDisplayConfig(),
+ CmdDisplayStats(),
+ CmdResetStats(),
+ CmdSerialBaudRate(),
+ CmdDebugBaudRate(),
+ CmdStartUpMode(),
+
+ CmdFrequencyBand(),
+ CmdFrequencySubBand(),
+ CmdPublicNetwork(),
+ CmdDeviceId(),
+ CmdDeviceClass(),
+
+ CmdAppPort(),
+ CmdNetworkAddress(),
+ CmdNetworkSessionKey(),
+ CmdDataSessionKey(),
+ CmdUplinkCounter(),
+ CmdDownlinkCounter(),
+ CmdSaveSession(),
+ CmdRestoreSession(),
+ CmdNetworkKey(),
+ CmdNetworkId(),
- _dot->setEvents(_events);
- _dot->setWakeupCallback(this, &CommandTerminal::wakeup);
- _serialp = &serial;
+ CmdJoinDelay(),
+// Remove join settings commands until valid case for changing default settings
+// CmdJoinRx1Offset(),
+// CmdJoinRx2Datarate(),
+// CmdJoinRx2Frequency(),
+ CmdJoinRequest(),
+ CmdJoinRetries(),
+ CmdJoinByteOrder(),
+ CmdNetworkJoinMode(),
+ CmdPreserveSession(),
+ CmdNetworkJoinStatus(),
+ CmdNetworkLinkCheck(),
+ CmdLinkCheckCount(),
+ CmdLinkCheckThreshold(),
+ CmdEncryption(),
+
+ CmdRssi(),
+ CmdSnr(),
+ CmdDataPending(),
+
+ CmdSessionDataRate(),
+ CmdChannelMask(),
- addCommand(new CmdAttention(_dot));
- addCommand(new CmdIdentification(_dot, serial));
- addCommand(new CmdResetCpu(_dot, serial));
- addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE", "ATE0: disable, ATE1: enable"));
- addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV", "ATV0: disable, ATV1: enable"));
- addCommand(new CmdDummy(_dot, "Hardware Flow Control", "AT&K", "AT&K0: disable, AT&K3: enable"));
+ CmdTxDataRate(),
+ CmdTxPower(),
+ CmdAntennaGain(),
+ CmdTxFrequency(),
+ CmdTxInverted(),
+ CmdTxWait(),
+ CmdTxChannel(),
+ CmdTxNextMs(),
+ CmdTimeOnAir(),
+
+ CmdRxDelay(),
+ CmdRxOutput(),
+ CmdRxInverted(),
+
+ CmdErrorCorrection(),
+ CmdCRC(),
+ CmdAdaptiveDataRate(),
+
+ CmdACKAttempts(),
+ CmdRepeat(),
+ CmdMacCmd(),
+
+ CmdSendString(),
+ CmdSendBinary(),
+ CmdReceiveOnce(),
- addCommand(new CmdFactoryDefault(_dot));
- addCommand(new CmdSaveConfig(_dot));
- addCommand(new CmdDisplayConfig(_dot, serial));
- addCommand(new CmdDisplayStats(_dot, serial));
- addCommand(new CmdResetStats(_dot, serial));
- addCommand(new CmdSerialBaudRate(_dot, serial));
- addCommand(new CmdDebugBaudRate(_dot, serial));
- addCommand(new CmdStartUpMode(_dot, serial));
+ CmdDummy("Serial Data Mode", "AT+SD", "Enter serial data mode, exit with '+++'", "NONE"),
+ CmdDummy("Sleep Mode", "AT+SLEEP", "Enter sleep mode (0:deepsleep,1:sleep)", "(0,1)"),
+ CmdSerialClearOnError(),
+ CmdWakeMode(),
+ CmdWakeInterval(),
+ CmdWakePin(),
+ CmdWakeDelay(),
+ CmdWakeTimeout(),
+ CmdPing(),
+ CmdLogLevel(),
+
+ CmdDummy("***** Test Commands *****", "", "", ""),
+ CmdRxDataRate(),
+ CmdRxFrequency(),
+ CmdReceiveContinuous(),
+ CmdSendStringOnInterval(),
+
+#ifdef MTS_RADIO_DEBUG_COMMANDS
+ CmdDummy("***** Debug Commands *****", "", "", ""),
+ CmdSendContinuous(),
+ CmdWriteProtectedConfig(),
+ CmdDumpRegisters(),
+ CmdEraseFlash(),
+ CmdDisableDutyCycle(),
+#endif
+
+};
+
+const verify_ptr_t CommandTerminal::_verify[NO_OF_COMMANDS] = {
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
- addCommand(new CmdFrequencyBand(_dot, serial));
- addCommand(new CmdFrequencySubBand(_dot, serial));
- addCommand(new CmdPublicNetwork(_dot, serial));
- addCommand(new CmdDeviceId(_dot, serial));
- addCommand(new CmdDeviceClass(_dot, serial));
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdSerialBaudRate::verify,
+ CmdDebugBaudRate::verify,
+ CmdStartUpMode::verify,
+
+ CmdFrequencyBand::verify,
+ CmdFrequencySubBand::verify,
+ CmdPublicNetwork::verify,
+ CmdDeviceId::verify,
+ CmdDeviceClass::verify,
- addCommand(new CmdAppPort(_dot, serial));
- addCommand(new CmdNetworkAddress(_dot, serial));
- addCommand(new CmdNetworkSessionKey(_dot, serial));
- addCommand(new CmdDataSessionKey(_dot, serial));
- addCommand(new CmdUplinkCounter(_dot, serial));
- addCommand(new CmdDownlinkCounter(_dot, serial));
- addCommand(new CmdSaveSession(_dot, serial));
- addCommand(new CmdRestoreSession(_dot, serial));
- addCommand(new CmdNetworkKey(_dot, serial));
- addCommand(new CmdNetworkId(_dot, serial));
+ CmdAppPort::verify,
+ CmdNetworkAddress::verify,
+ CmdNetworkSessionKey::verify,
+ CmdDataSessionKey::verify,
+ CmdUplinkCounter::verify,
+ CmdDownlinkCounter::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdNetworkKey::verify,
+ CmdNetworkId::verify,
+
+ CmdJoinDelay::verify,
+// Remove join settings commands until valid case for changing default settings
+// CmdJoinRx1Offset::verify,
+// CmdJoinRx2Datarate::verify,
+// CmdJoinRx2Frequency::verify,
+ CmdJoinRequest::verify,
+ CmdJoinRetries::verify,
+ CmdJoinByteOrder::verify,
+ CmdNetworkJoinMode::verify,
+ CmdPreserveSession::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdLinkCheckCount::verify,
+ CmdLinkCheckThreshold::verify,
+ CmdEncryption::verify,
+
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+
+ CmdSessionDataRate::verify,
+ CmdChannelMask::verify,
- addCommand(new CmdJoinDelay(_dot, serial));
- addCommand(new CmdJoinRequest(_dot, serial));
- addCommand(new CmdJoinRetries(_dot, serial));
- addCommand(new CmdJoinByteOrder(_dot, serial));
- addCommand(new CmdNetworkJoinMode(_dot, serial));
- addCommand(new CmdPreserveSession(_dot, serial));
- addCommand(new CmdNetworkJoinStatus(_dot, serial));
- addCommand(new CmdNetworkLinkCheck(_dot, serial));
- addCommand(new CmdLinkCheckCount(_dot, serial));
- addCommand(new CmdLinkCheckThreshold(_dot, serial));
- addCommand(new CmdEncryption(_dot, serial));
+ CmdTxDataRate::verify,
+ CmdTxPower::verify,
+ CmdAntennaGain::verify,
+ CmdTxFrequency::verify,
+ CmdTxInverted::verify,
+ CmdTxWait::verify,
+ CmdTxChannel::verify,
+ CmdTxNextMs::verify,
+ CmdTimeOnAir::verify,
+
+ CmdRxDelay::verify,
+ CmdRxOutput::verify,
+ CmdRxInverted::verify,
+
+ CmdErrorCorrection::verify,
+ CmdCRC::verify,
+ CmdAdaptiveDataRate::verify,
+
+ CmdACKAttempts::verify,
+ CmdRepeat::verify,
+ CmdMacCmd::verify,
+
+ CmdSendString::verify,
+ CmdSendBinary::verify,
+ CmdReceiveOnce::verify,
+
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdSerialClearOnError::verify,
+ CmdWakeMode::verify,
+ CmdWakeInterval::verify,
+ CmdWakePin::verify,
+ CmdWakeDelay::verify,
+ CmdWakeTimeout::verify,
+ CmdDummy::verify,
+ CmdLogLevel::verify,
+
+ CmdDummy::verify,
+ CmdRxDataRate::verify,
+ CmdRxFrequency::verify,
+ CmdReceiveContinuous::verify,
+ CmdSendStringOnInterval::verify,
- addCommand(new CmdRssi(_dot, serial));
- addCommand(new CmdSnr(_dot, serial));
- addCommand(new CmdDataPending(_dot, serial));
+#ifdef MTS_RADIO_DEBUG_COMMANDS
+ CmdDummy::verify,
+ CmdSendContinuous::verify,
+ CmdDummy::verify,
+ CmdDummy::verify,
+ CmdEraseFlash::verify,
+ CmdDisableDutyCycle::verify,
+#endif
- addCommand(new CmdSessionDataRate(_dot, serial));
+};
+
+const action_ptr_t CommandTerminal::_action[NO_OF_COMMANDS] = {
+ CmdAttention::action,
+ CmdIdentification::action,
+ CmdResetCpu::action,
+ CmdDummy::action,
+ CmdDummy::action,
+ CmdDummy::action,
- addCommand(new CmdTxDataRate(_dot, serial));
- addCommand(new CmdTxPower(_dot, serial));
- addCommand(new CmdAntennaGain(_dot, serial));
- addCommand(new CmdTxFrequency(_dot, serial));
- addCommand(new CmdTxInverted(_dot, serial));
- addCommand(new CmdTxWait(_dot, serial));
- addCommand(new CmdTxChannel(_dot, serial));
- addCommand(new CmdTxNextMs(_dot, serial));
- addCommand(new CmdTimeOnAir(_dot, serial));
+ CmdFactoryDefault::action,
+ CmdSaveConfig::action,
+ CmdDisplayConfig::action,
+ CmdDisplayStats::action,
+ CmdResetStats::action,
+ CmdSerialBaudRate::action,
+ CmdDebugBaudRate::action,
+ CmdStartUpMode::action,
+
+ CmdFrequencyBand::action,
+ CmdFrequencySubBand::action,
+ CmdPublicNetwork::action,
+ CmdDeviceId::action,
+ CmdDeviceClass::action,
+
+ CmdAppPort::action,
+ CmdNetworkAddress::action,
+ CmdNetworkSessionKey::action,
+ CmdDataSessionKey::action,
+ CmdUplinkCounter::action,
+ CmdDownlinkCounter::action,
+ CmdSaveSession::action,
+ CmdRestoreSession::action,
+ CmdNetworkKey::action,
+ CmdNetworkId::action,
- addCommand(new CmdRxDelay(_dot, serial));
- addCommand(new CmdRxOutput(_dot, serial));
- addCommand(new CmdRxInverted(_dot, serial));
+ CmdJoinDelay::action,
+// Remove join settings commands until valid case for changing default settings
+// CmdJoinRx1Offset::action,
+// CmdJoinRx2Datarate::action,
+// CmdJoinRx2Frequency::action,
+ CmdJoinRequest::action,
+ CmdJoinRetries::action,
+ CmdJoinByteOrder::action,
+ CmdNetworkJoinMode::action,
+ CmdPreserveSession::action,
+ CmdNetworkJoinStatus::action,
+ CmdNetworkLinkCheck::action,
+ CmdLinkCheckCount::action,
+ CmdLinkCheckThreshold::action,
+ CmdEncryption::action,
+
+ CmdRssi::action,
+ CmdSnr::action,
+ CmdDataPending::action,
- addCommand(new CmdErrorCorrection(_dot, serial));
- addCommand(new CmdCRC(_dot, serial));
- addCommand(new CmdAdaptiveDataRate(_dot, serial));
+ CmdSessionDataRate::action,
+ CmdChannelMask::action,
- addCommand(new CmdACKAttempts(_dot, serial));
- addCommand(new CmdRepeat(_dot, serial));
+ CmdTxDataRate::action,
+ CmdTxPower::action,
+ CmdAntennaGain::action,
+ CmdTxFrequency::action,
+ CmdTxInverted::action,
+ CmdTxWait::action,
+ CmdTxChannel::action,
+ CmdTxNextMs::action,
+ CmdTimeOnAir::action,
- addCommand(new CmdSendString(_dot, serial));
- addCommand(new CmdSendBinary(_dot, serial));
- addCommand(new CmdReceiveOnce(_dot, serial));
+ CmdRxDelay::action,
+ CmdRxOutput::action,
+ CmdRxInverted::action,
+
+ CmdErrorCorrection::action,
+ CmdCRC::action,
+ CmdAdaptiveDataRate::action,
+
+ CmdACKAttempts::action,
+ CmdRepeat::action,
+ CmdMacCmd::action,
- addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Enter serial data mode, exit with '+++'"));
- addCommand(new CmdDummy(_dot, "Sleep Mode", "AT+SLEEP", "Enter sleep mode (0:deepsleep,1:sleep)"));
- addCommand(new CmdSerialClearOnError(_dot, serial));
- addCommand(new CmdWakeMode(_dot, serial));
- addCommand(new CmdWakeInterval(_dot, serial));
- addCommand(new CmdWakePin(_dot, serial));
- addCommand(new CmdWakeDelay(_dot, serial));
- addCommand(new CmdWakeTimeout(_dot, serial));
- addCommand(new CmdPing(_dot, serial));
- addCommand(new CmdLogLevel(_dot, serial));
+ CmdSendString::action,
+ CmdSendBinary::action,
+ CmdReceiveOnce::action,
+
+ CmdDummy::action,
+ CmdDummy::action,
+ CmdSerialClearOnError::action,
+ CmdWakeMode::action,
+ CmdWakeInterval::action,
+ CmdWakePin::action,
+ CmdWakeDelay::action,
+ CmdWakeTimeout::action,
+ CmdPing::action,
+ CmdLogLevel::action,
+
+ CmdDummy::action,
+ CmdRxDataRate::action,
+ CmdRxFrequency::action,
+ CmdReceiveContinuous::action,
+ CmdSendStringOnInterval::action,
- addCommand(new CmdDummy(_dot, "***** Test Commands *****", "", ""));
- addCommand(new CmdRxDataRate(_dot, serial));
- addCommand(new CmdRxFrequency(_dot, serial));
- addCommand(new CmdReceiveContinuous(_dot, serial));
- addCommand(new CmdSendStringOnInterval(_dot, serial));
+#ifdef MTS_RADIO_DEBUG_COMMANDS
+ CmdDummy::action,
+ CmdSendContinuous::action,
+ CmdWriteProtectedConfig::action,
+ CmdDumpRegisters::action,
+ CmdEraseFlash::action,
+ CmdDisableDutyCycle::action,
+#endif
+
+};
+
+CommandTerminal::CommandTerminal(mts::ATSerial& serial) :
+ _serial(serial),
+ _mode(mDot::COMMAND_MODE),
+ _sleep_standby(true),
+#if defined(TARGET_MTS_MDOT_F411RE)
+ _xbee_on_sleep(XBEE_ON_SLEEP),
+#else
+ _xbee_on_sleep(GPIO2),
+#endif
+ _autoOTAEnabled(false)
+{
+ _serialp = &serial;
+}
+
+void CommandTerminal::init() {
+ _dot->setEvents(_events);
}
void CommandTerminal::printHelp() {
@@ -160,10 +419,11 @@
write(header.c_str());
write(newline);
write(newline);
- for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) {
- name = (*it)->name();
- text = (*it)->text();
- desc = (*it)->desc();
+
+ for (int i = 0; i < NO_OF_COMMANDS; i++) {
+ name = _commands[i].name();
+ text = _commands[i].text();
+ desc = _commands[i].desc();
write(text);
if (strlen(text) < 8)
write(tab);
@@ -182,23 +442,23 @@
}
bool CommandTerminal::writeable() {
- return _serial.writeable();
+ return _serialp->writeable();
}
bool CommandTerminal::readable() {
- return _serial.readable();
+ return _serialp->readable();
}
char CommandTerminal::read() {
char ch;
- _serial.read(&ch, 1);
+ _serialp->read(&ch, 1);
return ch;
}
void CommandTerminal::write(const char* message) {
while (!writeable())
;
- _serial.write(message, strlen(message));
+ _serialp->write(message, strlen(message));
}
void CommandTerminal::writef(const char* format, ...) {
@@ -209,7 +469,7 @@
int size = vsnprintf(buff, 256, format, ap);
while (!writeable())
;
- _serial.write(buff, size);
+ _serialp->write(buff, size);
va_end(ap);
}
@@ -227,12 +487,17 @@
timeout = _dot->getWakeDelay();
// wait for timeout or start of serial data
- while (!readable() && serial_read_timer.read_ms() < timeout && !_serial.escaped()) {
+ while (!readable() && serial_read_timer.read_ms() < timeout && !_serialp->escaped()) {
osDelay(2);
}
}
- if (readable() && !_serial.escaped()) {
+ if (!readable() && _events->SendAck()) {
+ logDebug("SERIAL NOT READABLE and ACK REQUESTED");
+ goto L_SEND;
+ }
+
+ if (readable() && !_serialp->escaped()) {
serial_read_timer.reset();
timeout = _dot->getWakeTimeout();
@@ -242,7 +507,7 @@
serial_buffer.push_back(read());
serial_read_timer.reset();
- if (_serial.escaped())
+ if (_serialp->escaped())
break;
}
}
@@ -251,14 +516,15 @@
if (!serial_buffer.empty()) {
if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
- _xbee_on_sleep = GPIO_PIN_RESET;
+ _xbee_on_sleep = GPIO_PIN_RESET;
+L_SEND:
// wait for any duty cycle limit to expire
- while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
+ while (_dot->getNextTxMs() > 0 && !_serialp->escaped()) {
osDelay(10);
}
- if (!_dot->getIsTransmitting()) {
+ if (_dot->getIsIdle()) {
logDebug("Received serial data, sending out radio.");
if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
@@ -270,15 +536,28 @@
} else {
// wait for send to finish
- while (_dot->getIsTransmitting() && !_serial.escaped())
+ while (!_dot->getIsIdle() && !_serialp->escaped()) {
osDelay(10);
+ }
// call recv to wait for any packet before sending again
- if (!_serial.escaped())
+ if (!_serialp->escaped())
_dot->recv(data);
// Clear the serial buffer if send is success
serial_buffer.clear();
+
+ // In class C mode pending data will be sent automatically without uplink
+ if (_dot->getClass() != "C") {
+ if (_dot->getDataPending()) {
+ logDebug("Data is pending");
+ goto L_SEND;
+ }
+ if (_dot->getAckRequested()) {
+ logDebug("Ack requested");
+ goto L_SEND;
+ }
+ }
}
} else {
logDebug("Radio is busy, cannot send.\r\n");
@@ -290,14 +569,13 @@
}
}
- if (!_serial.readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serial.escaped()) {
- _xbee_on_sleep = GPIO_PIN_RESET;
- sleep(_sleep_standby);
+ if (!_serialp->readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serialp->escaped()) {
+ sleep(true);
}
- if (_serial.escaped()) {
- _serial.clearEscaped();
- _serial.rxClear();
+ if (_serialp->escaped()) {
+ _serialp->clearEscaped();
+ _serialp->rxClear();
serial_data_mode = false;
_mode = mDot::COMMAND_MODE;
logDebug("Exit Serial Mode");
@@ -323,42 +601,46 @@
int cnt = 0;
while (!_dot->getNetworkJoinStatus()) {
- write("\r\nJoining network... ");
+ if (!serial_data_mode) {
+ write("\r\nJoining network... ");
+ }
+ logInfo("Joining network... ");
if (_dot->getNextTxMs() > 0) {
- int rand_time = rand() % 10000;
- writef("\r\nWaiting %lu s before next join attempt\r\n", (_dot->getNextTxMs() + rand_time) / 1000);
+ if (!serial_data_mode) {
+ writef("\r\nWaiting %lu s before next join attempt\r\n", _dot->getNextTxMs() / 1000);
+ }
+ logInfo("Waiting %lu s before next join attempt", _dot->getNextTxMs() / 1000);
tmr.reset();
while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
- osDelay(2);
+ osDelay(20);
}
-
- tmr.reset();
- while (tmr.read_ms() < rand_time && !_serial.escaped())
- osDelay(10);
}
if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
- write("Network Joined\r\n");
- write(done);
+ if (!serial_data_mode) {
+ write("Network Joined\r\n");
+ write(done);
+ }
+ logInfo("Network Joined");
return false;
}
- write("Network Join failed\r\n");
- write(error);
+ if (!serial_data_mode) {
+ write("Network Join failed\r\n");
+ write(error);
+ }
+ logInfo("Network Join failed");
- if (!_serial.escaped() && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
+ if (!_serial.escaped() && _dot->getFrequencySubBand() != 0 && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
cnt = 0;
- if (_dot->getFrequencyBand() == mDot::FB_915) {
+ if (_dot->getFrequencyBand() == mDot::FB_US915 || _dot->getFrequencyBand() == mDot::FB_AU915 ) {
uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
logWarning("Join retries exhausted, switching to sub band %u", band);
_dot->setFrequencySubBand(band);
}
-
- if (sleep < 60 * 60 * 1000)
- sleep *= 2;
}
tmr.reset();
@@ -370,8 +652,11 @@
_serial.clearEscaped();
serial_data_mode = false;
_mode = mDot::COMMAND_MODE;
- write("Join Canceled\r\n");
- write(done);
+ if (!serial_data_mode) {
+ write("Join Canceled\r\n");
+ write(done);
+ }
+ logInfo("Join Canceled\r\n");
return true;
}
}
@@ -385,11 +670,15 @@
bool running = true;
bool echo = _dot->getEcho();
std::string command;
+#if defined(TARGET_MTS_MDOT_F411RE)
std::deque<std::string> history;
int history_index = -1;
+#endif
std::vector<std::string> args;
bool join_canceled = false;
+ _autoOTAEnabled = _dot->getJoinMode() == mDot::AUTO_OTA;
+
if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
serial_data_mode = true;
@@ -450,20 +739,18 @@
peer_to_peer = false;
}
-
-
//Run terminal session
while (running) {
// wait for input to reduce at command idle current
while (!readable() || _mode == mDot::SERIAL_MODE) {
- if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) {
+ if (!join_canceled && _autoOTAEnabled) {
join_canceled = autoJoinCheck();
if (join_canceled)
command.clear();
}
- if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) {
+ if (!_autoOTAEnabled || (!join_canceled && _autoOTAEnabled)) {
switch (_mode) {
case mDot::SERIAL_MODE:
// signal wakeup, read serial and output to radio
@@ -501,6 +788,7 @@
if (readable())
ch2 = read();
+#if defined(TARGET_MTS_MDOT_F411RE)
if (ch1 == 0x5b && ch2 == 0x41) {
// up key
for (size_t i = 0; i < command.size() + 1; i++) {
@@ -530,6 +818,7 @@
writef("%s", history[history_index].c_str());
}
}
+#endif
}
while (readable())
read();
@@ -639,9 +928,20 @@
write(done);
} else {
_sleep_standby = !(args.size() > 1 && args[1] == "1");
+#if defined(TARGET_MTS_MDOT_F411RE)
+ //Read the board ID. If all 0's, it is revision B. This hardware does not support deep sleep.
+ DigitalIn ID2(PC_4);
+ DigitalIn ID1(PC_5);
+ DigitalIn ID0(PD_2);
+ if(ID2 == 0 && ID1 == 0 && ID0 == 0 && _sleep_standby == 1){
+ _sleep_standby = 0;
+ logWarning("This hardware version does not support deep sleep. Using sleep mode instead.");
+ }
+#endif
write(done);
+ osDelay(5);
this->sleep(_sleep_standby);
- wait(0.1);
+ osDelay(1);
}
}
} else {
@@ -661,28 +961,27 @@
}
// search for command
- for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) {
- Command* cmd = *it;
+ for (int i = 0; i < NO_OF_COMMANDS; i++) {
// match CMD or CMD? syntax if command is queryable
- if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
+ if (lookfor == _commands[i].text() && (!query || (query && _commands[i].queryable()))) {
found = true;
if (args[0] == "HELP") {
- writef("%s%s", cmd->help(), newline);
+ writef("%s%s", _commands[i].help().c_str(), newline);
write(done);
}
else if (args.size() > 1 && args[1] == "?") {
- writef("%s%s", cmd->usage().c_str(), newline);
+ writef("%s%s", _commands[i].usage().c_str(), newline);
write(done);
- } else if (!cmd->verify(args)) {
- writef("%s%s", cmd->errorMessage().c_str(), newline);
+ } else if (!_verify[i](args)) {
+ writef("%s%s", _errorMessage.c_str(), newline);
writef("%s", error);
} else {
- if (cmd->action(args) == 0) {
+ if (_action[i](args) == 0) {
writef("%s", done);
} else {
- writef("%s%s", cmd->errorMessage().c_str(), newline);
+ writef("%s%s", _errorMessage.c_str(), newline);
writef("%s", error);
}
}
@@ -695,6 +994,7 @@
}
}
+#if defined(TARGET_MTS_MDOT_F411RE)
if (history.size() == 0 || history.front() != command)
history.push_front(command);
history_index = -1;
@@ -702,23 +1002,271 @@
while (history.size() > 10)
history.pop_back();
+#else
+ command.clear();
+#endif
}
}
-std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
- if (format == mDot::HEXADECIMAL)
- return mts::Text::bin2hexString(data);
- else
- return std::string(data.begin(), data.end());
-}
-
void CommandTerminal::sleep(bool standby) {
_xbee_on_sleep = GPIO_PIN_RESET;
_serial.rxClear();
_serial.txClear();
+#if defined(TARGET_XDOT_L151CC)
+ xdot_save_gpio_state();
+
+ /* GPIO Ports Clock Enable */
+ __GPIOA_CLK_ENABLE();
+ __GPIOB_CLK_ENABLE();
+ __GPIOC_CLK_ENABLE();
+ __GPIOH_CLK_ENABLE();
+
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
+ GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ // I2C_SDA & I2C_SCL to analog nopull
+ GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
+ GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+ if (_dot->getWakePin() != WAKE || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_0;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+ if (_dot->getWakePin() != GPIO0 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_4;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+ if (_dot->getWakePin() != GPIO1 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_5;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+ if (_dot->getWakePin() != GPIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_0;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+ }
+ if (_dot->getWakePin() != GPIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_2;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+ }
+ if (_dot->getWakePin() != UART1_RX || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+#else
+ uint32_t portA[6];
+ uint32_t portB[6];
+ uint32_t portC[6];
+ uint32_t portD[6];
+ uint32_t portH[6];
+
+ //Save the GPIO state.
+ portA[0] = GPIOA->MODER;
+ portA[1] = GPIOA->OTYPER;
+ portA[2] = GPIOA->OSPEEDR;
+ portA[3] = GPIOA->PUPDR;
+ portA[4] = GPIOA->AFR[0];
+ portA[5] = GPIOA->AFR[1];
+
+ portB[0] = GPIOB->MODER;
+ portB[1] = GPIOB->OTYPER;
+ portB[2] = GPIOB->OSPEEDR;
+ portB[3] = GPIOB->PUPDR;
+ portB[4] = GPIOB->AFR[0];
+ portB[5] = GPIOB->AFR[1];
+
+ portC[0] = GPIOC->MODER;
+ portC[1] = GPIOC->OTYPER;
+ portC[2] = GPIOC->OSPEEDR;
+ portC[3] = GPIOC->PUPDR;
+ portC[4] = GPIOC->AFR[0];
+ portC[5] = GPIOC->AFR[1];
+
+ portD[0] = GPIOD->MODER;
+ portD[1] = GPIOD->OTYPER;
+ portD[2] = GPIOD->OSPEEDR;
+ portD[3] = GPIOD->PUPDR;
+ portD[4] = GPIOD->AFR[0];
+ portD[5] = GPIOD->AFR[1];
+
+ portH[0] = GPIOH->MODER;
+ portH[1] = GPIOH->OTYPER;
+ portH[2] = GPIOH->OSPEEDR;
+ portH[3] = GPIOH->PUPDR;
+ portH[4] = GPIOH->AFR[0];
+ portH[5] = GPIOH->AFR[1];
+
+ /* GPIO Ports Clock Enable */
+ __GPIOA_CLK_ENABLE();
+ __GPIOB_CLK_ENABLE();
+ __GPIOC_CLK_ENABLE();
+
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ // Set port A pins to analog nopull
+ GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10
+ | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ // Set port B pins to analog nopull
+ GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ // Set port C pins to analog nopull
+ GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+ // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+ // XBEE_DIN - PA3
+ // XBEE_DIO2 - PA5
+ // XBEE_DIO3 - PA4
+ // XBEE_DIO4 - PA7
+ // XBEE_DIO5 - PC1
+ // XBEE_DIO6 - PA1
+ // XBEE_DIO7 - PA0
+ // XBEE_SLEEPRQ - PA11
+
+ if (_dot->getWakePin() != XBEE_DIN || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_3;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+ if (_dot->getWakePin() != XBEE_DIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_5;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+ if (_dot->getWakePin() != XBEE_DIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_4;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+ if (_dot->getWakePin() != XBEE_DIO4 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_7;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+ if (_dot->getWakePin() != XBEE_DIO5 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_1;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+ }
+
+ if (_dot->getWakePin() != XBEE_DIO6 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_1;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+ if (_dot->getWakePin() != XBEE_DIO7 || _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_0;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+ if (_dot->getWakePin() != XBEE_SLEEPRQ|| _dot->getWakeMode() == mDot::RTC_ALARM) {
+ GPIO_InitStruct.Pin = GPIO_PIN_11;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+#endif
_dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
+
+#if defined(TARGET_XDOT_L151CC)
+ xdot_restore_gpio_state();
+#else
+ //Restore the GPIO state.
+ GPIOA->MODER = portA[0];
+ GPIOA->OTYPER = portA[1];
+ GPIOA->OSPEEDR = portA[2];
+ GPIOA->PUPDR = portA[3];
+ GPIOA->AFR[0] = portA[4];
+ GPIOA->AFR[1] = portA[5];
+
+ GPIOB->MODER = portB[0];
+ GPIOB->OTYPER = portB[1];
+ GPIOB->OSPEEDR = portB[2];
+ GPIOB->PUPDR = portB[3];
+ GPIOB->AFR[0] = portB[4];
+ GPIOB->AFR[1] = portB[5];
+
+ GPIOC->MODER = portC[0];
+ GPIOC->OTYPER = portC[1];
+ GPIOC->OSPEEDR = portC[2];
+ GPIOC->PUPDR = portC[3];
+ GPIOC->AFR[0] = portC[4];
+ GPIOC->AFR[1] = portC[5];
+
+ GPIOD->MODER = portD[0];
+ GPIOD->OTYPER = portD[1];
+ GPIOD->OSPEEDR = portD[2];
+ GPIOD->PUPDR = portD[3];
+ GPIOD->AFR[0] = portD[4];
+ GPIOD->AFR[1] = portD[5];
+
+ GPIOH->MODER = portH[0];
+ GPIOH->OTYPER = portH[1];
+ GPIOH->OSPEEDR = portH[2];
+ GPIOH->PUPDR = portH[3];
+ GPIOH->AFR[0] = portH[4];
+ GPIOH->AFR[1] = portH[5];
+#endif
+
+ _serial.rxClear();
+ _serial.txClear();
+}
+
+std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
+ if (format == mDot::HEXADECIMAL)
+ return mts::Text::bin2hexString(data);
+ else
+ return std::string(data.begin(), data.end());
}
bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
@@ -745,59 +1293,18 @@
}
void CommandTerminal::wakeup(void) {
- if (_dot->getWakePin() == XBEE_DIN) {
- _serial.reattach(XBEE_DOUT, XBEE_DIN);
- logInfo("Wakeup pin was serial input");
- }
}
-void CommandTerminal::RadioEvent::MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
+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) {
+ mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, retries);
- if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
- std::string msg = "OK";
- switch (info->Status) {
- case LORAMAC_EVENT_INFO_STATUS_ERROR:
- msg = "ERROR";
- break;
- case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
- msg = "TX_TIMEOUT";
- break;
- case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
- msg = "RX_TIMEOUT";
- break;
- case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
- msg = "RX_ERROR";
- break;
- case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
- msg = "JOIN_FAIL";
- break;
- case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
- msg = "DOWNLINK_FAIL";
- break;
- case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
- msg = "ADDRESS_FAIL";
- break;
- case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
- msg = "MIC_FAIL";
- break;
- default:
- break;
+ if (serial_data_mode) {
+ logDebug("Rx %d bytes", size);
+ if (size > 0) {
+ CommandTerminal::Serial()->write((char*) RxPayload, RxPayloadSize);
}
- logTrace("Event: %s", msg.c_str());
-
- logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
- flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
- logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
- info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
- info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
- }
-
- if (flags->Bits.Rx) {
- if (serial_data_mode) {
- logDebug("Rx %d bytes", info->RxBufferSize);
- if (info->RxBufferSize > 0) {
- _serial.write((char*) info->RxBuffer, info->RxBufferSize);
- }
+ if (!CommandTerminal::Serial()->readable() && _dot->getAckRequested() && _dot->getClass() == "C") {
+ _sendAck = true;
}
}
}