diff --git a/src/dmr/Slot.cpp b/src/dmr/Slot.cpp index fbbdaca2..486e4c43 100644 --- a/src/dmr/Slot.cpp +++ b/src/dmr/Slot.cpp @@ -45,6 +45,12 @@ using namespace dmr::packet; #include #include +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- + +const uint8_t MAX_LOST_FRAMES = 4U; + // --------------------------------------------------------------------------- // Static Class Members // --------------------------------------------------------------------------- @@ -152,6 +158,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz m_aveRSSI(0U), m_rssiCount(0U), m_silenceThreshold(DEFAULT_SILENCE_THRESHOLD), + m_frameLossCnt(0U), m_ccSeq(0U), m_ccRunning(false), m_ccPrevRunning(false), @@ -195,52 +202,75 @@ bool Slot::processFrame(uint8_t *data, uint32_t len) { assert(data != nullptr); - if (data[0U] == modem::TAG_LOST && m_rfState == RS_RF_AUDIO) { - if (m_rssi != 0U) { - ::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", - m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - } - else { - ::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%", - m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); - } + if (data[0U] == modem::TAG_LOST) { + if (m_frameLossCnt > MAX_LOST_FRAMES) { + m_frameLossCnt = 0U; + + if (m_rfState == RS_RF_AUDIO) { + if (m_rssi != 0U) { + ::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", + m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + } + else { + ::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%", + m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); + } + + LogMessage(LOG_RF, "DMR Slot %u, total frames: %d, total bits: %d, errors: %d, BER: %.4f%%", + m_slotNo, m_rfFrames, m_rfBits, m_rfErrs, float(m_rfErrs * 100U) / float(m_rfBits)); + + // release trunked grant (if necessary) + Slot *m_tscc = m_dmr->getTSCCSlot(); + if (m_tscc != nullptr) { + if (m_tscc->m_enableTSCC && m_rfLC != nullptr) { + m_tscc->m_affiliations->releaseGrant(m_rfLC->getDstId(), false); + } + } + + if (!m_tscc->m_enableTSCC) { + notifyCC_ReleaseGrant(m_rfLC->getDstId()); + } - LogMessage(LOG_RF, "DMR Slot %u, total frames: %d, total bits: %d, errors: %d, BER: %.4f%%", - m_slotNo, m_rfFrames, m_rfBits, m_rfErrs, float(m_rfErrs * 100U) / float(m_rfBits)); + if (m_rfTimeout) { + writeEndRF(); + return false; + } + else { + writeEndRF(true); + return true; + } + } - // release trunked grant (if necessary) - Slot *m_tscc = m_dmr->getTSCCSlot(); - if (m_tscc != nullptr) { - if (m_tscc->m_enableTSCC && m_rfLC != nullptr) { - m_tscc->m_affiliations->releaseGrant(m_rfLC->getDstId(), false); + if (m_rfState == RS_RF_DATA) { + ::ActivityLog("DMR", true, "Slot %u, RF data transmission lost", m_slotNo); + writeEndRF(); + return false; } - } - if (!m_tscc->m_enableTSCC) { - notifyCC_ReleaseGrant(m_rfLC->getDstId()); - } + m_rfState = RS_RF_LISTENING; + + m_rfLastDstId = 0U; + m_rfTGHang.stop(); - if (m_rfTimeout) { - writeEndRF(); return false; } else { - writeEndRF(true); - return true; - } - } + // increment the frame loss count by one for audio or data; otherwise drop + // packets + if (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA) { + ++m_frameLossCnt; + } + else { + // drop normally + m_frameLossCnt = 0U; + m_rfState = RS_RF_LISTENING; - if (data[0U] == modem::TAG_LOST && m_rfState == RS_RF_DATA) { - ::ActivityLog("DMR", true, "Slot %u, RF data transmission lost", m_slotNo); - writeEndRF(); - return false; - } + m_rfLastDstId = 0U; + m_rfTGHang.stop(); - if (data[0U] == modem::TAG_LOST) { - m_rfState = RS_RF_LISTENING; - m_rfLastDstId = 0U; - m_rfTGHang.stop(); - return false; + return false; + } + } } // Have we got RSSI bytes on the end? diff --git a/src/dmr/Slot.h b/src/dmr/Slot.h index 2134ab38..025d880f 100644 --- a/src/dmr/Slot.h +++ b/src/dmr/Slot.h @@ -194,6 +194,8 @@ namespace dmr uint32_t m_silenceThreshold; + uint8_t m_frameLossCnt; + uint8_t m_ccSeq; bool m_ccRunning; bool m_ccPrevRunning; diff --git a/src/nxdn/Control.cpp b/src/nxdn/Control.cpp index 990615da..d2806875 100644 --- a/src/nxdn/Control.cpp +++ b/src/nxdn/Control.cpp @@ -58,6 +58,8 @@ using namespace nxdn::packet; const uint8_t MAX_SYNC_BYTES_ERRS = 0U; +const uint8_t MAX_LOST_FRAMES = 4U; + const uint8_t SCRAMBLER[] = { 0x00U, 0x00U, 0x00U, 0x82U, 0xA0U, 0x88U, 0x8AU, 0x00U, 0xA2U, 0xA8U, 0x82U, 0x8AU, 0x82U, 0x02U, 0x20U, 0x08U, 0x8AU, 0x20U, 0xAAU, 0xA2U, 0x82U, 0x08U, 0x22U, 0x8AU, 0xAAU, 0x08U, 0x28U, 0x88U, @@ -130,6 +132,7 @@ Control::Control(bool authoritative, uint32_t ran, uint32_t callHang, uint32_t q m_netTimeout(1000U, timeout), m_networkWatchdog(1000U, 0U, 1500U), m_ccPacketInterval(1000U, 0U, 80U), + m_frameLossCnt(0U), m_ccFrameCnt(0U), m_ccSeq(0U), m_siteData(), @@ -355,44 +358,65 @@ bool Control::processFrame(uint8_t* data, uint32_t len) { assert(data != nullptr); - uint8_t type = data[0U]; bool sync = data[1U] == 0x01U; - if (type == modem::TAG_LOST && m_rfState == RS_RF_AUDIO) { - if (m_rssi != 0U) { - ::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", - float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + if (data[0U] == modem::TAG_LOST) { + if (m_frameLossCnt > MAX_LOST_FRAMES) { + m_frameLossCnt = 0U; + + if (m_rfState == RS_RF_AUDIO) { + if (m_rssi != 0U) { + ::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", + float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + } + else { + ::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%", + float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); + } + + LogMessage(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_TX_REL ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", + m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); + + m_affiliations.releaseGrant(m_rfLC.getDstId(), false); + if (!m_control) { + notifyCC_ReleaseGrant(m_rfLC.getDstId()); + } + + writeEndRF(); + return false; + } + + if (m_rfState == RS_RF_DATA) { + writeEndRF(); + return false; + } + + m_rfState = RS_RF_LISTENING; + + m_rfMask = 0x00U; + m_rfLC.reset(); + + return false; } else { - ::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%", - float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); - } + // increment the frame loss count by one for audio or data; otherwise drop + // packets + if (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA) { + ++m_frameLossCnt; + } + else { + m_frameLossCnt = 0U; + m_rfState = RS_RF_LISTENING; - LogMessage(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_TX_REL ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", - m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); + m_rfMask = 0x00U; + m_rfLC.reset(); - m_affiliations.releaseGrant(m_rfLC.getDstId(), false); - if (!m_control) { - notifyCC_ReleaseGrant(m_rfLC.getDstId()); + return false; + } } - - writeEndRF(); - return false; } - if (type == modem::TAG_LOST && m_rfState == RS_RF_DATA) { - writeEndRF(); - return false; - } - - if (type == modem::TAG_LOST) { - m_rfState = RS_RF_LISTENING; - m_rfMask = 0x00U; - m_rfLC.reset(); - return false; - } - - // Have we got RSSI bytes on the end? + // have we got RSSI bytes on the end? if (len == (NXDN_FRAME_LENGTH_BYTES + 4U)) { uint16_t raw = 0U; raw |= (data[50U] << 8) & 0xFF00U; diff --git a/src/nxdn/Control.h b/src/nxdn/Control.h index 98d11ffa..07b4e19e 100644 --- a/src/nxdn/Control.h +++ b/src/nxdn/Control.h @@ -188,6 +188,8 @@ namespace nxdn Timer m_ccPacketInterval; + uint8_t m_frameLossCnt; + uint8_t m_ccFrameCnt; uint8_t m_ccSeq; diff --git a/src/p25/Control.cpp b/src/p25/Control.cpp index e4b0d148..da881a21 100644 --- a/src/p25/Control.cpp +++ b/src/p25/Control.cpp @@ -58,6 +58,8 @@ const uint8_t MAX_SYNC_BYTES_ERRS = 4U; const uint32_t TSBK_PCH_CCH_CNT = 6U; const uint32_t MAX_PREAMBLE_TDU_CNT = 64U; +const uint8_t MAX_LOST_FRAMES = 4U; + // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -130,6 +132,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q m_ccPacketInterval(1000U, 0U, 10U), m_hangCount(3U * 8U), m_tduPreambleCount(8U), + m_frameLossCnt(0U), m_ccFrameCnt(0U), m_ccSeq(0U), m_nid(nac), @@ -440,66 +443,86 @@ bool Control::processFrame(uint8_t* data, uint32_t len) bool sync = data[1U] == 0x01U; - if (data[0U] == modem::TAG_LOST && m_rfState == RS_RF_AUDIO) { - if (m_rssi != 0U) { - ::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", - float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - } - else { - ::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%", - float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); - } + if (data[0U] == modem::TAG_LOST) { + if (m_frameLossCnt > MAX_LOST_FRAMES) { + m_frameLossCnt = 0U; - LogMessage(LOG_RF, P25_TDU_STR ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", - m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); + if (m_rfState == RS_RF_AUDIO) { + if (m_rssi != 0U) { + ::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", + float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + } + else { + ::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%", + float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); + } - m_affiliations.releaseGrant(m_voice->m_rfLC.getDstId(), false); - if (!m_control) { - notifyCC_ReleaseGrant(m_voice->m_rfLC.getDstId()); - } - m_trunk->writeNet_TSDU_Call_Term(m_voice->m_rfLC.getSrcId(), m_voice->m_rfLC.getDstId()); + LogMessage(LOG_RF, P25_TDU_STR ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", + m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits)); - writeRF_TDU(false); - m_voice->m_lastDUID = P25_DUID_TDU; - m_voice->writeNetwork(data + 2U, P25_DUID_TDU); + m_affiliations.releaseGrant(m_voice->m_rfLC.getDstId(), false); + if (!m_control) { + notifyCC_ReleaseGrant(m_voice->m_rfLC.getDstId()); + } + m_trunk->writeNet_TSDU_Call_Term(m_voice->m_rfLC.getSrcId(), m_voice->m_rfLC.getDstId()); - m_rfState = RS_RF_LISTENING; - m_rfLastDstId = 0U; - m_rfTGHang.stop(); + writeRF_TDU(false); + m_voice->m_lastDUID = P25_DUID_TDU; + m_voice->writeNetwork(data + 2U, P25_DUID_TDU); - m_tailOnIdle = true; + m_rfState = RS_RF_LISTENING; + m_rfLastDstId = 0U; + m_rfTGHang.stop(); - m_rfTimeout.stop(); - m_txQueue.clear(); + m_tailOnIdle = true; - if (m_network != nullptr) - m_network->resetP25(); + m_rfTimeout.stop(); + m_txQueue.clear(); - return false; - } + if (m_network != nullptr) + m_network->resetP25(); - if (data[0U] == modem::TAG_LOST && m_rfState == RS_RF_DATA) { - m_rfState = RS_RF_LISTENING; - m_rfLastDstId = 0U; - m_rfTGHang.stop(); + return false; + } - m_tailOnIdle = true; + if (m_rfState == RS_RF_DATA) { + m_rfState = RS_RF_LISTENING; + m_rfLastDstId = 0U; + m_rfTGHang.stop(); - m_data->resetRF(); + m_tailOnIdle = true; - m_rfTimeout.stop(); - m_txQueue.clear(); + m_data->resetRF(); - return false; - } + m_rfTimeout.stop(); + m_txQueue.clear(); - if (data[0U] == modem::TAG_LOST) { - m_rfState = RS_RF_LISTENING; + return false; + } - m_voice->resetRF(); - m_data->resetRF(); + m_rfState = RS_RF_LISTENING; - return false; + m_voice->resetRF(); + m_data->resetRF(); + + return false; + } + else { + // increment the frame loss count by one for audio or data; otherwise drop + // packets + if (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA) { + ++m_frameLossCnt; + } + else { + m_frameLossCnt = 0U; + m_rfState = RS_RF_LISTENING; + + m_voice->resetRF(); + m_data->resetRF(); + + return false; + } + } } if (!sync && m_rfState == RS_RF_LISTENING) { diff --git a/src/p25/Control.h b/src/p25/Control.h index 16e34352..6f066186 100644 --- a/src/p25/Control.h +++ b/src/p25/Control.h @@ -206,6 +206,8 @@ namespace p25 uint32_t m_hangCount; uint32_t m_tduPreambleCount; + uint8_t m_frameLossCnt; + uint8_t m_ccFrameCnt; uint8_t m_ccSeq;