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;

pull/12/head
Bryan Biedenkapp 4 years ago
parent 06e3e78a72
commit 91b932c1ea

@ -146,6 +146,7 @@ system:
packetPlayoutTime: 10
disableOFlowReset: false
ignoreModemConfigArea: false
dumpModemStatus: false
trace: false
debug: false
cwId:

@ -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,6 +405,12 @@ void Slot::clock()
}
if (m_enableTSCC) {
m_ccPacketInterval.clock(ms);
if (!m_ccPacketInterval.isRunning()) {
m_ccPacketInterval.start();
}
if (m_ccPacketInterval.isRunning() && m_ccPacketInterval.hasExpired()) {
// increment the TSCC counter on every slot 1 clock
m_tsccCnt++;
if (m_tsccCnt == TSCC_MAX_CNT) {
@ -426,6 +433,9 @@ void Slot::clock()
}
m_ccSeq++;
m_ccPacketInterval.start();
}
}
m_rfTimeoutTimer.clock(ms);

@ -137,6 +137,8 @@ namespace dmr
Timer m_netTimeoutTimer;
Timer m_packetTimer;
Timer m_ccPacketInterval;
StopWatch m_interval;
StopWatch m_elapsed;

@ -1599,6 +1599,7 @@ bool Host::createModem()
uint8_t packetPlayoutTime = (uint8_t)modemConf["packetPlayoutTime"].as<uint32_t>(10U);
bool disableOFlowReset = modemConf["disableOFlowReset"].as<bool>(false);
bool ignoreModemConfigArea = modemConf["ignoreModemConfigArea"].as<bool>(false);
bool dumpModemStatus = modemConf["dumpModemStatus"].as<bool>(false);
bool trace = modemConf["trace"].as<bool>(false);
bool debug = modemConf["debug"].as<bool>(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);

@ -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);

@ -33,7 +33,9 @@ using namespace lookups;
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <string>
#include <vector>
#include <fstream>
// ---------------------------------------------------------------------------
// Public Class Members
@ -110,17 +112,39 @@ std::vector<IdenTable> IdenTableLookup::list()
// ---------------------------------------------------------------------------
/// <summary>
/// Parses a table entry from the passed comma delimited string.
/// Loads the table from the passed lookup table file.
/// </summary>
/// <param name="tableEntry">Comma delimited string to process into table entry.</param>
/// <returns>Table entry.</returns>
IdenTable IdenTableLookup::parse(std::string tableEntry)
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
bool IdenTableLookup::load()
{
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<std::string> parsed;
char delim = ',';
for (auto it = tableEntry.begin(); it != tableEntry.end(); it++) {
for (auto it = line.begin(); it != line.end(); it++) {
if (*it == delim) {
if (!next.empty()) {
parsed.push_back(next);
@ -133,6 +157,7 @@ IdenTable IdenTableLookup::parse(std::string tableEntry)
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()));
@ -151,5 +176,19 @@ IdenTable IdenTableLookup::parse(std::string tableEntry)
LogMessage(LOG_HOST, "Channel Id %u: BaseFrequency = %uHz, TXOffsetMhz = %fMHz, BandwidthKhz = %fKHz, SpaceKhz = %fKHz",
entry.channelId(), entry.baseFrequency(), entry.txOffsetMhz(), entry.chBandwidthKhz(), entry.chSpaceKhz());
return entry;
m_table[channelId] = entry;
}
}
}
m_mutex.unlock();
file.close();
size_t size = m_table.size();
if (size == 0U)
return false;
LogInfoEx(LOG_HOST, "Loaded %u entries into lookup table", size);
return true;
}

@ -117,9 +117,10 @@ namespace lookups
/// <summary>Returns the list of entries in this lookup table.</summary>
std::vector<IdenTable> list();
private:
/// <summary>Parses a table entry from the passed comma delimited string.</summary>
IdenTable parse(std::string tableEntry);
protected:
/// <summary>Loads the table from the passed lookup table file.</summary>
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
virtual bool load();
};
} // namespace lookups

@ -40,7 +40,6 @@
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <string>
#include <unordered_map>
namespace lookups
@ -74,6 +73,10 @@ namespace lookups
/// <summary></summary>
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;
/// <summary>Parses a table entry from the passed comma delimited string.</summary>
/// <param name="tableEntry">Comma delimited string to process into table entry.</param>
/// <returns>Table entry.</returns>
virtual T parse(std::string tableEntry) = 0;
/// <summary>Loads the table from the passed lookup table file.</summary>
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
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

@ -39,7 +39,9 @@ using namespace lookups;
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <string>
#include <vector>
#include <fstream>
// ---------------------------------------------------------------------------
// Public Class Members
@ -164,17 +166,39 @@ bool RadioIdLookup::getACL()
// ---------------------------------------------------------------------------
/// <summary>
/// Parses a table entry from the passed comma delimited string.
/// Loads the table from the passed lookup table file.
/// </summary>
/// <param name="tableEntry">Comma delimited string to process into table entry.</param>
/// <returns>Table entry.</returns>
RadioId RadioIdLookup::parse(std::string tableEntry)
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
bool RadioIdLookup::load()
{
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<std::string> parsed;
char delim = ',';
for (auto it = tableEntry.begin(); it != tableEntry.end(); it++) {
for (auto it = line.begin(); it != line.end(); it++) {
if (*it == delim) {
if (!next.empty()) {
parsed.push_back(next);
@ -187,8 +211,24 @@ RadioId RadioIdLookup::parse(std::string tableEntry)
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;
return RadioId(radioEnabled, radioDefault);
m_table[id] = RadioId(radioEnabled, radioDefault);
}
}
}
m_mutex.unlock();
file.close();
size_t size = m_table.size();
if (size == 0U)
return false;
LogInfoEx(LOG_HOST, "Loaded %u entries into lookup table", size);
return true;
}

@ -116,11 +116,12 @@ namespace lookups
/// <summary>Flag indicating whether radio ID access control is enabled or not.</summary>
bool getACL();
private:
protected:
bool m_acl;
/// <summary>Parses a table entry from the passed comma delimited string.</summary>
virtual RadioId parse(std::string tableEntry);
/// <summary>Loads the table from the passed lookup table file.</summary>
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
virtual bool load();
};
} // namespace lookups

@ -38,7 +38,9 @@ using namespace lookups;
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <string>
#include <vector>
#include <fstream>
// ---------------------------------------------------------------------------
// Public Class Members
@ -127,17 +129,39 @@ bool TalkgroupIdLookup::getACL()
// ---------------------------------------------------------------------------
/// <summary>
/// Parses a table entry from the passed comma delimited string.
/// Loads the table from the passed lookup table file.
/// </summary>
/// <param name="tableEntry">Comma delimited string to process into table entry.</param>
/// <returns>Table entry.</returns>
TalkgroupId TalkgroupIdLookup::parse(std::string tableEntry)
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
bool TalkgroupIdLookup::load()
{
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<std::string> parsed;
char delim = ',';
for (auto it = tableEntry.begin(); it != tableEntry.end(); it++) {
for (auto it = line.begin(); it != line.end(); it++) {
if (*it == delim) {
if (!next.empty()) {
parsed.push_back(next);
@ -150,9 +174,25 @@ TalkgroupId TalkgroupIdLookup::parse(std::string tableEntry)
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;
return TalkgroupId(tgEnabled, tgSlot, tgDefault);
m_table[id] = TalkgroupId(tgEnabled, tgSlot, tgDefault);
}
}
}
m_mutex.unlock();
file.close();
size_t size = m_table.size();
if (size == 0U)
return false;
LogInfoEx(LOG_HOST, "Loaded %u entries into lookup table", size);
return true;
}

@ -121,11 +121,12 @@ namespace lookups
/// <summary>Flag indicating whether talkgroup ID access control is enabled or not.</summary>
bool getACL();
private:
protected:
bool m_acl;
/// <summary>Parses a table entry from the passed comma delimited string.</summary>
virtual TalkgroupId parse(std::string tableEntry);
/// <summary>Loads the table from the passed lookup table file.</summary>
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
virtual bool load();
};
} // namespace lookups

@ -107,11 +107,12 @@ using namespace modem;
/// <param name="packetPlayoutTime">Length of time in MS between packets to send to modem.</param>
/// <param name="disableOFlowReset">Flag indicating whether the ADC/DAC overflow reset logic is disabled.</param>
/// <param name="ignoreModemConfigArea">Flag indicating whether the modem configuration area is ignored.</param>
/// <param name="dumpModemStatus">Flag indicating whether the modem status is dumped to the log.</param>
/// <param name="trace">Flag indicating whether air interface modem trace is enabled.</param>
/// <param name="debug">Flag indicating whether air interface modem debug is enabled.</param>
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
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to warm reset the connection to the modem.
/// </summary>
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);
}
/// <summary>
/// Retrieve the air interface modem version.
/// </summary>
@ -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");

@ -211,7 +211,7 @@ namespace modem
/// <summary>Initializes a new instance of the Modem class.</summary>
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);
/// <summary>Finalizes a instance of the Modem class.</summary>
~Modem();
@ -416,6 +416,11 @@ namespace modem
bool m_ignoreModemConfigArea;
bool m_flashDisabled;
bool m_dumpModemStatus;
/// <summary>Internal helper to warm reset the connection to the modem.</summary>
void reset();
/// <summary>Retrieve the air interface modem version.</summary>
bool getFirmwareVersion();
/// <summary>Retrieve the current status from the air interface modem.</summary>

Loading…
Cancel
Save

Powered by TurnKey Linux.