diff --git a/src/modem/Modem.cpp b/src/modem/Modem.cpp index bfd60a3a..e5ded669 100644 --- a/src/modem/Modem.cpp +++ b/src/modem/Modem.cpp @@ -1155,7 +1155,16 @@ bool Modem::hasError() const /// void Modem::clearDMRFrame1() { - // TODO -- implement modem side buffer clear + uint8_t buffer[3U]; + + buffer[0U] = DVM_FRAME_START; + buffer[1U] = 3U; + buffer[2U] = CMD_DMR_CLEAR1; +#if DEBUG_MODEM + Utils::dump(1U, "Modem::clearDMRFrame1(), Written", buffer, 3U); +#endif + write(buffer, 3U); + Thread::sleep(5); // 5ms delay } /// @@ -1163,7 +1172,16 @@ void Modem::clearDMRFrame1() /// void Modem::clearDMRFrame2() { - // TODO -- implement modem side buffer clear + uint8_t buffer[3U]; + + buffer[0U] = DVM_FRAME_START; + buffer[1U] = 3U; + buffer[2U] = CMD_DMR_CLEAR2; +#if DEBUG_MODEM + Utils::dump(1U, "Modem::clearDMRFrame2(), Written", buffer, 3U); +#endif + write(buffer, 3U); + Thread::sleep(5); // 5ms delay } /// @@ -1180,6 +1198,7 @@ void Modem::clearP25Frame() Utils::dump(1U, "Modem::clearP25Data(), Written", buffer, 3U); #endif write(buffer, 3U); + Thread::sleep(5); // 5ms delay } /// @@ -1187,7 +1206,16 @@ void Modem::clearP25Frame() /// void Modem::clearNXDNFrame() { - // TODO -- implement modem side buffer clear + uint8_t buffer[3U]; + + buffer[0U] = DVM_FRAME_START; + buffer[1U] = 3U; + buffer[2U] = CMD_NXDN_CLEAR; +#if DEBUG_MODEM + Utils::dump(1U, "Modem::clearNXDNFrame(), Written", buffer, 3U); +#endif + write(buffer, 3U); + Thread::sleep(5); // 5ms delay } /// @@ -2536,6 +2564,10 @@ std::string Modem::cmdToString(uint8_t opcode) return std::string("DMR_ABORT"); case CMD_DMR_CACH_AT_CTRL: return std::string("DMR_CACH_AT_CTRL"); + case CMD_DMR_CLEAR1: + return std::string("DMR_CLEAR1"); + case CMD_DMR_CLEAR2: + return std::string("DMR_CLEAR2"); case CMD_P25_DATA: return std::string("P25_DATA"); @@ -2548,6 +2580,8 @@ std::string Modem::cmdToString(uint8_t opcode) return std::string("NXDN_DATA"); case CMD_NXDN_LOST: return std::string("NXDN_LOST"); + case CMD_NXDN_CLEAR: + return std::string("NXDN_CLEAR"); case CMD_ACK: return std::string("ACK"); diff --git a/src/modem/Modem.h b/src/modem/Modem.h index 39e9d569..ee1c2621 100644 --- a/src/modem/Modem.h +++ b/src/modem/Modem.h @@ -148,6 +148,8 @@ namespace modem CMD_DMR_START = 0x1DU, CMD_DMR_ABORT = 0x1EU, CMD_DMR_CACH_AT_CTRL = 0x1FU, + CMD_DMR_CLEAR1 = 0x20U, + CMD_DMR_CLEAR2 = 0x21U, CMD_P25_DATA = 0x31U, CMD_P25_LOST = 0x32U, @@ -155,6 +157,7 @@ namespace modem CMD_NXDN_DATA = 0x41U, CMD_NXDN_LOST = 0x42U, + CMD_NXDN_CLEAR = 0x43U, CMD_ACK = 0x70U, CMD_NAK = 0x7FU, diff --git a/src/p25/Control.cpp b/src/p25/Control.cpp index f8d810d7..04ec6979 100644 --- a/src/p25/Control.cpp +++ b/src/p25/Control.cpp @@ -127,7 +127,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q m_rfTGHang(1000U, tgHang), m_netTimeout(1000U, timeout), m_networkWatchdog(1000U, 0U, 1500U), - m_ccPacketInterval(1000U, 0U, 5U), + m_ccPacketInterval(1000U, 0U, 10U), m_hangCount(3U * 8U), m_tduPreambleCount(8U), m_ccFrameCnt(0U), @@ -646,6 +646,8 @@ uint32_t Control::getFrame(uint8_t* data) // tx immediate queue takes priority if (!m_txImmQueue.isEmpty()) { + m_modem->clearP25Frame(); + m_txImmQueue.getData(&len, 1U); m_txImmQueue.getData(data, len); } diff --git a/src/p25/lc/tsbk/OSP_QUE_RSP.cpp b/src/p25/lc/tsbk/OSP_QUE_RSP.cpp index b6d427b5..95f9e929 100644 --- a/src/p25/lc/tsbk/OSP_QUE_RSP.cpp +++ b/src/p25/lc/tsbk/OSP_QUE_RSP.cpp @@ -93,7 +93,7 @@ void OSP_QUE_RSP::encode(uint8_t* data, bool rawTSBK, bool noTrellis) } tsbkValue = (m_aivFlag) ? 0x80U : 0x00U; // Additional Info Flag - tsbkValue = (tsbkValue << 6) + m_service; // Service Type + tsbkValue = (tsbkValue << 6) + (m_service & 0x3FU); // Service Type tsbkValue = (tsbkValue << 8) + m_response; // Deny/Queue Reason if (m_group) { diff --git a/src/p25/packet/Trunk.cpp b/src/p25/packet/Trunk.cpp index 473f9378..9549961c 100644 --- a/src/p25/packet/Trunk.cpp +++ b/src/p25/packet/Trunk.cpp @@ -37,6 +37,7 @@ #include "edac/CRC.h" #include "remote/RESTClient.h" #include "Log.h" +#include "Thread.h" #include "Utils.h" using namespace p25; @@ -302,7 +303,7 @@ bool Trunk::process(uint8_t* data, uint32_t len, std::unique_ptr preDe if (iosp->getResponse() == P25_ANS_RSP_PROCEED) { if (m_p25->m_ackTSBKRequests) { - writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_ANS, false, true); + writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_VCH, false, true); } if (m_p25->m_authoritative) { @@ -316,10 +317,12 @@ bool Trunk::process(uint8_t* data, uint32_t len, std::unique_ptr preDe } } else if (iosp->getResponse() == P25_ANS_RSP_DENY) { - writeRF_TSDU_Deny(P25_WUID_FNE, srcId, P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_ANS); + writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_VCH, false, true); + writeRF_TSDU_Deny(P25_WUID_FNE, dstId, P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_VCH); } else if (iosp->getResponse() == P25_ANS_RSP_WAIT) { - writeRF_TSDU_Queue(P25_WUID_FNE, srcId, P25_QUE_RSN_TGT_UNIT_QUEUED, TSBK_IOSP_UU_ANS); + writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_VCH, false, true); + writeRF_TSDU_Queue(P25_WUID_FNE, dstId, P25_QUE_RSN_TGT_UNIT_QUEUED, TSBK_IOSP_UU_VCH, false, false); } } break; @@ -2264,6 +2267,10 @@ bool Trunk::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOp // transmit group grant writeRF_TSDU_SBF_Imm(iosp.get(), net); + if (m_p25->m_voiceOnControl) { + for (int i = 0; i < 3; i++) + writeRF_TSDU_SBF(iosp.get(), net); + } } else { if (!net) { @@ -2314,6 +2321,10 @@ bool Trunk::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOp // transmit private grant writeRF_TSDU_SBF_Imm(iosp.get(), net); + if (m_p25->m_voiceOnControl) { + for (int i = 0; i < 3; i++) + writeRF_TSDU_SBF(iosp.get(), net); + } } } @@ -2603,7 +2614,8 @@ void Trunk::writeRF_TSDU_U_Dereg_Ack(uint32_t srcId) /// /// /// -void Trunk::writeRF_TSDU_Queue(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv) +/// +void Trunk::writeRF_TSDU_Queue(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv, bool grp) { std::unique_ptr osp = new_unique(OSP_QUE_RSP); osp->setAIV(aiv); @@ -2611,6 +2623,7 @@ void Trunk::writeRF_TSDU_Queue(uint32_t srcId, uint32_t dstId, uint8_t reason, u osp->setDstId(dstId); osp->setService(service); osp->setResponse(reason); + osp->setGroup(grp); if (m_verbose) { LogMessage(LOG_RF, P25_TSDU_STR ", %s, AIV = %u, reason = $%02X, srcId = %u, dstId = %u", diff --git a/src/p25/packet/Trunk.h b/src/p25/packet/Trunk.h index 43aad598..2101ae5c 100644 --- a/src/p25/packet/Trunk.h +++ b/src/p25/packet/Trunk.h @@ -208,7 +208,7 @@ namespace p25 /// Helper to write a unit de-registration acknowledge packet. void writeRF_TSDU_U_Dereg_Ack(uint32_t srcId); /// Helper to write a queue packet. - void writeRF_TSDU_Queue(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv = false); + void writeRF_TSDU_Queue(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv = false, bool group = true); /// Helper to write a location registration response packet. bool writeRF_TSDU_Loc_Reg_Rsp(uint32_t srcId, uint32_t dstId, bool grp); diff --git a/src/p25/packet/Voice.cpp b/src/p25/packet/Voice.cpp index 60f49505..022307b9 100644 --- a/src/p25/packet/Voice.cpp +++ b/src/p25/packet/Voice.cpp @@ -389,7 +389,13 @@ bool Voice::process(uint8_t* data, uint32_t len) m_p25->m_rfState = RS_RF_AUDIO; - m_p25->m_rfTGHang.start(); + if (group) { + m_p25->m_rfTGHang.start(); + } + else { + m_p25->m_rfTGHang.stop(); + } + m_p25->m_rfLastDstId = dstId; // make sure we actually got a HDU -- otherwise treat the call as a late entry