diff --git a/src/dmr/Slot.cpp b/src/dmr/Slot.cpp index 7b7099a1..9f838b2b 100644 --- a/src/dmr/Slot.cpp +++ b/src/dmr/Slot.cpp @@ -509,9 +509,6 @@ void Slot::clock() } } } - else { - clearTSCCActivated(); - } } // handle timeouts and hang timers @@ -1429,6 +1426,10 @@ void Slot::writeRF_ControlData(uint16_t frameCnt, uint8_t n) /// void Slot::clearTSCCActivated() { + if (m_tsccPayloadDstId != 0U && m_tsccPayloadSrcId != 0U) { + m_control->writeRF_CSBK_Payload_Clear(m_tsccPayloadDstId, m_tsccPayloadSrcId, m_tsccPayloadGroup); + } + m_tsccPayloadDstId = 0U; m_tsccPayloadSrcId = 0U; m_tsccPayloadGroup = false; diff --git a/src/dmr/lc/CSBK.h b/src/dmr/lc/CSBK.h index e584ead7..fdab303d 100644 --- a/src/dmr/lc/CSBK.h +++ b/src/dmr/lc/CSBK.h @@ -82,7 +82,7 @@ namespace dmr /// DMR access color code. __PROTECTED_PROPERTY(uint8_t, colorCode, ColorCode); - /// Flag indicating this is the last TSBK in a sequence of TSBKs. + /// Flag indicating this is the last CSBK in a sequence of CSBKs. __PROTECTED_PROPERTY(bool, lastBlock, LastBlock); /// Flag indicating whether the CSBK is a Cdef block. __PROTECTED_PROPERTY(bool, Cdef, Cdef); diff --git a/src/dmr/packet/ControlSignaling.cpp b/src/dmr/packet/ControlSignaling.cpp index 50a69815..a53eb86f 100644 --- a/src/dmr/packet/ControlSignaling.cpp +++ b/src/dmr/packet/ControlSignaling.cpp @@ -1367,7 +1367,7 @@ void ControlSignaling::writeRF_CSBK_Grant_LateEntry(uint32_t dstId, uint32_t src } /// -/// Helper to write a payload random access to a TSCC payload channel on the RF interface. +/// Helper to write a payload activation to a TSCC payload channel on the RF interface. /// /// /// @@ -1412,6 +1412,36 @@ void ControlSignaling::writeRF_CSBK_Payload_Activate(uint32_t dstId, uint32_t sr writeRF_CSBK(csbk.get(), false, imm); } +/// +/// Helper to write a payload clear to a TSCC payload channel on the RF interface. +/// +/// +/// +/// +/// +void ControlSignaling::writeRF_CSBK_Payload_Clear(uint32_t dstId, uint32_t srcId, bool grp, bool imm) +{ + std::unique_ptr csbk = new_unique(CSBK_P_CLEAR); + + csbk->setGI(grp); + + csbk->setLastBlock(true); + + csbk->setLogicalCh1(m_slot->m_channelNo); + csbk->setSlotNo(m_slot->m_slotNo); + + csbk->setSrcId(srcId); + csbk->setDstId(dstId); + + if (m_verbose) { + LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, %s, group = %u, chNo = %u, slot = %u, srcId = %u, dstId = %u", + m_slot->m_slotNo, csbk->toString().c_str(), csbk->getGI(), csbk->getLogicalCh1(), csbk->getSlotNo(), srcId, dstId); + } + + for (uint8_t i = 0; i < 2U; i++) + writeRF_CSBK(csbk.get(), false, imm); +} + /// /// Helper to write a TSCC Aloha broadcast packet on the RF interface. /// diff --git a/src/dmr/packet/ControlSignaling.h b/src/dmr/packet/ControlSignaling.h index bd9f1bbc..13c35fb0 100644 --- a/src/dmr/packet/ControlSignaling.h +++ b/src/dmr/packet/ControlSignaling.h @@ -111,8 +111,10 @@ namespace dmr /// Helper to write a TSCC late entry channel grant packet on the RF interface. void writeRF_CSBK_Grant_LateEntry(uint32_t dstId, uint32_t srcId, bool grp); - /// Helper to write a payload random access to a TSCC payload channel on the RF interface. + /// Helper to write a payload activation to a TSCC payload channel on the RF interface. void writeRF_CSBK_Payload_Activate(uint32_t dstId, uint32_t srcId, bool grp, bool voice, bool imm = false); + /// Helper to write a payload clear to a TSCC payload channel on the RF interface. + void writeRF_CSBK_Payload_Clear(uint32_t dstId, uint32_t srcId, bool grp, bool imm = false); /// Helper to write a TSCC Aloha broadcast packet on the RF interface. void writeRF_TSCC_Aloha(); diff --git a/src/dmr/packet/Data.cpp b/src/dmr/packet/Data.cpp index 75834629..c7bdc355 100644 --- a/src/dmr/packet/Data.cpp +++ b/src/dmr/packet/Data.cpp @@ -141,6 +141,7 @@ bool Data::process(uint8_t* data, uint32_t len) if (m_tscc != nullptr) { if (m_tscc->m_enableTSCC) { m_tscc->m_affiliations->releaseGrant(m_slot->m_rfLC->getDstId(), false); + m_slot->clearTSCCActivated(); } } @@ -382,6 +383,15 @@ void Data::processNetwork(const data::Data& dmrData) LogMessage(LOG_RF, DMR_DT_TERMINATOR_WITH_LC ", slot = %u, dstId = %u", m_slot->m_slotNo, m_slot->m_netLC->getDstId()); } + // release trunked grant (if necessary) + Slot *m_tscc = m_slot->m_dmr->getTSCCSlot(); + if (m_tscc != nullptr) { + if (m_tscc->m_enableTSCC) { + m_tscc->m_affiliations->releaseGrant(m_slot->m_rfLC->getDstId(), false); + m_slot->clearTSCCActivated(); + } + } + // We've received the voice header and terminator haven't we? m_slot->m_netFrames += 2U; ::ActivityLog("DMR", false, "Slot %u network end of voice transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%",