From 91b932c1eaffdda3e60dd642a579bf887c045e08 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Thu, 12 May 2022 13:50:33 -0400 Subject: [PATCH] revert modem buffer sizes to pre-reorganization size; implement support to dump the modem status "dumpModemStatus"; refactor LookupTable to use C++ instead of bad C file loading (possible fix for a bad heap corruption problem); implement CC data interval timer for DMR CC; --- config.example.yml | 1 + dmr/Slot.cpp | 40 ++++++++----- dmr/Slot.h | 2 + host/Host.cpp | 19 +++--- host/calibrate/HostCal.cpp | 2 +- lookups/IdenTableLookup.cpp | 105 +++++++++++++++++++++++----------- lookups/IdenTableLookup.h | 7 ++- lookups/LookupTable.h | 54 ++--------------- lookups/RadioIdLookup.cpp | 80 +++++++++++++++++++------- lookups/RadioIdLookup.h | 7 ++- lookups/TalkgroupIdLookup.cpp | 82 +++++++++++++++++++------- lookups/TalkgroupIdLookup.h | 7 ++- modem/Modem.cpp | 76 ++++++++++++++---------- modem/Modem.h | 7 ++- 14 files changed, 304 insertions(+), 185 deletions(-) diff --git a/config.example.yml b/config.example.yml index 85bcaef5..4bf1337f 100644 --- a/config.example.yml +++ b/config.example.yml @@ -146,6 +146,7 @@ system: packetPlayoutTime: 10 disableOFlowReset: false ignoreModemConfigArea: false + dumpModemStatus: false trace: false debug: false cwId: diff --git a/dmr/Slot.cpp b/dmr/Slot.cpp index 608e5211..2687f2c8 100644 --- a/dmr/Slot.cpp +++ b/dmr/Slot.cpp @@ -127,6 +127,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz m_rfTGHang(1000U, tgHang), m_netTimeoutTimer(1000U, timeout), m_packetTimer(1000U, 0U, 50U), + m_ccPacketInterval(1000U, 0U, 5U), m_interval(), m_elapsed(), m_rfFrames(0U), @@ -404,28 +405,37 @@ void Slot::clock() } if (m_enableTSCC) { - // increment the TSCC counter on every slot 1 clock - m_tsccCnt++; - if (m_tsccCnt == TSCC_MAX_CNT) { - m_tsccCnt = 0U; + m_ccPacketInterval.clock(ms); + if (!m_ccPacketInterval.isRunning()) { + m_ccPacketInterval.start(); } - if (m_ccSeq == 3U) { - m_ccSeq = 0U; - } + if (m_ccPacketInterval.isRunning() && m_ccPacketInterval.hasExpired()) { + // increment the TSCC counter on every slot 1 clock + m_tsccCnt++; + if (m_tsccCnt == TSCC_MAX_CNT) { + m_tsccCnt = 0U; + } - if (m_dedicatedTSCC) { - setShortLC_TSCC(m_siteData, m_tsccCnt); - writeRF_ControlData(m_tsccCnt, m_ccSeq); - } - else { - if (m_ccRunning) { + if (m_ccSeq == 3U) { + m_ccSeq = 0U; + } + + if (m_dedicatedTSCC) { setShortLC_TSCC(m_siteData, m_tsccCnt); writeRF_ControlData(m_tsccCnt, m_ccSeq); } - } + else { + if (m_ccRunning) { + setShortLC_TSCC(m_siteData, m_tsccCnt); + writeRF_ControlData(m_tsccCnt, m_ccSeq); + } + } + + m_ccSeq++; - m_ccSeq++; + m_ccPacketInterval.start(); + } } m_rfTimeoutTimer.clock(ms); diff --git a/dmr/Slot.h b/dmr/Slot.h index c5009ff4..65bc8a84 100644 --- a/dmr/Slot.h +++ b/dmr/Slot.h @@ -137,6 +137,8 @@ namespace dmr Timer m_netTimeoutTimer; Timer m_packetTimer; + Timer m_ccPacketInterval; + StopWatch m_interval; StopWatch m_elapsed; diff --git a/host/Host.cpp b/host/Host.cpp index f62cf593..ea900f82 100644 --- a/host/Host.cpp +++ b/host/Host.cpp @@ -669,12 +669,12 @@ int Host::run() } // Macro to start DMR duplex idle transmission (or beacon) - #define START_DMR_DUPLEX_IDLE(x) \ - if (dmr != NULL) { \ - if (m_duplex) { \ - m_modem->writeDMRStart(x); \ - m_dmrTXTimer.start(); \ - } \ + #define START_DMR_DUPLEX_IDLE(x) \ + if (dmr != NULL) { \ + if (m_duplex) { \ + m_modem->writeDMRStart(x); \ + m_dmrTXTimer.start(); \ + } \ } // main execution loop @@ -1599,6 +1599,7 @@ bool Host::createModem() uint8_t packetPlayoutTime = (uint8_t)modemConf["packetPlayoutTime"].as(10U); bool disableOFlowReset = modemConf["disableOFlowReset"].as(false); bool ignoreModemConfigArea = modemConf["ignoreModemConfigArea"].as(false); + bool dumpModemStatus = modemConf["dumpModemStatus"].as(false); bool trace = modemConf["trace"].as(false); bool debug = modemConf["debug"].as(false); @@ -1730,12 +1731,16 @@ bool Host::createModem() LogInfo(" Ignore Modem Configuration Area: yes"); } + if (dumpModemStatus) { + LogInfo(" Dump Modem Status: yes"); + } + if (debug) { LogInfo(" Debug: yes"); } m_modem = new Modem(modemPort, m_duplex, rxInvert, txInvert, pttInvert, dcBlocker, cosLockout, fdmaPreamble, dmrRxDelay, p25CorrCount, - packetPlayoutTime, disableOFlowReset, ignoreModemConfigArea, trace, debug); + packetPlayoutTime, disableOFlowReset, ignoreModemConfigArea, dumpModemStatus, trace, debug); m_modem->setModeParams(m_dmrEnabled, m_p25Enabled); m_modem->setLevels(rxLevel, cwIdTXLevel, dmrTXLevel, p25TXLevel); m_modem->setSymbolAdjust(dmrSymLevel3Adj, dmrSymLevel1Adj, p25SymLevel3Adj, p25SymLevel1Adj); diff --git a/host/calibrate/HostCal.cpp b/host/calibrate/HostCal.cpp index edef798a..52883eed 100644 --- a/host/calibrate/HostCal.cpp +++ b/host/calibrate/HostCal.cpp @@ -404,7 +404,7 @@ int HostCal::run() return 2; } - m_modem = new Modem(modemPort, false, m_rxInvert, m_txInvert, m_pttInvert, m_dcBlocker, false, m_fdmaPreamble, m_dmrRxDelay, m_p25CorrCount, 10U, false, ignoreModemConfigArea, false, false); + m_modem = new Modem(modemPort, false, m_rxInvert, m_txInvert, m_pttInvert, m_dcBlocker, false, m_fdmaPreamble, m_dmrRxDelay, m_p25CorrCount, 10U, false, ignoreModemConfigArea, false, false, false); m_modem->setLevels(m_rxLevel, m_txLevel, m_txLevel, m_txLevel); m_modem->setSymbolAdjust(m_dmrSymLevel3Adj, m_dmrSymLevel1Adj, m_p25SymLevel3Adj, m_p25SymLevel1Adj); m_modem->setDCOffsetParams(m_txDCOffset, m_rxDCOffset); diff --git a/lookups/IdenTableLookup.cpp b/lookups/IdenTableLookup.cpp index 37731218..06f070e8 100644 --- a/lookups/IdenTableLookup.cpp +++ b/lookups/IdenTableLookup.cpp @@ -33,7 +33,9 @@ using namespace lookups; #include #include #include +#include #include +#include // --------------------------------------------------------------------------- // Public Class Members @@ -110,46 +112,83 @@ std::vector IdenTableLookup::list() // --------------------------------------------------------------------------- /// -/// Parses a table entry from the passed comma delimited string. +/// Loads the table from the passed lookup table file. /// -/// Comma delimited string to process into table entry. -/// Table entry. -IdenTable IdenTableLookup::parse(std::string tableEntry) +/// True, if lookup table was loaded, otherwise false. +bool IdenTableLookup::load() { - std::string next; - std::vector parsed; - char delim = ','; - - for (auto it = tableEntry.begin(); it != tableEntry.end(); it++) { - if (*it == delim) { - if (!next.empty()) { - parsed.push_back(next); - next.clear(); + if (m_filename.length() <= 0) { + return false; + } + + std::ifstream file (m_filename, std::ifstream::in); + if (file.fail()) { + LogError(LOG_HOST, "Cannot open the lookup file - %s", m_filename.c_str()); + return false; + } + + // clear table + clear(); + + m_mutex.lock(); + { + // read lines from file + std::string line; + while (std::getline(file, line)) { + if (line.length() > 0) { + if (line.at(0) == '#') + continue; + + // tokenize line + std::string next; + std::vector parsed; + char delim = ','; + + for (auto it = line.begin(); it != line.end(); it++) { + if (*it == delim) { + if (!next.empty()) { + parsed.push_back(next); + next.clear(); + } + } + else + next += *it; + } + if (!next.empty()) + parsed.push_back(next); + + // parse tokenized line + uint8_t channelId = (uint8_t)::atoi(parsed[0].c_str()); + uint32_t baseFrequency = (uint32_t)::atoi(parsed[1].c_str()); + float chSpaceKhz = float(::atof(parsed[2].c_str())); + float txOffsetMhz = float(::atof(parsed[3].c_str())); + float chBandwidthKhz = float(::atof(parsed[4].c_str())); + + if (chSpaceKhz == 0.0F) + chSpaceKhz = chBandwidthKhz / 2; + if (chSpaceKhz < 2.5F) // clamp to 2.5 + chSpaceKhz = 2.5F; + if (chSpaceKhz > 6.25F) // clamp to 6.25 + chSpaceKhz = 6.25F; + + IdenTable entry = IdenTable(channelId, baseFrequency, chSpaceKhz, txOffsetMhz, chBandwidthKhz); + + LogMessage(LOG_HOST, "Channel Id %u: BaseFrequency = %uHz, TXOffsetMhz = %fMHz, BandwidthKhz = %fKHz, SpaceKhz = %fKHz", + entry.channelId(), entry.baseFrequency(), entry.txOffsetMhz(), entry.chBandwidthKhz(), entry.chSpaceKhz()); + + m_table[channelId] = entry; } } - else - next += *it; } - if (!next.empty()) - parsed.push_back(next); - - uint8_t channelId = (uint8_t)::atoi(parsed[0].c_str()); - uint32_t baseFrequency = (uint32_t)::atoi(parsed[1].c_str()); - float chSpaceKhz = float(::atof(parsed[2].c_str())); - float txOffsetMhz = float(::atof(parsed[3].c_str())); - float chBandwidthKhz = float(::atof(parsed[4].c_str())); + m_mutex.unlock(); - if (chSpaceKhz == 0.0F) - chSpaceKhz = chBandwidthKhz / 2; - if (chSpaceKhz < 2.5F) // clamp to 2.5 - chSpaceKhz = 2.5F; - if (chSpaceKhz > 6.25F) // clamp to 6.25 - chSpaceKhz = 6.25F; + file.close(); - IdenTable entry = IdenTable(channelId, baseFrequency, chSpaceKhz, txOffsetMhz, chBandwidthKhz); + size_t size = m_table.size(); + if (size == 0U) + return false; - LogMessage(LOG_HOST, "Channel Id %u: BaseFrequency = %uHz, TXOffsetMhz = %fMHz, BandwidthKhz = %fKHz, SpaceKhz = %fKHz", - entry.channelId(), entry.baseFrequency(), entry.txOffsetMhz(), entry.chBandwidthKhz(), entry.chSpaceKhz()); + LogInfoEx(LOG_HOST, "Loaded %u entries into lookup table", size); - return entry; + return true; } diff --git a/lookups/IdenTableLookup.h b/lookups/IdenTableLookup.h index 12d0f67b..f334afc3 100644 --- a/lookups/IdenTableLookup.h +++ b/lookups/IdenTableLookup.h @@ -117,9 +117,10 @@ namespace lookups /// Returns the list of entries in this lookup table. std::vector list(); - private: - /// Parses a table entry from the passed comma delimited string. - IdenTable parse(std::string tableEntry); + protected: + /// Loads the table from the passed lookup table file. + /// True, if lookup table was loaded, otherwise false. + virtual bool load(); }; } // namespace lookups diff --git a/lookups/LookupTable.h b/lookups/LookupTable.h index e28c850d..d0fdb67f 100644 --- a/lookups/LookupTable.h +++ b/lookups/LookupTable.h @@ -40,7 +40,6 @@ #include #include #include -#include #include namespace lookups @@ -74,6 +73,10 @@ namespace lookups /// virtual void entry() { + if (m_reloadTime == 0U) { + return; + } + Timer timer(1U, 60U * m_reloadTime); timer.start(); @@ -157,56 +160,9 @@ namespace lookups bool m_acl; - /// Parses a table entry from the passed comma delimited string. - /// Comma delimited string to process into table entry. - /// Table entry. - virtual T parse(std::string tableEntry) = 0; - /// Loads the table from the passed lookup table file. /// True, if lookup table was loaded, otherwise false. - virtual bool load() - { - if (strlen(m_filename.c_str()) <= 0) { - return false; - } - - FILE* fp = ::fopen(m_filename.c_str(), "rt"); - if (fp == NULL) { - LogError(LOG_HOST, "Cannot open the lookup file - %s", m_filename.c_str()); - return false; - } - - // clear table - clear(); - - m_mutex.lock(); - { - char buffer[100U]; - while (::fgets(buffer, 100U, fp) != NULL) { - if (buffer[0U] == '#') - continue; - - std::string strbuf = buffer; - char* p1 = ::strtok(buffer, ",\r\n"); - - if (p1 != NULL) { - uint32_t id = (uint32_t)::atoi(p1); - m_table[id] = parse(strbuf); - } - } - } - m_mutex.unlock(); - - ::fclose(fp); - - size_t size = m_table.size(); - if (size == 0U) - return false; - - LogInfoEx(LOG_HOST, "Loaded %u entries into lookup table", size); - - return true; - } + virtual bool load() = 0; }; } // namespace lookups diff --git a/lookups/RadioIdLookup.cpp b/lookups/RadioIdLookup.cpp index 6f634814..8afeebbe 100644 --- a/lookups/RadioIdLookup.cpp +++ b/lookups/RadioIdLookup.cpp @@ -39,7 +39,9 @@ using namespace lookups; #include #include #include +#include #include +#include // --------------------------------------------------------------------------- // Public Class Members @@ -164,31 +166,69 @@ bool RadioIdLookup::getACL() // --------------------------------------------------------------------------- /// -/// Parses a table entry from the passed comma delimited string. +/// Loads the table from the passed lookup table file. /// -/// Comma delimited string to process into table entry. -/// Table entry. -RadioId RadioIdLookup::parse(std::string tableEntry) +/// True, if lookup table was loaded, otherwise false. +bool RadioIdLookup::load() { - std::string next; - std::vector parsed; - char delim = ','; - - for (auto it = tableEntry.begin(); it != tableEntry.end(); it++) { - if (*it == delim) { - if (!next.empty()) { - parsed.push_back(next); - next.clear(); + if (m_filename.length() <= 0) { + return false; + } + + std::ifstream file (m_filename, std::ifstream::in); + if (file.fail()) { + LogError(LOG_HOST, "Cannot open the lookup file - %s", m_filename.c_str()); + return false; + } + + // clear table + clear(); + + m_mutex.lock(); + { + // read lines from file + std::string line; + while (std::getline(file, line)) { + if (line.length() > 0) { + if (line.at(0) == '#') + continue; + + // tokenize line + std::string next; + std::vector parsed; + char delim = ','; + + for (auto it = line.begin(); it != line.end(); it++) { + if (*it == delim) { + if (!next.empty()) { + parsed.push_back(next); + next.clear(); + } + } + else + next += *it; + } + if (!next.empty()) + parsed.push_back(next); + + // parse tokenized line + uint32_t id = ::atoi(parsed[0].c_str()); + bool radioEnabled = ::atoi(parsed[1].c_str()) == 1; + bool radioDefault = false; + + m_table[id] = RadioId(radioEnabled, radioDefault); } } - else - next += *it; } - if (!next.empty()) - parsed.push_back(next); + m_mutex.unlock(); + + file.close(); + + size_t size = m_table.size(); + if (size == 0U) + return false; - bool radioEnabled = ::atoi(parsed[1].c_str()) == 1; - bool radioDefault = false; + LogInfoEx(LOG_HOST, "Loaded %u entries into lookup table", size); - return RadioId(radioEnabled, radioDefault); + return true; } diff --git a/lookups/RadioIdLookup.h b/lookups/RadioIdLookup.h index a2250346..30b7cc37 100644 --- a/lookups/RadioIdLookup.h +++ b/lookups/RadioIdLookup.h @@ -116,11 +116,12 @@ namespace lookups /// Flag indicating whether radio ID access control is enabled or not. bool getACL(); - private: + protected: bool m_acl; - /// Parses a table entry from the passed comma delimited string. - virtual RadioId parse(std::string tableEntry); + /// Loads the table from the passed lookup table file. + /// True, if lookup table was loaded, otherwise false. + virtual bool load(); }; } // namespace lookups diff --git a/lookups/TalkgroupIdLookup.cpp b/lookups/TalkgroupIdLookup.cpp index 57263df8..edc70b4b 100644 --- a/lookups/TalkgroupIdLookup.cpp +++ b/lookups/TalkgroupIdLookup.cpp @@ -38,7 +38,9 @@ using namespace lookups; #include #include #include +#include #include +#include // --------------------------------------------------------------------------- // Public Class Members @@ -127,32 +129,70 @@ bool TalkgroupIdLookup::getACL() // --------------------------------------------------------------------------- /// -/// Parses a table entry from the passed comma delimited string. +/// Loads the table from the passed lookup table file. /// -/// Comma delimited string to process into table entry. -/// Table entry. -TalkgroupId TalkgroupIdLookup::parse(std::string tableEntry) +/// True, if lookup table was loaded, otherwise false. +bool TalkgroupIdLookup::load() { - std::string next; - std::vector parsed; - char delim = ','; - - for (auto it = tableEntry.begin(); it != tableEntry.end(); it++) { - if (*it == delim) { - if (!next.empty()) { - parsed.push_back(next); - next.clear(); + if (m_filename.length() <= 0) { + return false; + } + + std::ifstream file (m_filename, std::ifstream::in); + if (file.fail()) { + LogError(LOG_HOST, "Cannot open the lookup file - %s", m_filename.c_str()); + return false; + } + + // clear table + clear(); + + m_mutex.lock(); + { + // read lines from file + std::string line; + while (std::getline(file, line)) { + if (line.length() > 0) { + if (line.at(0) == '#') + continue; + + // tokenize line + std::string next; + std::vector parsed; + char delim = ','; + + for (auto it = line.begin(); it != line.end(); it++) { + if (*it == delim) { + if (!next.empty()) { + parsed.push_back(next); + next.clear(); + } + } + else + next += *it; + } + if (!next.empty()) + parsed.push_back(next); + + // parse tokenized line + uint32_t id = ::atoi(parsed[0].c_str()); + bool tgEnabled = ::atoi(parsed[1].c_str()) == 1; + uint8_t tgSlot = (uint8_t)::atoi(parsed[2].c_str()); + bool tgDefault = false; + + m_table[id] = TalkgroupId(tgEnabled, tgSlot, tgDefault); } } - else - next += *it; } - if (!next.empty()) - parsed.push_back(next); + m_mutex.unlock(); + + file.close(); + + size_t size = m_table.size(); + if (size == 0U) + return false; - bool tgEnabled = ::atoi(parsed[1].c_str()) == 1; - uint8_t tgSlot = (uint8_t)::atoi(parsed[2].c_str()); - bool tgDefault = false; + LogInfoEx(LOG_HOST, "Loaded %u entries into lookup table", size); - return TalkgroupId(tgEnabled, tgSlot, tgDefault); + return true; } diff --git a/lookups/TalkgroupIdLookup.h b/lookups/TalkgroupIdLookup.h index 9126e07b..fb8f229f 100644 --- a/lookups/TalkgroupIdLookup.h +++ b/lookups/TalkgroupIdLookup.h @@ -121,11 +121,12 @@ namespace lookups /// Flag indicating whether talkgroup ID access control is enabled or not. bool getACL(); - private: + protected: bool m_acl; - /// Parses a table entry from the passed comma delimited string. - virtual TalkgroupId parse(std::string tableEntry); + /// Loads the table from the passed lookup table file. + /// True, if lookup table was loaded, otherwise false. + virtual bool load(); }; } // namespace lookups diff --git a/modem/Modem.cpp b/modem/Modem.cpp index 40b3f75d..58a6c3d9 100644 --- a/modem/Modem.cpp +++ b/modem/Modem.cpp @@ -107,11 +107,12 @@ using namespace modem; /// Length of time in MS between packets to send to modem. /// Flag indicating whether the ADC/DAC overflow reset logic is disabled. /// Flag indicating whether the modem configuration area is ignored. +/// Flag indicating whether the modem status is dumped to the log. /// Flag indicating whether air interface modem trace is enabled. /// Flag indicating whether air interface modem debug is enabled. Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, bool dcBlocker, bool cosLockout, uint8_t fdmaPreamble, uint8_t dmrRxDelay, uint8_t p25CorrCount, uint8_t packetPlayoutTime, bool disableOFlowReset, - bool ignoreModemConfigArea, bool trace, bool debug) : + bool ignoreModemConfigArea, bool dumpModemStatus, bool trace, bool debug) : m_port(port), m_dmrColorCode(0U), m_p25NAC(0x293U), @@ -160,12 +161,12 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, m_openPortHandler(NULL), m_closePortHandler(NULL), m_rspHandler(NULL), - m_rxDMRData1(1089U, "Modem RX DMR1"), // 1089 bytes = 33 DMR Frames - m_rxDMRData2(1089U, "Modem RX DMR2"), - m_txDMRData1(792U, "Modem TX DMR1"), // 792 bytes = 24 DMR Frames - m_txDMRData2(792U, "Modem TX DMR2"), - m_rxP25Data(6048U, "Modem RX P25"), // 6048 bytes = 28 P25 Frames - m_txP25Data(864U, "Modem TX P25"), // 864 = 4 P25 Frames + m_rxDMRData1(1000U, "Modem RX DMR1"), + m_rxDMRData2(1000U, "Modem RX DMR2"), + m_txDMRData1(1000U, "Modem TX DMR1"), + m_txDMRData2(1000U, "Modem TX DMR2"), + m_rxP25Data(1000U, "Modem RX P25"), + m_txP25Data(1000U, "Modem TX P25"), m_useDFSI(false), m_statusTimer(1000U, 0U, 250U), m_inactivityTimer(1000U, 4U), @@ -178,6 +179,7 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, m_error(false), m_ignoreModemConfigArea(ignoreModemConfigArea), m_flashDisabled(false), + m_dumpModemStatus(dumpModemStatus), m_trace(trace), m_debug(debug), m_playoutTimer(1000U, 0U, packetPlayoutTime) @@ -499,18 +501,7 @@ void Modem::clock(uint32_t ms) m_inactivityTimer.clock(ms); if (m_inactivityTimer.hasExpired()) { LogError(LOG_MODEM, "No reply from the modem for some time, resetting it"); - - m_error = true; - m_adcOverFlowCount = 0U; - m_dacOverFlowCount = 0U; - - close(); - - Thread::sleep(2000U); // 2s - while (!open()) { - Thread::sleep(5000U); // 5s - close(); - } + reset(); } bool forceModemReset = false; @@ -734,6 +725,17 @@ void Modem::clock(uint32_t ms) m_dmrSpace2 = m_buffer[8U]; m_p25Space = m_buffer[10U]; + if (m_dumpModemStatus) { + LogDebug(LOG_MODEM, "Modem::clock(), CMD_GET_STATUS, isHotspot = %u, modemState = %u, tx = %u, adcOverflow = %u, rxOverflow = %u, txOverflow = %u, dacOverflow = %u, dmrSpace1 = %u, dmrSpace2 = %u, p25Space = %u", + m_isHotspot, m_modemState, m_tx, adcOverflow, rxOverflow, txOverflow, dacOverflow, m_dmrSpace1, m_dmrSpace2, m_p25Space); + LogDebug(LOG_MODEM, "Modem::clock(), CMD_GET_STATUS, rxDMRData1 size = %u, len = %u, free = %u; rxDMRData2 size = %u, len = %u, free = %u, rxP25Data size = %u, len = %u, free = %u", + m_rxDMRData1.length(), m_rxDMRData1.dataSize(), m_rxDMRData1.freeSpace(), m_rxDMRData2.length(), m_rxDMRData2.dataSize(), m_rxDMRData2.freeSpace(), + m_rxP25Data.length(), m_rxP25Data.dataSize(), m_rxP25Data.freeSpace()); + LogDebug(LOG_MODEM, "Modem::clock(), CMD_GET_STATUS, txDMRData1 size = %u, len = %u, free = %u; txDMRData2 size = %u, len = %u, free = %u, txP25Data size = %u, len = %u, free = %u", + m_txDMRData1.length(), m_txDMRData1.dataSize(), m_txDMRData1.freeSpace(), m_txDMRData2.length(), m_txDMRData2.dataSize(), m_txDMRData2.freeSpace(), + m_txP25Data.length(), m_txP25Data.dataSize(), m_txP25Data.freeSpace()); + } + m_inactivityTimer.start(); } break; @@ -764,16 +766,8 @@ void Modem::clock(uint32_t ms) // force a modem reset because of a error condition if (forceModemReset) { - m_error = true; forceModemReset = false; - m_adcOverFlowCount = 0U; - m_dacOverFlowCount = 0U; - - close(); - - Thread::sleep(2000U); // 2s - while (!open()) - Thread::sleep(5000U); // 5s + reset(); } // Only feed data to the modem if the playout timer has expired @@ -1404,6 +1398,27 @@ bool Modem::sendCWId(const std::string& callsign) // Private Class Members // --------------------------------------------------------------------------- +/// +/// Internal helper to warm reset the connection to the modem. +/// +void Modem::reset() +{ + m_error = true; + m_adcOverFlowCount = 0U; + m_dacOverFlowCount = 0U; + + close(); + + Thread::sleep(2000U); // 2s + while (!open()) { + Thread::sleep(5000U); // 5s + close(); + } + + // reset modem to last state + setState(m_modemState); +} + /// /// Retrieve the air interface modem version. /// @@ -1923,7 +1938,10 @@ RESP_TYPE_DVM Modem::getResponse() if (m_buffer[0U] != DVM_FRAME_START) { LogDebug(LOG_MODEM, "getResponse(), first byte not a frame start; byte = %02X", m_buffer[0U]); - return RTM_TIMEOUT; + if (m_dumpModemStatus) { + Utils::dump(1U, "Modem Invalid Frame", m_buffer, 250U); + } + return RTM_ERROR; } //LogDebug(LOG_MODEM, "getResponse(), RESP_START"); diff --git a/modem/Modem.h b/modem/Modem.h index a6b5f44b..942b790d 100644 --- a/modem/Modem.h +++ b/modem/Modem.h @@ -211,7 +211,7 @@ namespace modem /// Initializes a new instance of the Modem class. Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, bool dcBlocker, bool cosLockout, uint8_t fdmaPreamble, uint8_t dmrRxDelay, uint8_t p25CorrCount, uint8_t packetPlayoutTime, bool disableOFlowReset, - bool ignoreModemConfigArea, bool trace, bool debug); + bool ignoreModemConfigArea, bool dumpModemStatus, bool trace, bool debug); /// Finalizes a instance of the Modem class. ~Modem(); @@ -416,6 +416,11 @@ namespace modem bool m_ignoreModemConfigArea; bool m_flashDisabled; + bool m_dumpModemStatus; + + /// Internal helper to warm reset the connection to the modem. + void reset(); + /// Retrieve the air interface modem version. bool getFirmwareVersion(); /// Retrieve the current status from the air interface modem.