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