From 9a4078b6a414a9742c5521a6fc1cc49646ee45ff Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Tue, 6 Apr 2021 18:59:52 +0000 Subject: [PATCH] conform to P25 standards for composite control channel when VoC mode is enabled, and transmit LC_RFSS_STS_BCAST every 3 superframes; --- p25/TrunkPacket.cpp | 3 +++ p25/VoicePacket.cpp | 31 +++++++++++++++++++++++++++++++ p25/VoicePacket.h | 2 ++ p25/lc/LC.cpp | 13 +++++++++++++ p25/lc/LC.h | 3 +++ 5 files changed, 52 insertions(+) diff --git a/p25/TrunkPacket.cpp b/p25/TrunkPacket.cpp index 6f2b2f29..0d7823db 100644 --- a/p25/TrunkPacket.cpp +++ b/p25/TrunkPacket.cpp @@ -216,6 +216,9 @@ void TrunkPacket::setServiceClass(bool control, bool voiceOnControl) m_rfTDULC.setServiceClass(serviceClass); m_netTDULC.setServiceClass(serviceClass); + + m_p25->m_voice->m_rfLC.setServiceClass(serviceClass); + m_p25->m_voice->m_netLC.setServiceClass(serviceClass); } /// diff --git a/p25/VoicePacket.cpp b/p25/VoicePacket.cpp index aac48178..df02d64b 100644 --- a/p25/VoicePacket.cpp +++ b/p25/VoicePacket.cpp @@ -46,6 +46,12 @@ using namespace p25; #include #include +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- + +const uint32_t VOC_LDU1_COUNT = 3U; + // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -62,6 +68,7 @@ void VoicePacket::resetRF() m_rfErrs = 0U; m_rfBits = 1U; m_rfUndecodableLC = 0U; + m_vocLDU1Count = 0U; } /// @@ -73,6 +80,7 @@ void VoicePacket::resetNet() m_netLastLDU1.reset(); m_netFrames = 0U; m_netLost = 0U; + m_vocLDU1Count = 0U; } /// @@ -373,6 +381,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) m_rfErrs = 0U; m_rfBits = 1U; m_rfUndecodableLC = 0U; + m_vocLDU1Count = 0U; m_p25->m_rfTimeout.start(); m_lastDUID = P25_DUID_HDU; @@ -436,6 +445,16 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) m_p25->m_trunk->touchDstIdGrant(m_rfLC.getDstId()); } + // single-channel trunking or voice on control support? + if (m_p25->m_control && m_p25->m_voiceOnControl) { + // per TIA-102.AABD-B transmit RFSS_STS_BCAST every 3 superframes (e.g. every 3 LDU1s) + m_vocLDU1Count++; + if (m_vocLDU1Count > VOC_LDU1_COUNT) { + m_vocLDU1Count = 0U; + m_rfLC.setLCO(LC_RFSS_STS_BCAST); + } + } + // Generate Sync Sync::addP25Sync(data + 2U); @@ -865,6 +884,7 @@ VoicePacket::VoicePacket(Control* p25, network::BaseNetwork* network, bool debug m_lastRejectId(0U), m_lastPatchGroup(0U), m_silenceThreshold(124U), + m_vocLDU1Count(0U), m_verbose(verbose), m_debug(debug) { @@ -1201,6 +1221,7 @@ void VoicePacket::writeNet_LDU1(const lc::LC& control, const data::LowSpeedData& m_p25->m_netTimeout.start(); m_netFrames = 0U; m_netLost = 0U; + m_vocLDU1Count = 0U; if (!m_p25->m_disableNetworkHDU) { uint8_t buffer[P25_HDU_FRAME_LENGTH_BYTES + 2U]; @@ -1237,6 +1258,16 @@ void VoicePacket::writeNet_LDU1(const lc::LC& control, const data::LowSpeedData& } } + // single-channel trunking or voice on control support? + if (m_p25->m_control && m_p25->m_voiceOnControl) { + // per TIA-102.AABD-B transmit RFSS_STS_BCAST every 3 superframes (e.g. every 3 LDU1s) + m_vocLDU1Count++; + if (m_vocLDU1Count > VOC_LDU1_COUNT) { + m_vocLDU1Count = 0U; + m_netLC.setLCO(LC_RFSS_STS_BCAST); + } + } + insertMissingAudio(m_netLDU1); uint8_t buffer[P25_LDU_FRAME_LENGTH_BYTES + 2U]; diff --git a/p25/VoicePacket.h b/p25/VoicePacket.h index 977b611d..267f485d 100644 --- a/p25/VoicePacket.h +++ b/p25/VoicePacket.h @@ -103,6 +103,8 @@ namespace p25 uint32_t m_silenceThreshold; + uint8_t m_vocLDU1Count; + bool m_verbose; bool m_debug; diff --git a/p25/lc/LC.cpp b/p25/lc/LC.cpp index f8b438fc..74ae8ddb 100644 --- a/p25/lc/LC.cpp +++ b/p25/lc/LC.cpp @@ -57,6 +57,7 @@ LC::LC() : m_mfId(P25_MFG_STANDARD), m_srcId(0U), m_dstId(0U), + m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), m_emergency(false), m_encrypted(false), m_priority(4U), @@ -97,6 +98,8 @@ LC& LC::operator=(const LC& data) m_srcId = data.m_srcId; m_dstId = data.m_dstId; + m_serviceClass = data.m_serviceClass; + m_grpVchNo = data.m_grpVchNo; m_emergency = data.m_emergency; @@ -633,6 +636,16 @@ void LC::encodeLC(uint8_t * rs) rsValue = (rsValue << 16) + m_callTimer; // Call Timer rsValue = (rsValue << 24) + m_srcId; // Source/Target Radio Address break; + case LC_RFSS_STS_BCAST: + rs[0U] |= 0x40U; // Implicit Operation + rsValue = m_siteData.lra(); // Location Registration Area + rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID + rsValue = (rsValue << 8) + m_siteData.rfssId(); // RF Sub-System ID + rsValue = (rsValue << 8) + m_siteData.siteId(); // Site ID + rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID + rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number + rsValue = (rsValue << 8) + m_serviceClass; // System Service Class + break; default: LogError(LOG_P25, "unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); break; diff --git a/p25/lc/LC.h b/p25/lc/LC.h index 8e7f43e2..7be2078f 100644 --- a/p25/lc/LC.h +++ b/p25/lc/LC.h @@ -107,6 +107,9 @@ namespace p25 /// Destination ID. __PROPERTY(uint32_t, dstId, DstId); + /// Service class. + __PROPERTY(uint8_t, serviceClass, ServiceClass); + /// Voice channel number. __PROPERTY(uint32_t, grpVchNo, GrpVchNo);