diff --git a/configs/config.example.yml b/configs/config.example.yml index 9838dd08..d9e0e06b 100644 --- a/configs/config.example.yml +++ b/configs/config.example.yml @@ -132,6 +132,8 @@ protocols: txHang: 8 # BER/Error threshold for silencing voice packets. (0 or 141 disables) silenceThreshold: 21 + # Maximum number of lost frames before terminating a call. + frameLossThreshold: 2 # Internal data queue size (in DMR packets). queueSize: 31 # Flag indicating whether or not verbose logging is enabled. @@ -215,6 +217,8 @@ protocols: sndcpGrant: false # BER/Error threshold for silencing voice packets. (0 or 1233 disables) silenceThreshold: 124 + # Maximum number of lost frames before terminating a call. + frameLossThreshold: 6 # Flag indicating whether or not a voice HDU will transmitted at the start of a call from the network. disableNetworkHDU: false # Internal data queue size (in P25 packets). @@ -262,6 +266,8 @@ protocols: callHang: 5 # BER/Error threshold for silencing voice packets. (0 or 144 disables) silenceThreshold: 14 + # Maximum number of lost frames before terminating a call. + frameLossThreshold: 4 # Internal data queue size (in NXDN packets). queueSize: 31 # Flag indicating whether or not verbose logging is enabled. diff --git a/src/dmr/Control.cpp b/src/dmr/Control.cpp index 57e39023..30d9ec4d 100644 --- a/src/dmr/Control.cpp +++ b/src/dmr/Control.cpp @@ -192,7 +192,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::vectorsetSilenceThreshold(silenceThreshold); m_slot2->setSilenceThreshold(silenceThreshold); + uint8_t frameLossThreshold = (uint8_t)dmrProtocol["frameLossThreshold"].as(dmr::DEFAULT_FRAME_LOSS_THRESHOLD); + if (frameLossThreshold == 0U) { + frameLossThreshold = 1U; + } + + if (frameLossThreshold > dmr::DEFAULT_FRAME_LOSS_THRESHOLD * 2U) { + LogWarning(LOG_DMR, "Frame loss threshold may be excessive, default is %u, configured is %u", dmr::DEFAULT_FRAME_LOSS_THRESHOLD, frameLossThreshold); + } + + m_slot1->setFrameLossThreshold(frameLossThreshold); + m_slot2->setFrameLossThreshold(frameLossThreshold); + if (printOptions) { if (enableTSCC) { LogInfo(" TSCC Slot: %u", m_tsccSlotNo); @@ -212,6 +224,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::vector #include -// --------------------------------------------------------------------------- -// Constants -// --------------------------------------------------------------------------- - -const uint8_t MAX_LOST_FRAMES = 2U; - // --------------------------------------------------------------------------- // Static Class Members // --------------------------------------------------------------------------- @@ -162,6 +156,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz m_rssiCount(0U), m_silenceThreshold(DEFAULT_SILENCE_THRESHOLD), m_frameLossCnt(0U), + m_frameLossThreshold(DEFAULT_FRAME_LOSS_THRESHOLD), m_ccSeq(0U), m_ccRunning(false), m_ccPrevRunning(false), @@ -206,7 +201,7 @@ bool Slot::processFrame(uint8_t *data, uint32_t len) assert(data != nullptr); if (data[0U] == modem::TAG_LOST) { - if (m_frameLossCnt > MAX_LOST_FRAMES) { + if (m_frameLossCnt > m_frameLossThreshold) { m_frameLossCnt = 0U; processFrameLoss(); @@ -605,7 +600,7 @@ void Slot::clock() if (m_frameLossCnt > 0U && m_rfState == RS_RF_LISTENING) m_frameLossCnt = 0U; - if (m_frameLossCnt >= MAX_LOST_FRAMES && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) { + if (m_frameLossCnt >= m_frameLossThreshold && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) { processFrameLoss(); } } @@ -728,15 +723,6 @@ void Slot::setTSCCActivated(uint32_t dstId, uint32_t srcId, bool group, bool voi m_tsccPayloadVoice = voice; } -/// -/// Helper to set the voice error silence threshold. -/// -/// -void Slot::setSilenceThreshold(uint32_t threshold) -{ - m_silenceThreshold = threshold; -} - /// /// Helper to get the last transmitted destination ID. /// diff --git a/src/dmr/Slot.h b/src/dmr/Slot.h index 1cf2e825..aaffb3f5 100644 --- a/src/dmr/Slot.h +++ b/src/dmr/Slot.h @@ -120,7 +120,9 @@ namespace dmr /// Sets a flag indicating whether the voice channels will notify the TSCC of traffic channel changes. void setNotifyCC(bool notifyCC) { m_notifyCC = notifyCC; } /// Helper to set the voice error silence threshold. - void setSilenceThreshold(uint32_t threshold); + void setSilenceThreshold(uint32_t threshold) { m_silenceThreshold = threshold; } + /// Helper to set the frame loss threshold. + void setFrameLossThreshold(uint32_t threshold) { m_frameLossThreshold = threshold; } /// Helper to get the last transmitted destination ID. uint32_t getLastDstId() const; @@ -204,6 +206,7 @@ namespace dmr uint32_t m_silenceThreshold; uint8_t m_frameLossCnt; + uint8_t m_frameLossThreshold; uint8_t m_ccSeq; bool m_ccRunning; diff --git a/src/nxdn/Control.cpp b/src/nxdn/Control.cpp index a83756fa..25339275 100644 --- a/src/nxdn/Control.cpp +++ b/src/nxdn/Control.cpp @@ -58,8 +58,6 @@ 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, @@ -136,6 +134,7 @@ Control::Control(bool authoritative, uint32_t ran, uint32_t callHang, uint32_t q m_networkWatchdog(1000U, 0U, 1500U), m_ccPacketInterval(1000U, 0U, 80U), m_frameLossCnt(0U), + m_frameLossThreshold(DEFAULT_FRAME_LOSS_THRESHOLD), m_ccFrameCnt(0U), m_ccSeq(0U), m_siteData(), @@ -258,6 +257,14 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw LogWarning(LOG_NXDN, "Silence threshold set to zero, defaulting to %u", nxdn::MAX_NXDN_VOICE_ERRORS); m_voice->m_silenceThreshold = nxdn::MAX_NXDN_VOICE_ERRORS; } + m_frameLossThreshold = (uint8_t)nxdnProtocol["frameLossThreshold"].as(nxdn::DEFAULT_FRAME_LOSS_THRESHOLD); + if (m_frameLossThreshold == 0U) { + m_frameLossThreshold = 1U; + } + + if (m_frameLossThreshold > nxdn::DEFAULT_FRAME_LOSS_THRESHOLD * 2U) { + LogWarning(LOG_NXDN, "Frame loss threshold may be excessive, default is %u, configured is %u", nxdn::DEFAULT_FRAME_LOSS_THRESHOLD, m_frameLossThreshold); + } bool disableCompositeFlag = nxdnProtocol["disableCompositeFlag"].as(false); uint8_t serviceClass = NXDN_SIF1_VOICE_CALL_SVC | NXDN_SIF1_DATA_CALL_SVC; @@ -329,6 +336,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw if (printOptions) { LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F); + LogInfo(" Frame Loss Threshold: %u", m_frameLossThreshold); if (m_control) { LogInfo(" Voice on Control: %s", m_voiceOnControl ? "yes" : "no"); @@ -365,7 +373,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len) bool sync = data[1U] == 0x01U; if (data[0U] == modem::TAG_LOST) { - if (m_frameLossCnt > MAX_LOST_FRAMES) { + if (m_frameLossCnt > m_frameLossThreshold) { m_frameLossCnt = 0U; processFrameLoss(); @@ -670,7 +678,7 @@ void Control::clock(uint32_t ms) if (m_frameLossCnt > 0U && m_rfState == RS_RF_LISTENING) m_frameLossCnt = 0U; - if (m_frameLossCnt >= MAX_LOST_FRAMES && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) { + if (m_frameLossCnt >= m_frameLossThreshold && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) { processFrameLoss(); } diff --git a/src/nxdn/Control.h b/src/nxdn/Control.h index 5277da3b..9fa1fee1 100644 --- a/src/nxdn/Control.h +++ b/src/nxdn/Control.h @@ -198,6 +198,7 @@ namespace nxdn Timer m_ccPacketInterval; uint8_t m_frameLossCnt; + uint8_t m_frameLossThreshold; uint8_t m_ccFrameCnt; uint8_t m_ccSeq; diff --git a/src/nxdn/NXDNDefines.h b/src/nxdn/NXDNDefines.h index a8b6a89e..02a4d623 100644 --- a/src/nxdn/NXDNDefines.h +++ b/src/nxdn/NXDNDefines.h @@ -145,6 +145,7 @@ namespace nxdn const uint8_t SACCH_IDLE[] = { 0x10U, 0x00U, 0x00U }; const uint32_t DEFAULT_SILENCE_THRESHOLD = 14U; + const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 4U; const uint32_t MAX_NXDN_VOICE_ERRORS = 144U; const uint32_t MAX_NXDN_VOICE_ERRORS_STEAL = 94U; diff --git a/src/p25/Control.cpp b/src/p25/Control.cpp index 2d9763bc..4f7681e9 100644 --- a/src/p25/Control.cpp +++ b/src/p25/Control.cpp @@ -56,8 +56,6 @@ 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 = 6U; - // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -135,6 +133,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q m_hangCount(3U * 8U), m_tduPreambleCount(8U), m_frameLossCnt(0U), + m_frameLossThreshold(DEFAULT_FRAME_LOSS_THRESHOLD), m_ccFrameCnt(0U), m_ccSeq(0U), m_nid(nac), @@ -285,6 +284,14 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw LogWarning(LOG_P25, "Silence threshold set to zero, defaulting to %u", p25::MAX_P25_VOICE_ERRORS); m_voice->m_silenceThreshold = p25::MAX_P25_VOICE_ERRORS; } + m_frameLossThreshold = (uint8_t)p25Protocol["frameLossThreshold"].as(p25::DEFAULT_FRAME_LOSS_THRESHOLD); + if (m_frameLossThreshold == 0U) { + m_frameLossThreshold = 1U; + } + + if (m_frameLossThreshold > p25::DEFAULT_FRAME_LOSS_THRESHOLD * 2U) { + LogWarning(LOG_P25, "Frame loss threshold may be excessive, default is %u, configured is %u", p25::DEFAULT_FRAME_LOSS_THRESHOLD, m_frameLossThreshold); + } m_disableNetworkHDU = p25Protocol["disableNetworkHDU"].as(false); @@ -373,6 +380,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw if (printOptions) { LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F); + LogInfo(" Frame Loss Threshold: %u", m_frameLossThreshold); if (m_control) { LogInfo(" Voice on Control: %s", m_voiceOnControl ? "yes" : "no"); @@ -445,7 +453,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len) bool sync = data[1U] == 0x01U; if (data[0U] == modem::TAG_LOST) { - if (m_frameLossCnt > MAX_LOST_FRAMES) { + if (m_frameLossCnt > m_frameLossThreshold) { m_frameLossCnt = 0U; processFrameLoss(); @@ -834,7 +842,7 @@ void Control::clock(uint32_t ms) if (m_frameLossCnt > 0U && m_rfState == RS_RF_LISTENING) m_frameLossCnt = 0U; - if (m_frameLossCnt >= MAX_LOST_FRAMES && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) { + if (m_frameLossCnt >= m_frameLossThreshold && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) { processFrameLoss(); } diff --git a/src/p25/Control.h b/src/p25/Control.h index 8738f939..4417f759 100644 --- a/src/p25/Control.h +++ b/src/p25/Control.h @@ -214,6 +214,7 @@ namespace p25 uint32_t m_tduPreambleCount; uint8_t m_frameLossCnt; + uint8_t m_frameLossThreshold; uint8_t m_ccFrameCnt; uint8_t m_ccSeq; diff --git a/src/p25/P25Defines.h b/src/p25/P25Defines.h index b983937c..39b7844c 100644 --- a/src/p25/P25Defines.h +++ b/src/p25/P25Defines.h @@ -201,6 +201,7 @@ namespace p25 const uint32_t P25_TGID_ALL = 0xFFFFU; const uint32_t DEFAULT_SILENCE_THRESHOLD = 124U; + const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 6U; const uint32_t MAX_P25_VOICE_ERRORS = 1233U; const uint8_t P25_FT_HDU_VALID = 0x01U;