diff --git a/src/host/p25/packet/Voice.cpp b/src/host/p25/packet/Voice.cpp index e0f22aa0..389152fe 100644 --- a/src/host/p25/packet/Voice.cpp +++ b/src/host/p25/packet/Voice.cpp @@ -674,24 +674,16 @@ bool Voice::process(uint8_t* data, uint32_t len) else { std::lock_guard lock(m_p25->s_activeTGLock); if (m_p25->m_activeTG.size() > 0) { - if (m_grpUpdtCount > m_p25->m_activeTG.size()) - m_grpUpdtCount = 0U; - - if (m_p25->m_activeTG.size() < 2) { - uint32_t dstId = m_p25->m_activeTG.at(0); - m_rfLC.setMFId(MFG_STANDARD); - m_rfLC.setLCO(LCO::GROUP_UPDT); - m_rfLC.setDstId(dstId); - } - else { - uint32_t dstId = m_p25->m_activeTG.at(m_grpUpdtCount); - uint32_t dstIdB = m_p25->m_activeTG.at(m_grpUpdtCount + 1U); + uint32_t dstId = 0U; + uint32_t dstIdB = 0U; + bool hasDstIdB = false; + if (nextActiveTalkgroups(m_p25->m_activeTG, m_grpUpdtCount, dstId, dstIdB, hasDstIdB)) { m_rfLC.setMFId(MFG_STANDARD); m_rfLC.setLCO(LCO::GROUP_UPDT); m_rfLC.setDstId(dstId); - m_rfLC.setDstIdB(dstIdB); - - m_grpUpdtCount++; + if (hasDstIdB) { + m_rfLC.setDstIdB(dstIdB); + } } } } @@ -2063,24 +2055,16 @@ void Voice::writeNet_LDU1() else { std::lock_guard lock(m_p25->s_activeTGLock); if (m_p25->m_activeTG.size() > 0) { - if (m_grpUpdtCount > m_p25->m_activeTG.size()) - m_grpUpdtCount = 0U; - - if (m_p25->m_activeTG.size() < 2) { - uint32_t dstId = m_p25->m_activeTG.at(0); + uint32_t dstId = 0U; + uint32_t dstIdB = 0U; + bool hasDstIdB = false; + if (nextActiveTalkgroups(m_p25->m_activeTG, m_grpUpdtCount, dstId, dstIdB, hasDstIdB)) { m_netLC.setMFId(MFG_STANDARD); m_netLC.setLCO(LCO::GROUP_UPDT); m_netLC.setDstId(dstId); - } - else { - uint32_t dstId = m_p25->m_activeTG.at(m_grpUpdtCount); - uint32_t dstIdB = m_p25->m_activeTG.at(m_grpUpdtCount + 1U); - m_netLC.setMFId(MFG_STANDARD); - m_netLC.setLCO(LCO::GROUP_UPDT); - m_netLC.setDstId(dstId); - m_netLC.setDstIdB(dstIdB); - - m_grpUpdtCount++; + if (hasDstIdB) { + m_netLC.setDstIdB(dstIdB); + } } } } @@ -2352,6 +2336,38 @@ void Voice::resetWithNullAudio(uint8_t* data, bool encrypted) } } +/* Helper to determine the next active talkgroup in a active multi-group scenario. */ + +bool Voice::nextActiveTalkgroups(const std::vector& activeTG, uint8_t& groupUpdtIndex, uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB) +{ + const size_t count = activeTG.size(); + if (count == 0U) { + groupUpdtIndex = 0U; + hasDstIdB = false; + return false; + } + + size_t index = static_cast(groupUpdtIndex); + if (index >= count) { + index = 0U; + } + + dstId = activeTG[index]; + if (count < 2U) { + groupUpdtIndex = static_cast(index); + hasDstIdB = false; + return true; + } + + const size_t nextIndex = (index + 1U) % count; + dstIdB = activeTG[nextIndex]; + hasDstIdB = true; + + // move the rolling index forward for the next report cycle + groupUpdtIndex = static_cast(nextIndex); + return true; +} + /* Given the last MI, generate the next MI using LFSR. */ void Voice::getNextMI(uint8_t lastMI[9U], uint8_t nextMI[9U]) diff --git a/src/host/p25/packet/Voice.h b/src/host/p25/packet/Voice.h index a5bb238f..c515e111 100644 --- a/src/host/p25/packet/Voice.h +++ b/src/host/p25/packet/Voice.h @@ -210,6 +210,18 @@ namespace p25 */ void resetWithNullAudio(uint8_t* data, bool encrypted); + /** + * @brief Helper to determine the next active talkgroup in a active multi-group scenario, + * this is intended to update the GROUP_UPDT LC field for the next transmission. + * @param activeTG Vector of active talkgroups. + * @param groupUpdtIndex Index of the current group update. + * @param dstId Destination ID of the current talkgroup. + * @param dstIdB Destination ID of the secondary talkgroup. + * @param hasDstIdB Flag indicating whether a secondary talkgroup exists. + * @return bool True if there is a next active talkgroup, otherwise false. + */ + bool nextActiveTalkgroups(const std::vector& activeTG, uint8_t& groupUpdtIndex, uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB); + /** * @brief Given the last MI, generate the next MI using LFSR. * @param lastMI Last MI received.