Merge branch 'master' into mqtt

This commit is contained in:
Jonathan Naylor 2025-03-14 13:39:49 +00:00
commit 62c33086ca
102 changed files with 1621 additions and 1489 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2021,2023 Jonathan Naylor, G4KLX
* Copyright (C) 2015-2021,2023,2025 Jonathan Naylor, G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -42,23 +42,24 @@ bool CDMRSlot::m_dumpTAData = true;
CModem* CDMRSlot::m_modem = NULL;
CDMRNetwork* CDMRSlot::m_network = NULL;
bool CDMRSlot::m_duplex = true;
CDMRLookup* CDMRSlot::m_lookup = NULL;
CDMRLookup* CDMRSlot::m_lookup = nullptr;
unsigned int CDMRSlot::m_hangCount = 3U * 17U;
DMR_OVCM_TYPES CDMRSlot::m_ovcm = DMR_OVCM_OFF;
DMR_OVCM CDMRSlot::m_ovcm = DMR_OVCM::OFF;
bool CDMRSlot::m_protect = false;
CRSSIInterpolator* CDMRSlot::m_rssiMapper = NULL;
CRSSIInterpolator* CDMRSlot::m_rssiMapper = nullptr;
unsigned int CDMRSlot::m_jitterTime = 360U;
unsigned int CDMRSlot::m_jitterSlots = 6U;
unsigned char* CDMRSlot::m_idle = NULL;
unsigned char* CDMRSlot::m_idle = nullptr;
FLCO CDMRSlot::m_flco1;
unsigned char CDMRSlot::m_id1 = 0U;
ACTIVITY_TYPE CDMRSlot::m_activity1 = ACTIVITY_NONE;
ACTIVITY_TYPE CDMRSlot::m_activity1 = ACTIVITY_TYPE::NONE;
FLCO CDMRSlot::m_flco2;
unsigned char CDMRSlot::m_id2 = 0U;
ACTIVITY_TYPE CDMRSlot::m_activity2 = ACTIVITY_NONE;
ACTIVITY_TYPE CDMRSlot::m_activity2 = ACTIVITY_TYPE::NONE;
const unsigned char TALKER_ID_NONE = 0x00U;
const unsigned char TALKER_ID_HEADER = 0x01U;
@ -76,22 +77,22 @@ const unsigned int BER_COUNT = 18U * 141U; // 18 * 60ms = 1080ms
CDMRSlot::CDMRSlot(unsigned int slotNo, unsigned int timeout) :
m_slotNo(slotNo),
m_queue(5000U, "DMR Slot"),
m_rfState(RS_RF_LISTENING),
m_netState(RS_NET_IDLE),
m_rfState(RPT_RF_STATE::LISTENING),
m_netState(RPT_NET_STATE::IDLE),
m_rfEmbeddedLC(),
m_rfEmbeddedData(NULL),
m_rfEmbeddedData(nullptr),
m_rfEmbeddedReadN(0U),
m_rfEmbeddedWriteN(1U),
m_rfTalkerId(TALKER_ID_NONE),
m_rfTalkerAlias(slotNo),
m_netEmbeddedLC(),
m_netEmbeddedData(NULL),
m_netEmbeddedData(nullptr),
m_netEmbeddedReadN(0U),
m_netEmbeddedWriteN(1U),
m_netTalkerId(TALKER_ID_NONE),
m_netTalkerAlias(slotNo),
m_rfLC(NULL),
m_netLC(NULL),
m_rfLC(nullptr),
m_netLC(nullptr),
m_rfSeqNo(0U),
m_rfN(0U),
m_lastrfN(0U),
@ -112,7 +113,7 @@ m_rfErrs(0U),
m_netErrs(0U),
m_rfTimeout(false),
m_netTimeout(false),
m_lastFrame(NULL),
m_lastFrame(nullptr),
m_lastFrameValid(false),
m_rssi(0),
m_maxRSSI(0),
@ -142,7 +143,7 @@ CDMRSlot::~CDMRSlot()
bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
{
assert(data != NULL);
assert(data != nullptr);
if (!m_enabled)
return false;
@ -185,7 +186,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
if (data[0U] == TAG_LOST) {
m_rfState = RS_RF_LISTENING;
m_rfState = RPT_RF_STATE::LISTENING;
return false;
}
@ -224,12 +225,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
slotType.setDataType(dataType);
if (dataType == DT_VOICE_LC_HEADER) {
if (m_rfState == RS_RF_AUDIO)
if (m_rfState == RPT_RF_STATE::AUDIO)
return true;
CDMRFullLC fullLC;
CDMRLC* lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
if (lc == NULL)
if (lc == nullptr)
return false;
unsigned int srcId = lc->getSrcId();
@ -238,25 +239,34 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
std::string dst = m_lookup->find(dstId);
FLCO flco = lc->getFLCO();
if (!m_protect) {
if (lc->getPF()) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
delete lc;
m_rfState = RPT_RF_STATE::LISTENING;
return false;
}
}
if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId);
delete lc;
m_rfState = RS_RF_LISTENING;
m_rfState = RPT_RF_STATE::LISTENING;
return false;
}
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO::GROUP, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId);
delete lc;
m_rfState = RS_RF_LISTENING;
m_rfState = RPT_RF_STATE::LISTENING;
return false;
}
if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
if ((m_ovcm == DMR_OVCM::TX_ON) || (m_ovcm == DMR_OVCM::ON))
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
lc->setOVCM(false);
m_rfLC = lc;
@ -311,7 +321,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
writeNetworkRF(data, DT_VOICE_LC_HEADER);
m_rfState = RS_RF_AUDIO;
m_rfState = RPT_RF_STATE::AUDIO;
if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
@ -324,7 +334,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
return true;
} else if (dataType == DT_VOICE_PI_HEADER) {
if (m_rfState != RS_RF_AUDIO)
if (m_rfState != RPT_RF_STATE::AUDIO)
return false;
// Regenerate the Slot Type
@ -342,14 +352,16 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
data[0U] = TAG_DATA;
data[1U] = 0x00U;
if (m_duplex)
writeQueueRF(data);
if (m_protect) {
if (m_duplex)
writeQueueRF(data);
writeNetworkRF(data, DT_VOICE_PI_HEADER);
writeNetworkRF(data, DT_VOICE_PI_HEADER);
}
return true;
} else if (dataType == DT_TERMINATOR_WITH_LC) {
if (m_rfState != RS_RF_AUDIO)
if (m_rfState != RPT_RF_STATE::AUDIO)
return false;
// Regenerate the LC data
@ -396,7 +408,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
return true;
}
} else if (dataType == DT_DATA_HEADER) {
if (m_rfState == RS_RF_DATA)
if (m_rfState == RPT_RF_STATE::DATA)
return true;
CDMRDataHeader dataHeader;
@ -426,7 +438,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfFrames = dataHeader.getBlocks();
m_rfLC = new CDMRLC(gi ? FLCO_GROUP : FLCO_USER_USER, srcId, dstId);
m_rfLC = new CDMRLC(gi ? FLCO::GROUP : FLCO::USER_USER, srcId, dstId);
// Regenerate the data header
dataHeader.get(data + 2U);
@ -445,7 +457,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
writeNetworkRF(data, DT_DATA_HEADER);
m_rfState = RS_RF_DATA;
m_rfState = RPT_RF_STATE::DATA;
if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA);
@ -469,13 +481,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
return false;
CSBKO csbko = csbk.getCSBKO();
if (csbko == CSBKO_BSDWNACT)
if (csbko == CSBKO::BSDWNACT)
return false;
// set the OVCM bit for the supported csbk
if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
if ((m_ovcm == DMR_OVCM::TX_ON) || (m_ovcm == DMR_OVCM::ON))
csbk.setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
csbk.setOVCM(false);
bool gi = csbk.getGI();
@ -515,38 +527,38 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (m_duplex)
writeQueueRF(data);
writeNetworkRF(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_USER_USER, srcId, dstId);
writeNetworkRF(data, DT_CSBK, gi ? FLCO::GROUP : FLCO::USER_USER, srcId, dstId);
switch (csbko) {
case CSBKO_UUVREQ:
case CSBKO::UUVREQ:
LogMessage("DMR Slot %u, received RF Unit to Unit Voice Service Request CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
writeJSONRF("csbk", "Unit to Unit Voice Service Request", srcId, src, gi, dstId);
break;
case CSBKO_UUANSRSP:
case CSBKO::UUANSRSP:
LogMessage("DMR Slot %u, received RF Unit to Unit Voice Service Answer Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
writeJSONRF("csbk", "Unit to Unit Voice Answer Response", srcId, src, gi, dstId);
break;
case CSBKO_NACKRSP:
case CSBKO::NACKRSP:
LogMessage("DMR Slot %u, received RF Negative Acknowledgment Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
writeJSONRF("csbk", "Negative Acknowledgment Response", srcId, src, gi, dstId);
break;
case CSBKO_PRECCSBK:
case CSBKO::PRECCSBK:
LogMessage("DMR Slot %u, received RF %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG ": "", dst.c_str());
writeJSONRF("csbk", "Preamble", srcId, src, gi, dstId);
break;
case CSBKO_CALL_ALERT:
case CSBKO::CALL_ALERT:
LogMessage("DMR Slot %u, received RF Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONRF("csbk", "Call Alert", srcId, src, gi, dstId);
break;
case CSBKO_CALL_ALERT_ACK:
case CSBKO::CALL_ALERT_ACK:
LogMessage("DMR Slot %u, received RF Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONRF("csbk", "Call Alert Ack", srcId, src, gi, dstId);
break;
case CSBKO_RADIO_CHECK:
case CSBKO::RADIO_CHECK:
LogMessage("DMR Slot %u, received RF Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONRF("csbk", "Radio Check", srcId, src, gi, dstId);
break;
case CSBKO_CALL_EMERGENCY:
case CSBKO::CALL_EMERGENCY:
LogMessage("DMR Slot %u, received RF Call Emergency CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONRF("csbk", "Call Emergency", srcId, src, gi, dstId);
break;
@ -562,8 +574,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
return true;
} else if (dataType == DT_RATE_12_DATA || dataType == DT_RATE_34_DATA || dataType == DT_RATE_1_DATA) {
if (m_rfState != RS_RF_DATA || m_rfFrames == 0U)
} else if ((dataType == DT_RATE_12_DATA) || (dataType == DT_RATE_34_DATA) || (dataType == DT_RATE_1_DATA)) {
if ((m_rfState != RPT_RF_STATE::DATA) || (m_rfFrames == 0U))
return false;
char title[80U];
@ -617,7 +629,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
return true;
}
} else if (audioSync) {
if (m_rfState == RS_RF_AUDIO) {
if (m_rfState == RPT_RF_STATE::AUDIO) {
m_lastrfN = 0;
// Convert the Audio Sync to be from the BS or MS as needed
CSync::addDMRAudioSync(data + 2U, m_duplex);
@ -657,13 +669,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
return false;
} else if (m_rfState == RS_RF_LISTENING) {
} else if (m_rfState == RPT_RF_STATE::LISTENING) {
m_rfEmbeddedLC.reset();
m_rfState = RS_RF_LATE_ENTRY;
m_rfState = RPT_RF_STATE::LATE_ENTRY;
return false;
}
} else {
if (m_rfState == RS_RF_AUDIO) {
if (m_rfState == RPT_RF_STATE::AUDIO) {
m_rfN = data[1U] & 0x0FU;
if (m_rfN > 5U)
return false;
@ -703,24 +715,24 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
char text[80U];
switch (flco) {
case FLCO_GROUP:
case FLCO_USER_USER:
case FLCO::GROUP:
case FLCO::USER_USER:
// ::sprintf(text, "DMR Slot %u, Embedded LC", m_slotNo);
// CUtils::dump(1U, text, data, 9U);
break;
case FLCO_GPS_INFO:
case FLCO::GINFO:
if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
CUtils::dump(1U, text, data, 9U);
logGPSPosition(data);
}
if (m_network != NULL)
if (m_network != nullptr)
m_network->writeRadioPosition(m_rfLC->getSrcId(), data);
break;
case FLCO_TALKER_ALIAS_HEADER:
if (m_network != NULL)
case FLCO::TALKER_ALIAS_HEADER:
if (m_network != nullptr)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 0U, data);
if (!(m_rfTalkerId & TALKER_ID_HEADER)) {
@ -740,8 +752,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
break;
case FLCO_TALKER_ALIAS_BLOCK1:
if (m_network != NULL)
case FLCO::TALKER_ALIAS_BLOCK1:
if (m_network != nullptr)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 1U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) {
@ -761,8 +773,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
break;
case FLCO_TALKER_ALIAS_BLOCK2:
if (m_network != NULL)
case FLCO::TALKER_ALIAS_BLOCK2:
if (m_network != nullptr)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 2U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) {
@ -782,8 +794,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
break;
case FLCO_TALKER_ALIAS_BLOCK3:
if (m_network != NULL)
case FLCO::TALKER_ALIAS_BLOCK3:
if (m_network != nullptr)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 3U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) {
@ -844,7 +856,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
return false;
} else if (m_rfState == RS_RF_LATE_ENTRY) {
} else if (m_rfState == RPT_RF_STATE::LATE_ENTRY) {
CDMREMB emb;
emb.putData(data + 2U);
@ -855,32 +867,41 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS());
CDMRLC* lc = m_rfEmbeddedLC.getLC();
if (lc != NULL) {
if (lc != nullptr) {
unsigned int srcId = lc->getSrcId();
unsigned int dstId = lc->getDstId();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
FLCO flco = lc->getFLCO();
if (!m_protect) {
if (lc->getPF()) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
delete lc;
m_rfState = RPT_RF_STATE::LISTENING;
return false;
}
}
if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId);
delete lc;
m_rfState = RS_RF_LISTENING;
m_rfState = RPT_RF_STATE::LISTENING;
return false;
}
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO::GROUP, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId);
delete lc;
m_rfState = RS_RF_LISTENING;
m_rfState = RPT_RF_STATE::LISTENING;
return false;
}
if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
if ((m_ovcm == DMR_OVCM::TX_ON) || (m_ovcm == DMR_OVCM::ON))
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
lc->setOVCM(false);
m_rfLC = lc;
@ -971,7 +992,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
writeNetworkRF(data, DT_VOICE, errors);
m_rfState = RS_RF_AUDIO;
m_rfState = RPT_RF_STATE::AUDIO;
if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
@ -992,7 +1013,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
unsigned int CDMRSlot::readModem(unsigned char* data)
{
assert(data != NULL);
assert(data != nullptr);
if (m_queue.isEmpty())
return 0U;
@ -1007,13 +1028,13 @@ unsigned int CDMRSlot::readModem(unsigned char* data)
void CDMRSlot::writeEndRF(bool writeEnd)
{
m_rfState = RS_RF_LISTENING;
m_rfState = RPT_RF_STATE::LISTENING;
if (m_netState == RS_NET_IDLE)
setShortLC(m_slotNo, 0U);
if (writeEnd) {
if (m_netState == RS_NET_IDLE && m_duplex && !m_rfTimeout) {
if ((m_netState == RPT_NET_STATE::IDLE) && m_duplex && !m_rfTimeout) {
// Create a dummy start end frame
unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
@ -1049,12 +1070,12 @@ void CDMRSlot::writeEndRF(bool writeEnd)
m_rfN = 0U;
delete m_rfLC;
m_rfLC = NULL;
m_rfLC = nullptr;
}
void CDMRSlot::writeEndNet(bool writeEnd)
{
m_netState = RS_NET_IDLE;
m_netState = RPT_NET_STATE::IDLE;
setShortLC(m_slotNo, 0U);
@ -1108,7 +1129,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
if (!m_enabled)
return;
if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE)
if ((m_rfState != RPT_RF_STATE::LISTENING) && (m_netState == RPT_NET_STATE::IDLE))
return;
m_networkWatchdog.start();
@ -1119,12 +1140,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
dmrData.getData(data + 2U);
if (dataType == DT_VOICE_LC_HEADER) {
if (m_netState == RS_NET_AUDIO)
if (m_netState == RPT_NET_STATE::AUDIO)
return;
CDMRFullLC fullLC;
CDMRLC* lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
if (lc == NULL) {
if (lc == nullptr) {
LogMessage("DMR Slot %u, bad LC received from the network, replacing", m_slotNo);
lc = new CDMRLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());
}
@ -1135,12 +1156,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
if (dstId != dmrData.getDstId() || srcId != dmrData.getSrcId() || flco != dmrData.getFLCO())
LogWarning("DMR Slot %u, DMRD header doesn't match the DMR RF header: %u->%s%u %u->%s%u", m_slotNo,
dmrData.getSrcId(), dmrData.getFLCO() == FLCO_GROUP ? "TG" : "", dmrData.getDstId(),
srcId, flco == FLCO_GROUP ? "TG" : "", dstId);
dmrData.getSrcId(), dmrData.getFLCO() == FLCO::GROUP ? "TG" : "", dmrData.getDstId(),
srcId, flco == FLCO::GROUP ? "TG" : "", dstId);
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
lc->setOVCM(false);
m_netLC = lc;
@ -1195,9 +1216,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeQueueNet(data);
}
m_netState = RS_NET_AUDIO;
m_netState = RPT_NET_STATE::AUDIO;
setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
setShortLC(m_slotNo, dstId, flco, ACTIVITY_TYPE::VOICE);
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
class CUserDBentry cn;
@ -1206,15 +1227,15 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
LogMessage("DMR Slot %u, received network voice header from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
writeJSONNet("start", srcId, src, flco == FLCO_GROUP, dstId);
} else if (dataType == DT_VOICE_PI_HEADER) {
if (m_netState != RS_NET_AUDIO) {
if (m_netState != RPT_NET_STATE::AUDIO) {
CDMRLC* lc = new CDMRLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());
unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId();
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
lc->setOVCM(false);
m_netLC = lc;
@ -1261,9 +1282,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netBits = 1U;
m_netErrs = 0U;
m_netState = RS_NET_AUDIO;
m_netState = RPT_NET_STATE::AUDIO;
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_VOICE);
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_TYPE::VOICE);
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
class CUserDBentry cn;
@ -1293,7 +1314,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeQueueNet(data);
} else if (dataType == DT_TERMINATOR_WITH_LC) {
if (m_netState != RS_NET_AUDIO)
if (m_netState != RPT_NET_STATE::AUDIO)
return;
// Regenerate the LC data
@ -1334,7 +1355,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeJSONNet("end", float(m_netFrames) / 16.667F, float(m_netLost * 100U) / float(m_netFrames), float(m_netErrs * 100U) / float(m_netBits));
writeEndNet();
} else if (dataType == DT_DATA_HEADER) {
if (m_netState == RS_NET_DATA)
if (m_netState == RPT_NET_STATE::DATA)
return;
CDMRDataHeader dataHeader;
@ -1371,9 +1392,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeQueueNet(data);
m_netState = RS_NET_DATA;
m_netState = RPT_NET_STATE::DATA;
setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA);
setShortLC(m_slotNo, dstId, gi ? FLCO::GROUP : FLCO::USER_USER, ACTIVITY_TYPE::DATA);
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
@ -1387,15 +1408,15 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeEndNet();
}
} else if (dataType == DT_VOICE_SYNC) {
if (m_netState == RS_NET_IDLE) {
if (m_netState == RPT_NET_STATE::IDLE) {
CDMRLC* lc = new CDMRLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());
unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId();
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
lc->setOVCM(false);
m_netLC = lc;
@ -1451,9 +1472,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netEmbeddedWriteN = 1U;
m_netTalkerId = TALKER_ID_NONE;
m_netState = RS_NET_AUDIO;
m_netState = RPT_NET_STATE::AUDIO;
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_VOICE);
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_TYPE::VOICE);
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
@ -1464,7 +1485,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeJSONNet("late_entry", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId);
}
if (m_netState == RS_NET_AUDIO) {
if (m_netState == RPT_NET_STATE::AUDIO) {
unsigned char fid = m_netLC->getFID();
if (fid == FID_ETSI || fid == FID_DMRA)
m_netErrs += m_fec.regenerateDMR(data + 2U);
@ -1503,7 +1524,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netN = dmrData.getN();
}
} else if (dataType == DT_VOICE) {
if (m_netState != RS_NET_AUDIO)
if (m_netState != RPT_NET_STATE::AUDIO)
return;
unsigned char fid = m_netLC->getFID();
@ -1526,19 +1547,19 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
char text[80U];
switch (flco) {
case FLCO_GROUP:
case FLCO_USER_USER:
case FLCO::GROUP:
case FLCO::USER_USER:
// ::sprintf(text, "DMR Slot %u, Embedded LC", m_slotNo);
// CUtils::dump(1U, text, data, 9U);
break;
case FLCO_GPS_INFO:
case FLCO::GINFO:
if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
CUtils::dump(1U, text, data, 9U);
logGPSPosition(data);
}
break;
case FLCO_TALKER_ALIAS_HEADER:
case FLCO::TALKER_ALIAS_HEADER:
if (!(m_netTalkerId & TALKER_ID_HEADER)) {
if (!m_netTalkerId)
m_netTalkerAlias.reset();
@ -1555,7 +1576,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netTalkerId |= TALKER_ID_HEADER;
}
break;
case FLCO_TALKER_ALIAS_BLOCK1:
case FLCO::TALKER_ALIAS_BLOCK1:
if (!(m_netTalkerId & TALKER_ID_BLOCK1)) {
if (!m_netTalkerId)
m_netTalkerAlias.reset();
@ -1572,7 +1593,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netTalkerId |= TALKER_ID_BLOCK1;
}
break;
case FLCO_TALKER_ALIAS_BLOCK2:
case FLCO::TALKER_ALIAS_BLOCK2:
if (!(m_netTalkerId & TALKER_ID_BLOCK2)) {
if (!m_netTalkerId)
m_netTalkerAlias.reset();
@ -1589,7 +1610,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netTalkerId |= TALKER_ID_BLOCK2;
}
break;
case FLCO_TALKER_ALIAS_BLOCK3:
case FLCO::TALKER_ALIAS_BLOCK3:
if (!(m_netTalkerId & TALKER_ID_BLOCK3)) {
if (!m_netTalkerId)
m_netTalkerAlias.reset();
@ -1661,13 +1682,13 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
}
CSBKO csbko = csbk.getCSBKO();
if (csbko == CSBKO_BSDWNACT)
if (csbko == CSBKO::BSDWNACT)
return;
// set the OVCM bit for the supported csbk
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
csbk.setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
csbk.setOVCM(false);
bool gi = csbk.getGI();
@ -1689,7 +1710,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
data[0U] = TAG_DATA;
data[1U] = 0x00U;
if (csbko == CSBKO_PRECCSBK && csbk.getDataContent()) {
if ((csbko == CSBKO::PRECCSBK) && csbk.getDataContent()) {
unsigned int cbf = NO_PREAMBLE_CSBK + csbk.getCBF() - 1U;
for (unsigned int i = 0U; i < NO_PREAMBLE_CSBK; i++, cbf--) {
// Change blocks to follow
@ -1716,31 +1737,31 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
std::string dst = m_lookup->find(dstId);
switch (csbko) {
case CSBKO_UUVREQ:
case CSBKO::UUVREQ:
LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Request CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
writeJSONNet("csbk", "Unit to Unit Voice Service Request", srcId, src, gi, dstId);
break;
case CSBKO_UUANSRSP:
case CSBKO::UUANSRSP:
LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Answer Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
writeJSONNet("csbk", "Unit to Unit Voice Service Answer Response", srcId, src, gi, dstId);
break;
case CSBKO_NACKRSP:
case CSBKO::NACKRSP:
LogMessage("DMR Slot %u, received network Negative Acknowledgment Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
writeJSONNet("csbk", "UNegative Acknowledgment Response", srcId, src, gi, dstId);
break;
case CSBKO_PRECCSBK:
case CSBKO::PRECCSBK:
LogMessage("DMR Slot %u, received network %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONNet("csbk", "Preamble", srcId, src, gi, dstId);
break;
case CSBKO_CALL_ALERT:
case CSBKO::CALL_ALERT:
LogMessage("DMR Slot %u, received network Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONNet("csbk", "Call Alert", srcId, src, gi, dstId);
break;
case CSBKO_CALL_ALERT_ACK:
case CSBKO::CALL_ALERT_ACK:
LogMessage("DMR Slot %u, received network Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONNet("csbk", "Call Alert Ack", srcId, src, gi, dstId);
break;
case CSBKO_RADIO_CHECK:
case CSBKO::RADIO_CHECK:
LogMessage("DMR Slot %u, received network Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
writeJSONNet("csbk", "Radio Check", srcId, src, gi, dstId);
break;
@ -1882,11 +1903,11 @@ void CDMRSlot::clock()
}
}
if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA) {
if ((m_netState == RPT_NET_STATE::AUDIO) || (m_netState == RPT_NET_STATE::DATA)) {
m_networkWatchdog.clock(ms);
if (m_networkWatchdog.hasExpired()) {
if (m_netState == RS_NET_AUDIO) {
if (m_netState == RPT_NET_STATE::AUDIO) {
// We've received the voice header haven't we?
m_netFrames += 1U;
LogMessage("DMR Slot %u, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
@ -1900,7 +1921,7 @@ void CDMRSlot::clock()
}
}
if (m_netState == RS_NET_AUDIO) {
if (m_netState == RPT_NET_STATE::AUDIO) {
m_packetTimer.clock(ms);
if (m_packetTimer.isRunning() && m_packetTimer.hasExpired()) {
@ -1918,9 +1939,9 @@ void CDMRSlot::clock()
void CDMRSlot::writeQueueRF(const unsigned char *data)
{
assert(data != NULL);
assert(data != nullptr);
if (m_netState != RS_NET_IDLE)
if (m_netState != RPT_NET_STATE::IDLE)
return;
unsigned char len = DMR_FRAME_LENGTH_BYTES + 2U;
@ -1937,12 +1958,12 @@ void CDMRSlot::writeQueueRF(const unsigned char *data)
void CDMRSlot::writeNetworkRF(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId, unsigned char errors)
{
assert(data != NULL);
assert(data != nullptr);
if (m_netState != RS_NET_IDLE)
if (m_netState != RPT_NET_STATE::IDLE)
return;
if (m_network == NULL)
if (m_network == nullptr)
return;
CDMRData dmrData;
@ -1965,15 +1986,15 @@ void CDMRSlot::writeNetworkRF(const unsigned char* data, unsigned char dataType,
void CDMRSlot::writeNetworkRF(const unsigned char* data, unsigned char dataType, unsigned char errors)
{
assert(data != NULL);
assert(m_rfLC != NULL);
assert(data != nullptr);
assert(m_rfLC != nullptr);
writeNetworkRF(data, dataType, m_rfLC->getFLCO(), m_rfLC->getSrcId(), m_rfLC->getDstId(), errors);
}
void CDMRSlot::writeQueueNet(const unsigned char *data)
{
assert(data != NULL);
assert(data != nullptr);
unsigned char len = DMR_FRAME_LENGTH_BYTES + 2U;
@ -2002,6 +2023,7 @@ void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData
m_lookup = lookup;
m_hangCount = callHang * 17U;
m_ovcm = ovcm;
m_protect = protect;
m_rssiMapper = rssiMapper;
@ -2022,7 +2044,7 @@ void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData
void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, ACTIVITY_TYPE type)
{
assert(m_modem != NULL);
assert(m_modem != nullptr);
switch (slotNo) {
case 1U:
@ -2066,41 +2088,41 @@ void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, ACTIV
if (m_id1 != 0U) {
lc[2U] = m_id1;
if (m_activity1 == ACTIVITY_VOICE && m_flco1 == FLCO_GROUP)
if ((m_activity1 == ACTIVITY_TYPE::VOICE) && (m_flco1 == FLCO::GROUP))
lc[1U] |= 0x08U;
else if (m_activity1 == ACTIVITY_VOICE && m_flco1 == FLCO_USER_USER)
else if ((m_activity1 == ACTIVITY_TYPE::VOICE) && (m_flco1 == FLCO::USER_USER))
lc[1U] |= 0x09U;
else if (m_activity1 == ACTIVITY_DATA && m_flco1 == FLCO_GROUP)
else if ((m_activity1 == ACTIVITY_TYPE::DATA) && (m_flco1 == FLCO::GROUP))
lc[1U] |= 0x0BU;
else if (m_activity1 == ACTIVITY_DATA && m_flco1 == FLCO_USER_USER)
else if ((m_activity1 == ACTIVITY_TYPE::DATA) && (m_flco1 == FLCO::USER_USER))
lc[1U] |= 0x0AU;
else if (m_activity1 == ACTIVITY_CSBK && m_flco1 == FLCO_GROUP)
else if ((m_activity1 == ACTIVITY_TYPE::CSBK) && (m_flco1 == FLCO::GROUP))
lc[1U] |= 0x02U;
else if (m_activity1 == ACTIVITY_CSBK && m_flco1 == FLCO_USER_USER)
else if ((m_activity1 == ACTIVITY_TYPE::CSBK) && (m_flco1 == FLCO::USER_USER))
lc[1U] |= 0x03U;
else if (m_activity1 == ACTIVITY_EMERG && m_flco1 == FLCO_GROUP)
else if ((m_activity1 == ACTIVITY_TYPE::EMERG) && (m_flco1 == FLCO::GROUP))
lc[1U] |= 0x0CU;
else if (m_activity1 == ACTIVITY_EMERG && m_flco1 == FLCO_USER_USER)
else if ((m_activity1 == ACTIVITY_TYPE::EMERG) && (m_flco1 == FLCO::USER_USER))
lc[1U] |= 0x0DU;
}
if (m_id2 != 0U) {
lc[3U] = m_id2;
if (m_activity2 == ACTIVITY_VOICE && m_flco2 == FLCO_GROUP)
if ((m_activity2 == ACTIVITY_TYPE::VOICE) && (m_flco2 == FLCO::GROUP))
lc[1U] |= 0x80U;
else if (m_activity2 == ACTIVITY_VOICE && m_flco2 == FLCO_USER_USER)
else if ((m_activity2 == ACTIVITY_TYPE::VOICE) && (m_flco2 == FLCO::USER_USER))
lc[1U] |= 0x90U;
else if (m_activity2 == ACTIVITY_DATA && m_flco2 == FLCO_GROUP)
else if ((m_activity2 == ACTIVITY_TYPE::DATA) && (m_flco2 == FLCO::GROUP))
lc[1U] |= 0xB0U;
else if (m_activity2 == ACTIVITY_DATA && m_flco2 == FLCO_USER_USER)
else if ((m_activity2 == ACTIVITY_TYPE::DATA) && (m_flco2 == FLCO::USER_USER))
lc[1U] |= 0xA0U;
else if (m_activity2 == ACTIVITY_CSBK && m_flco2 == FLCO_GROUP)
else if ((m_activity2 == ACTIVITY_TYPE::CSBK) && (m_flco2 == FLCO::GROUP))
lc[1U] |= 0x20U;
else if (m_activity2 == ACTIVITY_CSBK && m_flco2 == FLCO_USER_USER)
else if ((m_activity2 == ACTIVITY_TYPE::CSBK) && (m_flco2 == FLCO::USER_USER))
lc[1U] |= 0x30U;
else if (m_activity2 == ACTIVITY_EMERG && m_flco2 == FLCO_GROUP)
else if ((m_activity2 == ACTIVITY_TYPE::EMERG) && (m_flco2 == FLCO::GROUP))
lc[1U] |= 0xC0U;
else if (m_activity2 == ACTIVITY_EMERG && m_flco2 == FLCO_USER_USER)
else if ((m_activity2 == ACTIVITY_TYPE::EMERG) && (m_flco2 == FLCO::USER_USER))
lc[1U] |= 0xD0U;
}
@ -2116,7 +2138,7 @@ void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, ACTIV
bool CDMRSlot::insertSilence(const unsigned char* data, unsigned char seqNo)
{
assert(data != NULL);
assert(data != nullptr);
// Do not send duplicate
if (seqNo == m_netN)
@ -2194,7 +2216,7 @@ void CDMRSlot::insertSilence(unsigned int count)
bool CDMRSlot::isBusy() const
{
return m_rfState != RS_RF_LISTENING || m_netState != RS_NET_IDLE;
return (m_rfState != RPT_RF_STATE::LISTENING) || (m_netState != RPT_NET_STATE::IDLE);
}
void CDMRSlot::enable(bool enabled)
@ -2203,7 +2225,7 @@ void CDMRSlot::enable(bool enabled)
m_queue.clear();
// Reset the RF section
m_rfState = RS_RF_LISTENING;
m_rfState = RPT_RF_STATE::LISTENING;
m_rfTimeoutTimer.stop();
m_rfTimeout = false;
@ -2219,10 +2241,10 @@ void CDMRSlot::enable(bool enabled)
m_rfN = 0U;
delete m_rfLC;
m_rfLC = NULL;
m_rfLC = nullptr;
// Reset the networking section
m_netState = RS_NET_IDLE;
m_netState = RPT_NET_STATE::IDLE;
m_lastFrameValid = false;
@ -2240,7 +2262,7 @@ void CDMRSlot::enable(bool enabled)
m_netN = 0U;
delete m_netLC;
m_netLC = NULL;
m_netLC = nullptr;
}
m_enabled = enabled;