diff --git a/Defines.h b/Defines.h
index 938d50ae..3a166803 100644
--- a/Defines.h
+++ b/Defines.h
@@ -128,8 +128,6 @@ const uint32_t REMOTE_MODEM_PORT = 3334;
const uint32_t TRAFFIC_DEFAULT_PORT = 62031;
const uint32_t RCON_DEFAULT_PORT = 9990;
-const uint32_t QUEUE_RESIZE_SIZE = 500;
-
const uint8_t BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
enum HOST_STATE {
diff --git a/HostMain.cpp b/HostMain.cpp
index ad23dfaf..cf0c8d65 100644
--- a/HostMain.cpp
+++ b/HostMain.cpp
@@ -73,7 +73,6 @@ bool g_killed = false;
bool g_fireDMRBeacon = false;
bool g_fireP25Control = false;
-bool g_interruptP25Control = false;
// ---------------------------------------------------------------------------
// Global Functions
diff --git a/HostMain.h b/HostMain.h
index 50198a1e..62461119 100644
--- a/HostMain.h
+++ b/HostMain.h
@@ -49,7 +49,6 @@ extern bool g_killed;
extern bool g_fireDMRBeacon;
extern bool g_fireP25Control;
-extern bool g_interruptP25Control;
extern HOST_SW_API void fatal(const char* msg, ...);
diff --git a/RingBuffer.h b/RingBuffer.h
index dd240e85..482532a6 100644
--- a/RingBuffer.h
+++ b/RingBuffer.h
@@ -76,7 +76,7 @@ public:
bool addData(const T* buffer, uint32_t length)
{
if (length >= freeSpace()) {
- LogError(LOG_HOST, "%s buffer overflow, clearing the buffer. (%u >= %u)", m_name, length, freeSpace());
+ LogError(LOG_HOST, "[%s] buffer overflow, clearing the buffer. (%u >= %u)", m_name, length, freeSpace());
clear();
return false;
}
diff --git a/config.example.yml b/config.example.yml
index 41a4a005..ccf04a75 100644
--- a/config.example.yml
+++ b/config.example.yml
@@ -43,7 +43,7 @@ protocols:
callHang: 5
txHang: 8
silenceThreshold: 21
- queueSize: 5000
+ queueSize: 31
verbose: true
debug: false
p25:
@@ -73,7 +73,7 @@ protocols:
sndcpGrant: false
silenceThreshold: 124
disableNetworkHDU: false
- queueSize: 5000
+ queueSize: 12
verbose: true
debug: false
system:
diff --git a/dmr/Control.cpp b/dmr/Control.cpp
index 5bf6df4b..bdfe1e46 100644
--- a/dmr/Control.cpp
+++ b/dmr/Control.cpp
@@ -217,53 +217,44 @@ bool Control::processWakeup(const uint8_t* data)
}
///
-/// Process a data frame for slot 1, from the RF interface.
+/// Process a data frame for slot, from the RF interface.
///
/// DMR data frame buffer.
/// Length of data frame buffer.
/// True, if data frame was processed, otherwise false.
-bool Control::processFrame1(uint8_t *data, uint32_t len)
+bool Control::processFrame(uint32_t slotNo, uint8_t *data, uint32_t len)
{
assert(data != NULL);
- return m_slot1->processFrame(data, len);
-}
-
-///
-/// Get a frame data for slot 1, from data ring buffer.
-///
-/// Buffer to put retrieved DMR data frame data.
-/// Length of data retrieved from DMR ring buffer.
-uint32_t Control::getFrame1(uint8_t* data)
-{
- assert(data != NULL);
-
- return m_slot1->getFrame(data);
-}
-
-///
-/// Process a data frame for slot 2, from the RF interface.
-///
-/// DMR data frame buffer.
-/// Length of data frame buffer.
-/// True, if data frame was processed, otherwise false.
-bool Control::processFrame2(uint8_t *data, uint32_t len)
-{
- assert(data != NULL);
-
- return m_slot2->processFrame(data, len);
+ switch (slotNo) {
+ case 1U:
+ return m_slot1->processFrame(data, len);
+ case 2U:
+ return m_slot2->processFrame(data, len);
+ default:
+ LogError(LOG_NET, "DMR, invalid slot, slotNo = %u", slotNo);
+ return false;
+ }
}
///
-/// Get a frame data for slot 2, from data ring buffer.
+/// Get a data frame for slot, from data ring buffer.
///
/// Buffer to put retrieved DMR data frame data.
/// Length of data retrieved from DMR ring buffer.
-uint32_t Control::getFrame2(uint8_t *data)
+uint32_t Control::getFrame(uint32_t slotNo, uint8_t* data)
{
assert(data != NULL);
- return m_slot2->getFrame(data);
+ switch (slotNo) {
+ case 1U:
+ return m_slot1->getFrame(data);
+ case 2U:
+ return m_slot2->getFrame(data);
+ default:
+ LogError(LOG_NET, "DMR, invalid slot, slotNo = %u", slotNo);
+ return 0U;
+ }
}
///
diff --git a/dmr/Control.h b/dmr/Control.h
index 2c455643..d6c0b18a 100644
--- a/dmr/Control.h
+++ b/dmr/Control.h
@@ -76,14 +76,10 @@ namespace dmr
/// Helper to process wakeup frames from the RF interface.
bool processWakeup(const uint8_t* data);
- /// Process a data frame for slot 1, from the RF interface.
- bool processFrame1(uint8_t* data, uint32_t len);
- /// Get a frame data for slot 1, from data ring buffer.
- uint32_t getFrame1(uint8_t* data);
- /// Process a data frame for slot 2, from the RF interface.
- bool processFrame2(uint8_t* data, uint32_t len);
- /// Get a frame data for slot 2, from data ring buffer.
- uint32_t getFrame2(uint8_t* data);
+ /// Process a data frame for slot, from the RF interface.
+ bool processFrame(uint32_t slotNo, uint8_t* data, uint32_t len);
+ /// Get a data frame for slot, from data ring buffer.
+ uint32_t getFrame(uint32_t slotNo, uint8_t* data);
/// Updates the processor.
void clock();
diff --git a/dmr/ControlPacket.cpp b/dmr/ControlPacket.cpp
index 60ba4f37..7a8a6797 100644
--- a/dmr/ControlPacket.cpp
+++ b/dmr/ControlPacket.cpp
@@ -67,6 +67,7 @@ using namespace dmr;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Process DMR data frame from the RF interface.
///
@@ -135,9 +136,9 @@ bool ControlPacket::process(uint8_t* data, uint32_t len)
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
- m_slot->writeNetworkRF(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_PRIVATE, srcId, dstId);
+ m_slot->writeNetwork(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_PRIVATE, srcId, dstId);
if (m_verbose) {
switch (csbko) {
@@ -283,11 +284,11 @@ void ControlPacket::processNetwork(const data::Data & dmrData)
// Convert the Data Sync to be from the BS or MS as needed
Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
}
}
else
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
if (m_verbose) {
switch (csbko) {
@@ -425,7 +426,7 @@ void ControlPacket::writeRF_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
///
@@ -473,12 +474,13 @@ void ControlPacket::writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId)
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the ControlPacket class.
///
@@ -540,7 +542,7 @@ void ControlPacket::writeRF_TSCC_Aloha()
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
///
@@ -587,7 +589,7 @@ void ControlPacket::writeRF_TSCC_Bcast_Ann_Wd(uint32_t channelNo, bool annWd)
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
///
@@ -628,5 +630,5 @@ void ControlPacket::writeRF_TSCC_Bcast_Sys_Parm()
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
diff --git a/dmr/DataPacket.cpp b/dmr/DataPacket.cpp
index d7c6e0c6..3f11a8ce 100644
--- a/dmr/DataPacket.cpp
+++ b/dmr/DataPacket.cpp
@@ -48,6 +48,7 @@ using namespace dmr;
// ---------------------------------------------------------------------------
// Macros
// ---------------------------------------------------------------------------
+
// Don't process RF frames if the network isn't in a idle state.
#define CHECK_TRAFFIC_COLLISION(_DST_ID) \
if (m_slot->m_netState != RS_NET_IDLE && _DST_ID == m_slot->m_netLastDstId) { \
@@ -65,6 +66,7 @@ using namespace dmr;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Process DMR data frame from the RF interface.
///
@@ -100,11 +102,11 @@ bool DataPacket::process(uint8_t* data, uint32_t len)
data[0U] = modem::TAG_EOT;
data[1U] = 0x00U;
- m_slot->writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
+ m_slot->writeNetwork(data, DT_TERMINATOR_WITH_LC);
if (m_slot->m_duplex) {
for (uint32_t i = 0U; i < m_slot->m_hangCount; i++)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
}
@@ -184,9 +186,9 @@ bool DataPacket::process(uint8_t* data, uint32_t len)
data[1U] = 0x00U;
if (m_slot->m_duplex && m_repeatDataPacket)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
- m_slot->writeNetworkRF(data, DT_DATA_HEADER);
+ m_slot->writeNetwork(data, DT_DATA_HEADER);
m_slot->m_rfState = RS_RF_DATA;
m_slot->m_rfLastDstId = dstId;
@@ -263,10 +265,10 @@ bool DataPacket::process(uint8_t* data, uint32_t len)
// convert the Data Sync to be from the BS or MS as needed
Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
- m_slot->writeNetworkRF(data, dataType);
+ m_slot->writeNetwork(data, dataType);
if (m_slot->m_duplex && m_repeatDataPacket) {
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
if (m_slot->m_rfFrames == 0U) {
@@ -330,11 +332,11 @@ void DataPacket::processNetwork(const data::Data& dmrData)
if (m_slot->m_duplex) {
for (uint32_t i = 0U; i < m_slot->m_hangCount; i++)
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
}
else {
for (uint32_t i = 0U; i < 3U; i++)
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
}
}
@@ -387,10 +389,10 @@ void DataPacket::processNetwork(const data::Data& dmrData)
data[1U] = 0x00U;
// Put a small delay into starting transmission
- m_slot->writeQueueNet(m_slot->m_idle);
- m_slot->writeQueueNet(m_slot->m_idle);
+ m_slot->addFrame(m_slot->m_idle, true);
+ m_slot->addFrame(m_slot->m_idle, true);
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
m_slot->m_netState = RS_NET_DATA;
m_slot->m_netLastDstId = dstId;
@@ -469,7 +471,7 @@ void DataPacket::processNetwork(const data::Data& dmrData)
data[0U] = m_slot->m_netFrames == 0U ? modem::TAG_EOT : modem::TAG_DATA;
data[1U] = 0x00U;
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
if (m_verbose) {
if (dataType == DT_RATE_12_DATA) {
@@ -502,6 +504,7 @@ void DataPacket::processNetwork(const data::Data& dmrData)
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the DataPacket class.
///
diff --git a/dmr/Slot.cpp b/dmr/Slot.cpp
index d5405a41..aa0ec85e 100644
--- a/dmr/Slot.cpp
+++ b/dmr/Slot.cpp
@@ -93,6 +93,7 @@ uint16_t Slot::m_tsccCnt = 0U;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the Slot class.
///
@@ -108,7 +109,7 @@ uint16_t Slot::m_tsccCnt = 0U;
Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSize, bool dumpDataPacket, bool repeatDataPacket,
bool dumpCSBKData, bool debug, bool verbose) :
m_slotNo(slotNo),
- m_queue(queueSize, "DMR Slot"),
+ m_queue(queueSize, "DMR Slot Frame"),
m_rfState(RS_RF_LISTENING),
m_rfLastDstId(0U),
m_netState(RS_NET_IDLE),
@@ -621,49 +622,34 @@ void Slot::setSiteData(uint32_t netId, uint8_t siteId, uint8_t channelId, uint32
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
+
///
-/// Write data processed from RF to the data ring buffer.
+/// Add data frame to the data ring buffer.
///
///
-void Slot::writeQueueRF(const uint8_t *data)
+///
+void Slot::addFrame(const uint8_t *data, bool net)
{
assert(data != NULL);
- if (m_netState != RS_NET_IDLE)
- return;
-
- uint8_t len = DMR_FRAME_LENGTH_BYTES + 2U;
-
- uint32_t space = m_queue.freeSpace();
- if (space < (len + 1U)) {
- uint32_t queueLen = m_queue.length();
- m_queue.resize(queueLen + QUEUE_RESIZE_SIZE);
- LogError(LOG_DMR, "Slot %u, overflow in the DMR slot queue; queue free is %u, needed %u; resized was %u is %u", m_slotNo, space, len, queueLen, m_queue.length());
- return;
- }
-
- if (m_debug) {
- Utils::symbols("!!! *Tx DMR", data + 2U, len - 2U);
+ if (!net) {
+ if (m_netState != RS_NET_IDLE)
+ return;
}
- m_queue.addData(&len, 1U);
- m_queue.addData(data, len);
-}
-
-///
-/// Write data processed from the network to the data ring buffer.
-///
-///
-void Slot::writeQueueNet(const uint8_t *data)
-{
- assert(data != NULL);
-
uint8_t len = DMR_FRAME_LENGTH_BYTES + 2U;
-
uint32_t space = m_queue.freeSpace();
if (space < (len + 1U)) {
- LogError(LOG_DMR, "Slot %u, overflow in the DMR slot queue while writing network data; queue free is %u, needed %u", m_slotNo, space, len);
- return;
+ if (!net) {
+ uint32_t queueLen = m_queue.length();
+ m_queue.resize(queueLen + (DMR_FRAME_LENGTH_BYTES + 2U));
+ LogError(LOG_DMR, "Slot %u, overflow in the DMR slot queue; queue free is %u, needed %u; resized was %u is %u", m_slotNo, space, len, queueLen, m_queue.length());
+ return;
+ }
+ else {
+ LogError(LOG_DMR, "Slot %u, overflow in the DMR slot queue while writing network data; queue free is %u, needed %u", m_slotNo, space, len);
+ return;
+ }
}
if (m_debug) {
@@ -675,21 +661,21 @@ void Slot::writeQueueNet(const uint8_t *data)
}
///
-/// Write data processed from RF to the network.
+/// Write data frame to the network.
///
///
///
///
-void Slot::writeNetworkRF(const uint8_t* data, uint8_t dataType, uint8_t errors)
+void Slot::writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t errors)
{
assert(data != NULL);
assert(m_rfLC != NULL);
- writeNetworkRF(data, dataType, m_rfLC->getFLCO(), m_rfLC->getSrcId(), m_rfLC->getDstId(), errors);
+ writeNetwork(data, dataType, m_rfLC->getFLCO(), m_rfLC->getSrcId(), m_rfLC->getDstId(), errors);
}
///
-/// Write data processed from RF to the network.
+/// Write data frame to the network.
///
///
///
@@ -697,7 +683,7 @@ void Slot::writeNetworkRF(const uint8_t* data, uint8_t dataType, uint8_t errors)
///
///
///
-void Slot::writeNetworkRF(const uint8_t* data, uint8_t dataType, uint8_t flco, uint32_t srcId,
+void Slot::writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t flco, uint32_t srcId,
uint32_t dstId, uint8_t errors)
{
assert(data != NULL);
@@ -760,7 +746,7 @@ void Slot::writeEndRF(bool writeEnd)
data[1U] = 0x00U;
for (uint32_t i = 0U; i < m_hangCount; i++)
- writeQueueRF(data);
+ addFrame(data);
}
}
@@ -818,11 +804,11 @@ void Slot::writeEndNet(bool writeEnd)
if (m_duplex) {
for (uint32_t i = 0U; i < m_hangCount; i++)
- writeQueueNet(data);
+ addFrame(data, true);
}
else {
for (uint32_t i = 0U; i < 3U; i++)
- writeQueueNet(data);
+ addFrame(data, true);
}
}
diff --git a/dmr/Slot.h b/dmr/Slot.h
index eb15385d..f47f127b 100644
--- a/dmr/Slot.h
+++ b/dmr/Slot.h
@@ -54,6 +54,7 @@ namespace dmr
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
+
class HOST_SW_API VoicePacket;
class HOST_SW_API DataPacket;
class HOST_SW_API ControlPacket;
@@ -76,7 +77,7 @@ namespace dmr
/// Process a data frame from the RF interface.
bool processFrame(uint8_t* data, uint32_t len);
- /// Get frame data from data ring buffer.
+ /// Get data frame from data ring buffer.
uint32_t getFrame(uint8_t* data);
/// Process a data frames from the network.
@@ -208,14 +209,13 @@ namespace dmr
static uint16_t m_tsccCnt;
- /// Write data processed from RF to the data ring buffer.
- void writeQueueRF(const uint8_t* data);
- /// Write data processed from the network to the data ring buffer.
- void writeQueueNet(const uint8_t* data);
- /// Write data processed from RF to the network.
- void writeNetworkRF(const uint8_t* data, uint8_t dataType, uint8_t errors = 0U);
- /// Write data processed from RF to the network.
- void writeNetworkRF(const uint8_t* data, uint8_t dataType, uint8_t flco, uint32_t srcId,
+ /// Add data frame to the data ring buffer.
+ void addFrame(const uint8_t* data, bool net = false);
+
+ /// Write data frame to the network.
+ void writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t errors = 0U);
+ /// Write data frame to the network.
+ void writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t flco, uint32_t srcId,
uint32_t dstId, uint8_t errors = 0U);
/// Helper to write RF end of frame data.
diff --git a/dmr/VoicePacket.cpp b/dmr/VoicePacket.cpp
index fb2bc526..c0912293 100644
--- a/dmr/VoicePacket.cpp
+++ b/dmr/VoicePacket.cpp
@@ -49,6 +49,7 @@ using namespace dmr;
// ---------------------------------------------------------------------------
// Macros
// ---------------------------------------------------------------------------
+
#define CHECK_TRAFFIC_COLLISION_DELLC(_DST_ID) \
if (m_slot->m_netState != RS_NET_IDLE && _DST_ID == m_slot->m_netLastDstId) { \
LogWarning(LOG_RF, "DMR Slot %u, Traffic collision detect, preempting new RF traffic to existing network traffic!", m_slot->m_slotNo); \
@@ -67,6 +68,7 @@ using namespace dmr;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Process DMR voice frame from the RF interface.
///
@@ -183,10 +185,10 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
m_slot->m_modem->writeDMRAbort(m_slot->m_slotNo);
for (uint32_t i = 0U; i < NO_HEADERS_DUPLEX; i++)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
}
- m_slot->writeNetworkRF(data, DT_VOICE_LC_HEADER);
+ m_slot->writeNetwork(data, DT_VOICE_LC_HEADER);
m_slot->m_rfState = RS_RF_AUDIO;
m_slot->m_rfLastDstId = dstId;
@@ -229,9 +231,9 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
- m_slot->writeNetworkRF(data, DT_VOICE_PI_HEADER);
+ m_slot->writeNetwork(data, DT_VOICE_PI_HEADER);
if (m_verbose) {
LogMessage(LOG_RF, DMR_DT_VOICE_PI_HEADER ", slot = %u, algId = %u, kId = %u, dstId = %u", m_slot->m_slotNo, lc->getAlgId(), lc->getKId(), lc->getDstId());
@@ -284,9 +286,9 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
- m_slot->writeNetworkRF(data, DT_VOICE_SYNC, errors);
+ m_slot->writeNetwork(data, DT_VOICE_SYNC, errors);
return true;
}
@@ -438,7 +440,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
data[0U] = modem::TAG_DATA;
data[1U] = 0x00U;
- m_slot->writeNetworkRF(data, DT_VOICE, errors);
+ m_slot->writeNetwork(data, DT_VOICE, errors);
if (m_embeddedLCOnly) {
// Only send the previously received LC
@@ -451,7 +453,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
}
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
return true;
}
@@ -539,10 +541,10 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
m_slot->m_modem->writeDMRAbort(m_slot->m_slotNo);
for (uint32_t i = 0U; i < NO_HEADERS_DUPLEX; i++)
- m_slot->writeQueueRF(start);
+ m_slot->addFrame(start);
}
- m_slot->writeNetworkRF(start, DT_VOICE_LC_HEADER);
+ m_slot->writeNetwork(start, DT_VOICE_LC_HEADER);
m_rfN = data[1U] & 0x0FU;
@@ -589,9 +591,9 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
data[1U] = 0x00U;
if (m_slot->m_duplex)
- m_slot->writeQueueRF(data);
+ m_slot->addFrame(data);
- m_slot->writeNetworkRF(data, DT_VOICE, errors);
+ m_slot->writeNetwork(data, DT_VOICE, errors);
m_slot->m_rfState = RS_RF_AUDIO;
@@ -690,15 +692,15 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
}
for (uint32_t i = 0U; i < m_slot->m_jitterSlots; i++)
- m_slot->writeQueueNet(m_slot->m_idle);
+ m_slot->addFrame(m_slot->m_idle, true);
if (m_slot->m_duplex) {
for (uint32_t i = 0U; i < NO_HEADERS_DUPLEX; i++)
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
}
else {
for (uint32_t i = 0U; i < NO_HEADERS_SIMPLEX; i++)
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
}
m_slot->m_netState = RS_NET_AUDIO;
@@ -734,7 +736,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
}
for (uint32_t i = 0U; i < m_slot->m_jitterSlots; i++)
- m_slot->writeQueueNet(m_slot->m_idle);
+ m_slot->addFrame(m_slot->m_idle, true);
// Create a dummy start frame
uint8_t start[DMR_FRAME_LENGTH_BYTES + 2U];
@@ -754,11 +756,11 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
if (m_slot->m_duplex) {
for (uint32_t i = 0U; i < NO_HEADERS_DUPLEX; i++)
- m_slot->writeQueueRF(start);
+ m_slot->addFrame(start);
}
else {
for (uint32_t i = 0U; i < NO_HEADERS_SIMPLEX; i++)
- m_slot->writeQueueRF(start);
+ m_slot->addFrame(start);
}
m_slot->m_netFrames = 0U;
@@ -800,7 +802,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
data[0U] = modem::TAG_DATA;
data[1U] = 0x00U;
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
if (m_verbose) {
LogMessage(LOG_NET, DMR_DT_VOICE_PI_HEADER ", slot = %u, algId = %u, kId = %u, dstId = %u", m_slot->m_slotNo, lc->getAlgId(), lc->getKId(), lc->getDstId());
@@ -831,7 +833,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
}
for (uint32_t i = 0U; i < m_slot->m_jitterSlots; i++)
- m_slot->writeQueueNet(m_slot->m_idle);
+ m_slot->addFrame(m_slot->m_idle, true);
// Create a dummy start frame
uint8_t start[DMR_FRAME_LENGTH_BYTES + 2U];
@@ -851,11 +853,11 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
if (m_slot->m_duplex) {
for (uint32_t i = 0U; i < NO_HEADERS_DUPLEX; i++)
- m_slot->writeQueueRF(start);
+ m_slot->addFrame(start);
}
else {
for (uint32_t i = 0U; i < NO_HEADERS_SIMPLEX; i++)
- m_slot->writeQueueRF(start);
+ m_slot->addFrame(start);
}
m_slot->m_netFrames = 0U;
@@ -902,7 +904,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
}
if (!m_slot->m_netTimeout)
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
m_netEmbeddedReadN = (m_netEmbeddedReadN + 1U) % 2U;
m_netEmbeddedWriteN = (m_netEmbeddedWriteN + 1U) % 2U;
@@ -1035,7 +1037,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
if (insertSilence(data, dmrData.getN())) {
if (!m_slot->m_netTimeout)
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
}
m_slot->m_packetTimer.start();
@@ -1055,6 +1057,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the VoicePacket class.
///
@@ -1255,7 +1258,7 @@ void VoicePacket::insertSilence(uint32_t count)
emb.encode(data + 2U);
}
- m_slot->writeQueueNet(data);
+ m_slot->addFrame(data, true);
m_netN = n;
diff --git a/host/Host.cpp b/host/Host.cpp
index e79c28bc..f62cf593 100644
--- a/host/Host.cpp
+++ b/host/Host.cpp
@@ -95,8 +95,6 @@ Host::Host(const std::string& confFile) :
m_cwIdTimer(1000U),
m_dmrEnabled(false),
m_p25Enabled(false),
- m_p25CtrlChannel(false),
- m_dmrCtrlChannel(false),
m_duplex(false),
m_fixedMode(false),
m_timeout(180U),
@@ -120,7 +118,10 @@ Host::Host(const std::string& confFile) :
m_tidLookup(NULL),
m_dmrBeacons(false),
m_dmrTSCCData(false),
- m_controlData(false),
+ m_dmrCtrlChannel(false),
+ m_p25CCData(false),
+ m_p25CtrlChannel(false),
+ m_p25CtrlBroadcast(false),
m_remoteControl(NULL)
{
UDPSocket::startup();
@@ -357,10 +358,25 @@ int Host::run()
bool dumpTAData = dmrProtocol["dumpTAData"].as(true);
uint32_t callHang = dmrProtocol["callHang"].as(3U);
uint32_t txHang = dmrProtocol["txHang"].as(4U);
- uint32_t dmrQueueSize = dmrProtocol["queueSize"].as(5120U);
+ uint32_t queueSize = dmrProtocol["queueSize"].as(31U);
bool dmrVerbose = dmrProtocol["verbose"].as(true);
bool dmrDebug = dmrProtocol["debug"].as(false);
+ // clamp queue size to no less then 24 and no greater the 100
+ if (queueSize <= 24U) {
+ LogWarning(LOG_HOST, "DMR queue size must be greater then 24 frames, defaulting to 24 frames!");
+ queueSize = 24U;
+ }
+ if (queueSize > 100U) {
+ LogWarning(LOG_HOST, "DMR queue size must be less then 100 frames, defaulting to 100 frames!");
+ queueSize = 100U;
+ }
+ if (queueSize > 60U) {
+ LogWarning(LOG_HOST, "DMR queue size is excessive, >60 frames!");
+ }
+
+ uint32_t queueSizeBytes = queueSize * (dmr::DMR_FRAME_LENGTH_BYTES * 5U);
+
uint32_t jitter = m_conf["network"]["jitter"].as(360U);
if (txHang > m_rfModeHang)
@@ -378,7 +394,7 @@ int Host::run()
LogInfo(" Dump CSBK Data: %s", dmrDumpCsbkData ? "yes" : "no");
LogInfo(" Call Hang: %us", callHang);
LogInfo(" TX Hang: %us", txHang);
- LogInfo(" Queue Size: %u", dmrQueueSize);
+ LogInfo(" Queue Size: %u (%u bytes)", queueSize, queueSizeBytes);
LogInfo(" Roaming Beacons: %s", m_dmrBeacons ? "yes" : "no");
if (m_dmrBeacons) {
@@ -403,13 +419,19 @@ int Host::run()
if (dmrCtrlChannel) {
m_dmrCtrlChannel = dmrCtrlChannel;
}
+
+ g_fireDMRBeacon = true;
}
- dmr = new dmr::Control(m_dmrColorCode, callHang, dmrQueueSize, embeddedLCOnly, dumpTAData, m_timeout, m_rfTalkgroupHang,
+ dmr = new dmr::Control(m_dmrColorCode, callHang, queueSizeBytes, embeddedLCOnly, dumpTAData, m_timeout, m_rfTalkgroupHang,
m_modem, m_network, m_duplex, m_ridLookup, m_tidLookup, m_idenTable, rssi, jitter, dmrDumpDataPacket, dmrRepeatDataPacket,
dmrDumpCsbkData, dmrDebug, dmrVerbose);
dmr->setOptions(m_conf, m_dmrNetId, m_siteId, m_channelId, m_channelNo, true);
+ if (dmrCtrlChannel) {
+ dmr->setCCRunning(true);
+ }
+
m_dmrTXTimer.setTimeout(txHang);
if (dmrVerbose) {
@@ -421,8 +443,8 @@ int Host::run()
}
// initialize P25
- Timer p25CCIntervalTimer(1000U);
- Timer p25CCDurationTimer(1000U);
+ Timer p25BcastIntervalTimer(1000U);
+ Timer p25BcastDurationTimer(1000U);
p25::Control* p25 = NULL;
LogInfo("P25 Parameters");
@@ -430,34 +452,47 @@ int Host::run()
if (m_p25Enabled) {
yaml::Node p25Protocol = protocolConf["p25"];
uint32_t tduPreambleCount = p25Protocol["tduPreambleCount"].as(8U);
- m_controlData = p25Protocol["control"]["enable"].as(false);
+ m_p25CCData = p25Protocol["control"]["enable"].as(false);
bool p25CtrlChannel = p25Protocol["control"]["dedicated"].as(false);
bool p25CtrlBroadcast = p25Protocol["control"]["broadcast"].as(true);
bool p25DumpDataPacket = p25Protocol["dumpDataPacket"].as(false);
bool p25RepeatDataPacket = p25Protocol["repeatDataPacket"].as(true);
bool p25DumpTsbkData = p25Protocol["dumpTsbkData"].as(false);
uint32_t callHang = p25Protocol["callHang"].as(3U);
- uint32_t p25QueueSize = p25Protocol["queueSize"].as(8192U);
+ uint16_t queueSize = p25Protocol["queueSize"].as(12U);
bool p25Verbose = p25Protocol["verbose"].as(true);
bool p25Debug = p25Protocol["debug"].as(false);
+ // clamp queue size to no less then 5 and no greater the 100 frames
+ if (queueSize <= 10U) {
+ LogWarning(LOG_HOST, "P25 queue size must be greater then 10 frames, defaulting to 10 frames!");
+ queueSize = 10U;
+ }
+ if (queueSize > 100U) {
+ LogWarning(LOG_HOST, "P25 queue size must be less then 100 frames, defaulting to 100 frames!");
+ queueSize = 100U;
+ }
+ if (queueSize > 30U) {
+ LogWarning(LOG_HOST, "P25 queue size is excessive, >30 frames!");
+ }
+
+ uint32_t queueSizeBytes = queueSize * p25::P25_LDU_FRAME_LENGTH_BYTES;
+
LogInfo(" TDU Preamble before Voice: %u", tduPreambleCount);
LogInfo(" Dump Packet Data: %s", p25DumpDataPacket ? "yes" : "no");
LogInfo(" Repeat Packet Data: %s", p25RepeatDataPacket ? "yes" : "no");
LogInfo(" Dump TSBK Data: %s", p25DumpTsbkData ? "yes" : "no");
LogInfo(" Call Hang: %us", callHang);
- LogInfo(" Queue Size: %u", p25QueueSize);
+ LogInfo(" Queue Size: %u (%u bytes)", queueSize, queueSizeBytes);
- LogInfo(" Control: %s", m_controlData ? "yes" : "no");
+ LogInfo(" Control: %s", m_p25CCData ? "yes" : "no");
uint32_t p25ControlBcstInterval = p25Protocol["control"]["interval"].as(300U);
uint32_t p25ControlBcstDuration = p25Protocol["control"]["duration"].as(1U);
- if (m_controlData) {
+ if (m_p25CCData) {
LogInfo(" Control Broadcast: %s", p25CtrlBroadcast ? "yes" : "no");
LogInfo(" Control Channel: %s", p25CtrlChannel ? "yes" : "no");
if (p25CtrlChannel) {
- p25ControlBcstInterval = 30U;
- p25ControlBcstDuration = 120U;
m_p25CtrlChannel = p25CtrlChannel;
}
else {
@@ -465,28 +500,27 @@ int Host::run()
LogInfo(" Control Broadcast Duration: %us", p25ControlBcstDuration);
}
- m_p25CtrlBroadcast = p25CtrlBroadcast;
- p25CCIntervalTimer.setTimeout(p25ControlBcstInterval);
- p25CCIntervalTimer.start();
+ p25BcastDurationTimer.setTimeout(p25ControlBcstDuration);
- p25CCDurationTimer.setTimeout(p25ControlBcstDuration);
+ p25BcastIntervalTimer.setTimeout(p25ControlBcstInterval);
+ p25BcastIntervalTimer.start();
+ m_p25CtrlBroadcast = p25CtrlBroadcast;
if (p25CtrlBroadcast) {
g_fireP25Control = true;
- g_interruptP25Control = false;
- }
- else {
- g_fireP25Control = false;
- g_interruptP25Control = false;
}
}
- p25 = new p25::Control(m_p25NAC, callHang, p25QueueSize, m_modem, m_network, m_timeout, m_rfTalkgroupHang,
- p25ControlBcstInterval, m_duplex, m_ridLookup, m_tidLookup, m_idenTable, rssi, p25DumpDataPacket, p25RepeatDataPacket,
+ p25 = new p25::Control(m_p25NAC, callHang, queueSizeBytes, m_modem, m_network, m_timeout, m_rfTalkgroupHang,
+ m_duplex, m_ridLookup, m_tidLookup, m_idenTable, rssi, p25DumpDataPacket, p25RepeatDataPacket,
p25DumpTsbkData, p25Debug, p25Verbose);
p25->setOptions(m_conf, m_cwCallsign, m_voiceChNo, m_p25PatchSuperGroup, m_p25NetId, m_p25SysId, m_p25RfssId,
m_siteId, m_channelId, m_channelNo, true);
+ if (p25CtrlChannel) {
+ p25->setCCRunning(true);
+ }
+
if (p25Verbose) {
LogInfo(" Verbose: yes");
}
@@ -513,7 +547,7 @@ int Host::run()
}
#endif
- // P25 control channel checks
+ // P25 CC checks
if (m_dmrEnabled && m_p25CtrlChannel) {
::LogError(LOG_HOST, "Cannot have DMR enabled when using dedicated P25 control!");
g_killed = true;
@@ -523,7 +557,7 @@ int Host::run()
::LogWarning(LOG_HOST, "Fixed mode should be enabled when using dedicated P25 control!");
}
- if (!m_duplex && m_controlData) {
+ if (!m_duplex && m_p25CCData) {
::LogError(LOG_HOST, "Cannot have P25 control and simplex mode at the same time.");
g_killed = true;
}
@@ -544,7 +578,7 @@ int Host::run()
}
// DMR beacon checks
- if (m_dmrBeacons && m_controlData) {
+ if (m_dmrBeacons && m_p25CCData) {
::LogError(LOG_HOST, "Cannot have DMR roaming becaons and P25 control at the same time.");
g_killed = true;
}
@@ -618,13 +652,9 @@ int Host::run()
// Macro to interrupt a running P25 control channel transmission
#define INTERRUPT_P25_CONTROL \
if (p25 != NULL) { \
- if (g_interruptP25Control) { \
- p25CCDurationTimer.stop(); \
- if (p25CCDurationTimer.isRunning() && !p25CCDurationTimer.hasExpired()) { \
- LogDebug(LOG_HOST, "traffic interrupts P25 CC, g_interruptP25Control = %u", g_interruptP25Control); \
- m_modem->clearP25Data(); \
- p25->reset(); \
- } \
+ p25->setCCHalted(true); \
+ if (p25BcastDurationTimer.isRunning() && !p25BcastDurationTimer.isPaused()) { \
+ p25BcastDurationTimer.pause(); \
} \
}
@@ -695,33 +725,37 @@ int Host::run()
// to the modem
ret = m_modem->hasDMRSpace1();
if (ret) {
- len = dmr->getFrame1(data);
+ len = dmr->getFrame(1U, data);
if (len > 0U) {
+ // if the state is idle; set to DMR, start mode timer and start DMR idle frames
if (m_state == STATE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang);
setState(STATE_DMR);
START_DMR_DUPLEX_IDLE(true);
}
+
+ // if the state is DMR; start DMR idle frames and write DMR slot 1 data
if (m_state == STATE_DMR) {
START_DMR_DUPLEX_IDLE(true);
m_modem->writeDMRData1(data, len);
+ // if there is no DMR CC running; run the interrupt macro to stop
+ // any running DMR beacon
if (!dmr->getCCRunning()) {
INTERRUPT_DMR_BEACON;
}
- if (g_interruptP25Control && p25CCDurationTimer.isRunning()) {
- p25CCDurationTimer.pause();
+ // if there is a P25 CC running; halt the CC
+ if (p25 != NULL) {
+ if (p25->getCCRunning() && !p25->getCCHalted()) {
+ p25->setCCHalted(true);
+ INTERRUPT_P25_CONTROL;
+ }
}
m_modeTimer.start();
}
-/*
- else if (m_state != HOST_STATE_LOCKOUT) {
- LogWarning(LOG_HOST, "DMR data received, state = %u", m_state);
- }
-*/
}
}
@@ -730,33 +764,35 @@ int Host::run()
// to the modem
ret = m_modem->hasDMRSpace2();
if (ret) {
- len = dmr->getFrame2(data);
+ len = dmr->getFrame(2U, data);
if (len > 0U) {
+ // if the state is idle; set to DMR, start mode timer and start DMR idle frames
if (m_state == STATE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang);
setState(STATE_DMR);
START_DMR_DUPLEX_IDLE(true);
}
+
+ // if the state is DMR; start DMR idle frames and write DMR slot 2 data
if (m_state == STATE_DMR) {
START_DMR_DUPLEX_IDLE(true);
m_modem->writeDMRData2(data, len);
+ // if there is no DMR CC running; run the interrupt macro to stop
+ // any running DMR beacon
if (!dmr->getCCRunning()) {
INTERRUPT_DMR_BEACON;
}
- if (g_interruptP25Control && p25CCDurationTimer.isRunning()) {
- p25CCDurationTimer.pause();
+ // if there is a P25 CC running; halt the CC
+ if (p25->getCCRunning() && !p25->getCCHalted()) {
+ p25->setCCHalted(true);
+ INTERRUPT_P25_CONTROL;
}
m_modeTimer.start();
}
-/*
- else if (m_state != HOST_STATE_LOCKOUT) {
- LogWarning(LOG_HOST, "DMR data received, state = %u", m_state);
- }
-*/
}
}
}
@@ -770,38 +806,31 @@ int Host::run()
if (ret) {
len = p25->getFrame(data);
if (len > 0U) {
+ // if the state is idle; set to P25 and start mode timer
if (m_state == STATE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang);
setState(STATE_P25);
}
+ // if the state is P25; write P25 data
if (m_state == STATE_P25) {
m_modem->writeP25Data(data, len);
-
+
INTERRUPT_DMR_BEACON;
-
- if (g_interruptP25Control && p25CCDurationTimer.isRunning()) {
- p25CCDurationTimer.pause();
- }
-
+
m_modeTimer.start();
}
-/*
- else if (m_state != HOST_STATE_LOCKOUT) {
- LogWarning(LOG_HOST, "P25 data received, state = %u", m_state);
- }
-*/
}
else {
+ // if we have no P25 data, and we're either idle or P25 state, check if we
+ // need to be starting the CC running flag or writing end of voice call data
if (m_state == STATE_IDLE || m_state == STATE_P25) {
- // P25 control data, if control data is being transmitted
- if (p25CCDurationTimer.isRunning() && !p25CCDurationTimer.hasExpired()) {
- p25->setCCRunning(true);
- p25->writeControlRF();
+ if (p25->getCCHalted()) {
+ p25->setCCHalted(false);
}
- // P25 status data, tail on idle
- ret = p25->writeEndRF();
+ // write end of voice if necessary
+ ret = p25->writeRF_VoiceEnd();
if (ret) {
if (m_state == STATE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang);
@@ -817,13 +846,12 @@ int Host::run()
// if the modem is in duplex -- handle P25 CC burst control
if (m_duplex) {
- if (p25CCDurationTimer.isPaused() && !g_interruptP25Control) {
- LogDebug(LOG_HOST, "traffic complete, resume P25 CC, g_interruptP25Control = %u", g_interruptP25Control);
- p25CCDurationTimer.resume();
+ if (p25BcastDurationTimer.isPaused() && !p25->getCCHalted()) {
+ p25BcastDurationTimer.resume();
}
- if (g_interruptP25Control) {
- g_fireP25Control = true;
+ if (p25->getCCHalted()) {
+ p25->setCCHalted(false);
}
if (g_fireP25Control) {
@@ -859,8 +887,9 @@ int Host::run()
if (ret) {
m_modeTimer.setTimeout(m_rfModeHang);
setState(STATE_DMR);
+
START_DMR_DUPLEX_IDLE(true);
-
+
INTERRUPT_DMR_BEACON;
INTERRUPT_P25_CONTROL;
}
@@ -871,10 +900,10 @@ int Host::run()
setState(STATE_DMR);
START_DMR_DUPLEX_IDLE(true);
- dmr->processFrame1(data, len);
+ dmr->processFrame(1U, data, len);
INTERRUPT_DMR_BEACON;
- p25CCDurationTimer.stop();
+ p25BcastDurationTimer.stop();
}
}
else if (m_state == STATE_DMR) {
@@ -889,7 +918,7 @@ int Host::run()
}
else {
// process slot 1 frames
- bool ret = dmr->processFrame1(data, len);
+ bool ret = dmr->processFrame(1U, data, len);
if (ret) {
INTERRUPT_DMR_BEACON;
INTERRUPT_P25_CONTROL;
@@ -928,7 +957,7 @@ int Host::run()
setState(STATE_DMR);
START_DMR_DUPLEX_IDLE(true);
- dmr->processFrame2(data, len);
+ dmr->processFrame(2U, data, len);
INTERRUPT_DMR_BEACON;
INTERRUPT_P25_CONTROL;
@@ -946,7 +975,7 @@ int Host::run()
}
else {
// process slot 2 frames
- bool ret = dmr->processFrame2(data, len);
+ bool ret = dmr->processFrame(2U, data, len);
if (ret) {
INTERRUPT_DMR_BEACON;
INTERRUPT_P25_CONTROL;
@@ -970,6 +999,7 @@ int Host::run()
len = m_modem->readP25Data(data);
if (len > 0U) {
if (m_state == STATE_IDLE) {
+ // process P25 frames
bool ret = p25->processFrame(data, len);
if (ret) {
m_modeTimer.setTimeout(m_rfModeHang);
@@ -979,7 +1009,7 @@ int Host::run()
INTERRUPT_P25_CONTROL;
}
else {
- ret = p25->writeEndRF();
+ ret = p25->writeRF_VoiceEnd();
if (ret) {
INTERRUPT_DMR_BEACON;
@@ -994,13 +1024,12 @@ int Host::run()
// if the modem is in duplex -- handle P25 CC burst control
if (m_duplex) {
- if (p25CCDurationTimer.isPaused() && !g_interruptP25Control) {
- LogDebug(LOG_HOST, "traffic complete, resume P25 CC, g_interruptP25Control = %u", g_interruptP25Control);
- p25CCDurationTimer.resume();
+ if (p25BcastDurationTimer.isPaused() && !p25->getCCHalted()) {
+ p25BcastDurationTimer.resume();
}
- if (g_interruptP25Control) {
- g_fireP25Control = true;
+ if (p25->getCCHalted()) {
+ p25->setCCHalted(false);
}
if (g_fireP25Control) {
@@ -1008,20 +1037,20 @@ int Host::run()
}
}
else {
- p25CCDurationTimer.stop();
- g_interruptP25Control = false;
+ p25BcastDurationTimer.stop();
}
}
}
}
else if (m_state == STATE_P25) {
+ // process P25 frames
bool ret = p25->processFrame(data, len);
if (ret) {
m_modeTimer.start();
INTERRUPT_P25_CONTROL;
}
else {
- ret = p25->writeEndRF();
+ ret = p25->writeRF_VoiceEnd();
if (ret) {
m_modeTimer.start();
}
@@ -1061,11 +1090,11 @@ int Host::run()
m_cwIdTimer.clock(ms);
if (m_cwIdTimer.isRunning() && m_cwIdTimer.hasExpired()) {
if (!m_modem->hasTX() && !m_p25CtrlChannel && !m_dmrCtrlChannel) {
- if (dmrBeaconDurationTimer.isRunning() || p25CCDurationTimer.isRunning()) {
+ if (dmrBeaconDurationTimer.isRunning() || p25BcastDurationTimer.isRunning()) {
LogDebug(LOG_HOST, "CW, beacon or CC timer running, ceasing");
dmrBeaconDurationTimer.stop();
- p25CCDurationTimer.stop();
+ p25BcastDurationTimer.stop();
}
LogDebug(LOG_HOST, "CW, start transmitting");
@@ -1135,7 +1164,12 @@ int Host::run()
}
g_fireDMRBeacon = false;
- LogDebug(LOG_HOST, "DMR, roaming beacon burst");
+ if (m_dmrTSCCData) {
+ LogDebug(LOG_HOST, "DMR, start CC broadcast");
+ }
+ else {
+ LogDebug(LOG_HOST, "DMR, roaming beacon burst");
+ }
dmrBeaconIntervalTimer.start();
dmrBeaconDurationTimer.start();
}
@@ -1168,11 +1202,12 @@ int Host::run()
/** P25 */
if (p25 != NULL) {
- if (m_controlData) {
- p25CCIntervalTimer.clock(ms);
+ if (m_p25CCData) {
+ p25BcastIntervalTimer.clock(ms);
- if (m_p25CtrlBroadcast) {
- if ((p25CCIntervalTimer.isRunning() && p25CCIntervalTimer.hasExpired()) || g_fireP25Control) {
+ if (!m_p25CtrlChannel && m_p25CtrlBroadcast) {
+ // clock and check P25 CC broadcast interval timer
+ if ((p25BcastIntervalTimer.isRunning() && p25BcastIntervalTimer.hasExpired()) || g_fireP25Control) {
if ((m_state == STATE_IDLE || m_state == STATE_P25) && !m_modem->hasTX()) {
if (m_modeTimer.isRunning()) {
m_modeTimer.stop();
@@ -1181,11 +1216,6 @@ int Host::run()
if (m_state != STATE_P25)
setState(STATE_P25);
- if (g_interruptP25Control) {
- g_interruptP25Control = false;
- LogDebug(LOG_HOST, "traffic complete, restart P25 CC broadcast, g_interruptP25Control = %u", g_interruptP25Control);
- }
-
p25->writeAdjSSNetwork();
p25->setCCRunning(true);
@@ -1195,45 +1225,40 @@ int Host::run()
}
g_fireP25Control = false;
- p25CCIntervalTimer.start();
- p25CCDurationTimer.start();
+ p25BcastIntervalTimer.start();
+ p25BcastDurationTimer.start();
// if the CC is continuous -- clock one cycle into the duration timer
if (m_p25CtrlChannel) {
- p25CCDurationTimer.clock(ms);
+ p25BcastDurationTimer.clock(ms);
}
}
}
- // if the CC is continuous -- we don't clock the CC duration timer (which results in the CC
- // broadcast running infinitely until stopped)
- if (!m_p25CtrlChannel) {
- // clock and check P25 CC duration timer
- p25CCDurationTimer.clock(ms);
- if (p25CCDurationTimer.isRunning() && p25CCDurationTimer.hasExpired()) {
- p25CCDurationTimer.stop();
+ if (p25BcastDurationTimer.isPaused()) {
+ p25BcastDurationTimer.resume();
+ }
- p25->writeControlEndRF();
- p25->setCCRunning(false);
+ // clock and check P25 CC broadcast duration timer
+ p25BcastDurationTimer.clock(ms);
+ if (p25BcastDurationTimer.isRunning() && p25BcastDurationTimer.hasExpired()) {
+ p25BcastDurationTimer.stop();
- if (m_state == STATE_P25 && !m_modeTimer.isRunning()) {
- m_modeTimer.setTimeout(m_rfModeHang);
- m_modeTimer.start();
- }
- }
+ p25->setCCRunning(false);
- if (p25CCDurationTimer.isPaused()) {
- p25CCDurationTimer.resume();
+ if (m_state == STATE_P25 && !m_modeTimer.isRunning()) {
+ m_modeTimer.setTimeout(m_rfModeHang);
+ m_modeTimer.start();
}
}
}
else {
// simply use the P25 CC interval timer in a non-broadcast state to transmit adjacent site data over
// the network
- if (p25CCIntervalTimer.isRunning() && p25CCIntervalTimer.hasExpired()) {
+ if (p25BcastIntervalTimer.isRunning() && p25BcastIntervalTimer.hasExpired()) {
if ((m_state == STATE_IDLE || m_state == STATE_P25) && !m_modem->hasTX()) {
p25->writeAdjSSNetwork();
- p25CCIntervalTimer.start();
+ p25BcastIntervalTimer.start();
}
}
}
@@ -1241,16 +1266,31 @@ int Host::run()
}
if (g_killed) {
+ if (dmr != NULL) {
+ if (m_dmrCtrlChannel) {
+ if (!hasTxShutdown) {
+ m_modem->clearDMRData1();
+ m_modem->clearDMRData2();
+ }
+
+ dmr->setCCRunning(false);
+
+ dmrBeaconDurationTimer.stop();
+ dmrBeaconIntervalTimer.stop();
+ }
+ }
+
if (p25 != NULL) {
- if (m_p25CtrlChannel && !hasTxShutdown) {
- m_modem->clearP25Data();
- p25->reset();
+ if (m_p25CtrlChannel) {
+ if (!hasTxShutdown) {
+ m_modem->clearP25Data();
+ p25->reset();
+ }
- p25->writeControlEndRF();
p25->setCCRunning(false);
- p25CCDurationTimer.stop();
- p25CCIntervalTimer.stop();
+ p25BcastDurationTimer.stop();
+ p25BcastIntervalTimer.stop();
}
}
diff --git a/host/Host.h b/host/Host.h
index 76465bd0..5084058d 100644
--- a/host/Host.h
+++ b/host/Host.h
@@ -83,10 +83,6 @@ private:
bool m_dmrEnabled;
bool m_p25Enabled;
- bool m_p25CtrlChannel;
- bool m_p25CtrlBroadcast;
- bool m_dmrCtrlChannel;
-
bool m_duplex;
bool m_fixedMode;
bool m_useDFSI;
@@ -118,7 +114,10 @@ private:
bool m_dmrBeacons;
bool m_dmrTSCCData;
- bool m_controlData;
+ bool m_dmrCtrlChannel;
+ bool m_p25CCData;
+ bool m_p25CtrlChannel;
+ bool m_p25CtrlBroadcast;
uint8_t m_siteId;
uint32_t m_dmrNetId;
diff --git a/modem/Modem.cpp b/modem/Modem.cpp
index 84b90859..40b3f75d 100644
--- a/modem/Modem.cpp
+++ b/modem/Modem.cpp
@@ -160,12 +160,12 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert,
m_openPortHandler(NULL),
m_closePortHandler(NULL),
m_rspHandler(NULL),
- m_rxDMRData1(1110U, "Modem RX DMR1"),
- m_rxDMRData2(1110U, "Modem RX DMR2"),
- m_txDMRData1(740U, "Modem TX DMR1"),
- m_txDMRData2(740U, "Modem TX DMR2"),
- m_rxP25Data(6000U, "Modem RX P25"),
- m_txP25Data(864U, "Modem TX P25"),
+ m_rxDMRData1(1089U, "Modem RX DMR1"), // 1089 bytes = 33 DMR Frames
+ m_rxDMRData2(1089U, "Modem RX DMR2"),
+ m_txDMRData1(792U, "Modem TX DMR1"), // 792 bytes = 24 DMR Frames
+ m_txDMRData2(792U, "Modem TX DMR2"),
+ m_rxP25Data(6048U, "Modem RX P25"), // 6048 bytes = 28 P25 Frames
+ m_txP25Data(864U, "Modem TX P25"), // 864 = 4 P25 Frames
m_useDFSI(false),
m_statusTimer(1000U, 0U, 250U),
m_inactivityTimer(1000U, 4U),
diff --git a/network/RemoteControl.cpp b/network/RemoteControl.cpp
index eaf8cdf2..3baf1df5 100644
--- a/network/RemoteControl.cpp
+++ b/network/RemoteControl.cpp
@@ -306,7 +306,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25)
else if (rcom == RCD_P25_CC_CMD) {
// Command is in the form of: "p25-cc"
if (p25 != NULL) {
- if (host->m_controlData) {
+ if (host->m_p25CCData) {
g_fireP25Control = true;
}
else {
@@ -321,7 +321,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25)
// Command is in the form of: "p25-cc-fallback 0/1"
uint8_t fallback = getArgUInt8(args, 0U);
if (p25 != NULL) {
- if (host->m_controlData) {
+ if (host->m_p25CCData) {
p25->trunk()->setConvFallback((fallback == 1U) ? true : false);
}
else {
@@ -727,7 +727,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25)
else if (rcom == RCD_P25_CC_DEDICATED_CMD) {
// Command is in the form of: "p25-cc-dedicated"
if (p25 != NULL) {
- if (host->m_controlData) {
+ if (host->m_p25CCData) {
if (dmr != NULL) {
LogError(LOG_RCON, CMD_FAILED_STR "Can't enable P25 control channel while DMR is enabled!");
}
@@ -735,7 +735,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25)
host->m_p25CtrlChannel = !host->m_p25CtrlChannel;
host->m_p25CtrlBroadcast = true;
g_fireP25Control = true;
- g_interruptP25Control = false;
+ p25->setCCHalted(false);
LogInfoEx(LOG_RCON, "P25 CC is %s", host->m_p25CtrlChannel ? "enabled" : "disabled");
}
@@ -751,16 +751,16 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25)
else if (rcom == RCD_P25_CC_BCAST_CMD) {
// Command is in the form of: "p25-cc-bcast"
if (p25 != NULL) {
- if (host->m_controlData) {
+ if (host->m_p25CCData) {
host->m_p25CtrlBroadcast = !host->m_p25CtrlBroadcast;
if (!host->m_p25CtrlBroadcast) {
g_fireP25Control = false;
- g_interruptP25Control = true;
+ p25->setCCHalted(true);
}
else {
g_fireP25Control = true;
- g_interruptP25Control = false;
+ p25->setCCHalted(false);
}
LogInfoEx(LOG_RCON, "P25 CC broadcast is %s", host->m_p25CtrlBroadcast ? "enabled" : "disabled");
diff --git a/p25/Control.cpp b/p25/Control.cpp
index eb7b3988..1d6356f0 100644
--- a/p25/Control.cpp
+++ b/p25/Control.cpp
@@ -59,6 +59,7 @@ const uint32_t MAX_PREAMBLE_TDU_CNT = 64U;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the Control class.
///
@@ -69,7 +70,6 @@ const uint32_t MAX_PREAMBLE_TDU_CNT = 64U;
/// Instance of the BaseNetwork class.
/// Transmit timeout.
/// Amount of time to hang on the last talkgroup mode from RF.
-/// Control Channel Broadcast Interval.
/// Flag indicating full-duplex operation.
/// Instance of the RadioIdLookup class.
/// Instance of the TalkgroupIdLookup class.
@@ -81,7 +81,7 @@ const uint32_t MAX_PREAMBLE_TDU_CNT = 64U;
/// Flag indicating whether P25 debug is enabled.
/// Flag indicating whether P25 verbose logging is enabled.
Control::Control(uint32_t nac, uint32_t callHang, uint32_t queueSize, modem::Modem* modem, network::BaseNetwork* network,
- uint32_t timeout, uint32_t tgHang, uint32_t ccBcstInterval, bool duplex, lookups::RadioIdLookup* ridLookup,
+ uint32_t timeout, uint32_t tgHang, bool duplex, lookups::RadioIdLookup* ridLookup,
lookups::TalkgroupIdLookup* tidLookup, lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper,
bool dumpPDUData, bool repeatPDU, bool dumpTSBKData, bool debug, bool verbose) :
m_voice(NULL),
@@ -105,19 +105,20 @@ Control::Control(uint32_t nac, uint32_t callHang, uint32_t queueSize, modem::Mod
m_ridLookup(ridLookup),
m_tidLookup(tidLookup),
m_idenEntry(),
- m_queue(queueSize, "P25 Control"),
+ m_queue(queueSize, "P25 Frame"),
m_rfState(RS_RF_LISTENING),
m_rfLastDstId(0U),
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
m_tailOnIdle(false),
- m_ccOnIdle(false),
m_ccRunning(false),
- m_ccBcstInterval(ccBcstInterval),
+ m_ccPrevRunning(false),
+ m_ccHalted(false),
m_rfTimeout(1000U, timeout),
m_rfTGHang(1000U, tgHang),
m_netTimeout(1000U, timeout),
m_networkWatchdog(1000U, 0U, 1500U),
+ m_ccPacketInterval(1000U, 0U, 5U),
m_hangCount(3U * 8U),
m_tduPreambleCount(8U),
m_ccFrameCnt(0U),
@@ -130,6 +131,7 @@ Control::Control(uint32_t nac, uint32_t callHang, uint32_t queueSize, modem::Mod
m_minRSSI(0U),
m_aveRSSI(0U),
m_rssiCount(0U),
+ m_writeImmediate(false),
m_verbose(verbose),
m_debug(debug)
{
@@ -184,6 +186,7 @@ Control::~Control()
void Control::reset()
{
m_rfState = RS_RF_LISTENING;
+ m_ccHalted = false;
if (m_voice != NULL) {
m_voice->resetRF();
@@ -293,6 +296,9 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
m_trunk->m_voiceChTable.push_back(*it);
}
+ uint32_t ccBcstInterval = p25Protocol["control"]["interval"].as(300U);
+ m_trunk->m_adjSiteUpdateInterval += ccBcstInterval;
+
if (printOptions) {
LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F);
@@ -342,15 +348,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
}
}
-///
-/// Sets a flag indicating whether the P25 control channel is running.
-///
-///
-void Control::setCCRunning(bool ccRunning)
-{
- m_ccRunning = ccRunning;
-}
-
///
/// Process a data frame from the RF interface.
///
@@ -388,7 +385,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len)
writeRF_TDU(false);
m_voice->m_lastDUID = P25_DUID_TDU;
- m_voice->writeNetworkRF(data + 2U, P25_DUID_TDU);
+ m_voice->writeNetwork(data + 2U, P25_DUID_TDU);
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
@@ -496,7 +493,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len)
// are we interrupting a running CC?
if (m_ccRunning) {
if (duid != P25_DUID_TSDU) {
- g_interruptP25Control = true;
+ m_ccHalted = true;
}
}
@@ -557,7 +554,6 @@ uint32_t Control::getFrame(uint8_t* data)
uint8_t len = 0U;
m_queue.getData(&len, 1U);
-
m_queue.getData(data, len);
return len;
@@ -572,81 +568,36 @@ void Control::writeAdjSSNetwork()
}
///
-/// Helper to write control channel frame data.
+/// Helper to write end of voice call frame data.
///
///
-bool Control::writeControlRF()
+bool Control::writeRF_VoiceEnd()
{
- if (!m_control) {
- return false;
- }
-
- const uint8_t maxSeq = 8U;
- if (m_ccSeq == maxSeq) {
- m_ccSeq = 0U;
- }
-
- if (m_ccFrameCnt == 254U) {
- m_trunk->writeAdjSSNetwork();
- m_ccFrameCnt = 0U;
- }
-
if (m_netState == RS_NET_IDLE && m_rfState == RS_RF_LISTENING) {
- m_trunk->writeRF_ControlData(m_ccFrameCnt, m_ccSeq, true);
-
- m_ccSeq++;
- if (m_ccSeq == maxSeq) {
- m_ccFrameCnt++;
- }
-
- return true;
- }
-
- return false;
-}
-
-///
-/// Helper to write end of control channel frame data.
-///
-///
-bool Control::writeControlEndRF()
-{
- if (!m_control) {
- return false;
- }
-
- if (m_netState == RS_NET_IDLE && m_rfState == RS_RF_LISTENING) {
- for (uint32_t i = 0; i < TSBK_PCH_CCH_CNT; i++) {
- m_trunk->queueRF_TSBK_Ctrl(TSBK_OSP_MOT_PSH_CCH);
- }
+ if (m_tailOnIdle) {
+ bool ret = false;
+ if (m_netState == RS_NET_IDLE && m_rfState == RS_RF_LISTENING) {
+ m_voice->writeRF_EndOfVoice();
+
+ // this should have been cleared by writeRF_EndOfVoice; but if it hasn't clear it
+ // to prevent badness
+ if (m_voice->m_hadVoice) {
+ m_voice->m_hadVoice = false;
+ }
- writeRF_Nulls();
- return true;
- }
+ m_tailOnIdle = false;
+ if (m_network != NULL)
+ m_network->resetP25();
- return false;
-}
+ ret = true;
+ }
-///
-/// Helper to write end of frame data.
-///
-///
-bool Control::writeEndRF()
-{
- if (m_netState == RS_NET_IDLE && m_rfState == RS_RF_LISTENING) {
- if (m_tailOnIdle) {
- bool ret = m_voice->writeEndRF();
if (!m_control && m_duplex) {
writeRF_Nulls();
}
return ret;
}
-
- if (m_ccOnIdle) {
- g_fireP25Control = true;
- m_ccOnIdle = false;
- }
}
return false;
@@ -669,6 +620,40 @@ void Control::clock(uint32_t ms)
}
}
+ // if we have control enabled; do clocking to generate a CC data stream
+ if (m_control) {
+ if (m_ccRunning && !m_ccPacketInterval.isRunning()) {
+ m_ccPacketInterval.start();
+ }
+
+ if (m_ccHalted) {
+ if (!m_ccRunning) {
+ m_ccHalted = false;
+ m_ccPrevRunning = m_ccRunning;
+ }
+ }
+ else {
+ m_ccPacketInterval.clock(ms);
+ if (!m_ccPacketInterval.isRunning()) {
+ m_ccPacketInterval.start();
+ }
+
+ if (m_ccPacketInterval.isRunning() && m_ccPacketInterval.hasExpired()) {
+ if (m_ccRunning) {
+ writeRF_ControlData();
+ }
+
+ m_ccPacketInterval.start();
+ }
+ }
+
+ if (m_ccPrevRunning && !m_ccRunning) {
+ writeRF_ControlEnd();
+ m_ccPrevRunning = m_ccRunning;
+ }
+ }
+
+ // handle timeouts and hang timers
m_rfTimeout.clock(ms);
m_netTimeout.clock(ms);
@@ -718,6 +703,7 @@ void Control::clock(uint32_t ms)
}
}
+ // reset states if we're in a rejected state
if (m_rfState == RS_RF_REJECTED) {
m_queue.clear();
@@ -735,7 +721,14 @@ void Control::clock(uint32_t ms)
m_rfState = RS_RF_LISTENING;
}
- m_trunk->clock(ms);
+ // clock data and trunking
+ if (m_data != NULL) {
+ m_data->clock(ms);
+ }
+
+ if (m_trunk != NULL) {
+ m_trunk->clock(ms);
+ }
}
///
@@ -752,63 +745,52 @@ void Control::setDebugVerbose(bool debug, bool verbose)
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
-///
-/// Write data processed from RF to the data ring buffer.
-///
-///
-///
-void Control::writeQueueRF(const uint8_t* data, uint32_t length)
-{
- assert(data != NULL);
-
- if (m_rfTimeout.isRunning() && m_rfTimeout.hasExpired())
- return;
-
- uint32_t space = m_queue.freeSpace();
- if (space < (length + 1U)) {
- uint32_t queueLen = m_queue.length();
- m_queue.resize(queueLen + QUEUE_RESIZE_SIZE);
-
- LogError(LOG_P25, "overflow in the P25 RF queue; queue resized was %u is %u", queueLen, m_queue.length());
- return;
- }
-
- if (m_debug) {
- Utils::symbols("!!! *Tx P25", data + 2U, length - 2U);
- }
-
- uint8_t len = length;
- m_queue.addData(&len, 1U);
-
- m_queue.addData(data, len);
-}
///
-/// Write data processed from the network to the data ring buffer.
+/// Add data frame to the data ring buffer.
///
///
///
-void Control::writeQueueNet(const uint8_t* data, uint32_t length)
+///
+void Control::addFrame(const uint8_t* data, uint32_t length, bool net)
{
assert(data != NULL);
- if (m_netTimeout.isRunning() && m_netTimeout.hasExpired())
- return;
-
- uint32_t space = m_queue.freeSpace();
- if (space < (length + 1U)) {
- LogError(LOG_P25, "network overflow in the P25 RF queue");
- return;
+ if (!net) {
+ if (m_rfTimeout.isRunning() && m_rfTimeout.hasExpired())
+ return;
+ } else {
+ if (m_netTimeout.isRunning() && m_netTimeout.hasExpired())
+ return;
}
- if (m_debug) {
- Utils::symbols("!!! *Tx P25", data + 2U, length - 2U);
+ if (m_writeImmediate && m_modem->hasP25Space() && m_modem->getState() == modem::STATE_P25) {
+ m_writeImmediate = false;
+ m_modem->writeP25Data(data, length, true);
}
+ else {
+ uint32_t space = m_queue.freeSpace();
+ if (space < (length + 1U)) {
+ if (!net) {
+ uint32_t queueLen = m_queue.length();
+ m_queue.resize(queueLen + P25_LDU_FRAME_LENGTH_BYTES);
+ LogError(LOG_P25, "overflow in the P25 queue while writing data; queue free is %u, needed %u; resized was %u is %u", space, length, queueLen, m_queue.length());
+ return;
+ }
+ else {
+ LogError(LOG_P25, "overflow in the P25 queue while writing network data; queue free is %u, needed %u", space, length);
+ return;
+ }
+ }
- uint8_t len = length;
- m_queue.addData(&len, 1U);
+ if (m_debug) {
+ Utils::symbols("!!! *Tx P25", data + 2U, length - 2U);
+ }
- m_queue.addData(data, len);
+ uint8_t len = length;
+ m_queue.addData(&len, 1U);
+ m_queue.addData(data, len);
+ }
}
#if ENABLE_DFSI_SUPPORT
@@ -1031,6 +1013,70 @@ void Control::processNetwork()
delete data;
}
+///
+/// Helper to write control channel frame data.
+///
+///
+bool Control::writeRF_ControlData()
+{
+ if (!m_control)
+ return false;
+
+ if (m_ccFrameCnt == 254U) {
+ m_trunk->writeAdjSSNetwork();
+ m_ccFrameCnt = 0U;
+ }
+
+ // don't add any frames if the queue is full
+ uint8_t len = (P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES * 2U) + 2U;
+ uint32_t space = m_queue.freeSpace();
+ if (space < (len + 1U)) {
+ return false;
+ }
+
+ const uint8_t maxSeq = 8U;
+ if (m_ccSeq == maxSeq) {
+ m_ccSeq = 0U;
+ }
+
+ if (m_netState == RS_NET_IDLE && m_rfState == RS_RF_LISTENING) {
+ m_trunk->writeRF_ControlData(m_ccFrameCnt, m_ccSeq, true);
+
+ m_ccSeq++;
+ if (m_ccSeq == maxSeq) {
+ m_ccFrameCnt++;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+///
+/// Helper to write end of control channel frame data.
+///
+///
+bool Control::writeRF_ControlEnd()
+{
+ if (!m_control)
+ return false;
+
+ m_queue.clear();
+ m_ccPacketInterval.stop();
+
+ if (m_netState == RS_NET_IDLE && m_rfState == RS_RF_LISTENING) {
+ for (uint32_t i = 0; i < TSBK_PCH_CCH_CNT; i++) {
+ m_trunk->queueRF_TSBK_Ctrl(TSBK_OSP_MOT_PSH_CCH);
+ }
+
+ writeRF_Nulls();
+ return true;
+ }
+
+ return false;
+}
+
///
/// Helper to write data nulls.
///
@@ -1049,7 +1095,7 @@ void Control::writeRF_Nulls()
LogDebug(LOG_P25, "writeRF_Nulls()");
}
- writeQueueRF(data, NULLS_LENGTH_BYTES + 2U);
+ addFrame(data, NULLS_LENGTH_BYTES + 2U);
}
///
@@ -1110,13 +1156,13 @@ void Control::writeRF_TDU(bool noNetwork)
addBusyBits(data + 2U, P25_TDU_FRAME_LENGTH_BITS, true, true);
if (!noNetwork)
- m_voice->writeNetworkRF(data + 2U, P25_DUID_TDU);
+ m_voice->writeNetwork(data + 2U, P25_DUID_TDU);
if (m_duplex) {
data[0U] = modem::TAG_EOT;
data[1U] = 0x00U;
- writeQueueRF(data, P25_TDU_FRAME_LENGTH_BYTES + 2U);
+ addFrame(data, P25_TDU_FRAME_LENGTH_BYTES + 2U);
}
}
diff --git a/p25/Control.h b/p25/Control.h
index afa71bde..07496fe8 100644
--- a/p25/Control.h
+++ b/p25/Control.h
@@ -55,6 +55,7 @@ namespace p25
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
+
class HOST_SW_API VoicePacket;
namespace dfsi { class HOST_SW_API DFSIVoicePacket; }
class HOST_SW_API DataPacket;
@@ -70,7 +71,7 @@ namespace p25
public:
/// Initializes a new instance of the Control class.
Control(uint32_t nac, uint32_t callHang, uint32_t queueSize, modem::Modem* modem, network::BaseNetwork* network,
- uint32_t timeout, uint32_t tgHang, uint32_t ccBcstInterval, bool duplex, lookups::RadioIdLookup* ridLookup,
+ uint32_t timeout, uint32_t tgHang, bool duplex, lookups::RadioIdLookup* ridLookup,
lookups::TalkgroupIdLookup* tidLookup, lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper,
bool dumpPDUData, bool repeatPDU, bool dumpTSBKData, bool debug, bool verbose);
/// Finalizes a instance of the Control class.
@@ -83,8 +84,15 @@ namespace p25
void setOptions(yaml::Node& conf, const std::string cwCallsign, const std::vector voiceChNo,
uint32_t pSuperGroup, uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId,
uint8_t channelId, uint32_t channelNo, bool printOptions);
+
+ /// Gets a flag indicating whether the P25 control channel is running.
+ bool getCCRunning() { return m_ccRunning; }
/// Sets a flag indicating whether the P25 control channel is running.
- void setCCRunning(bool ccRunning);
+ void setCCRunning(bool ccRunning) { m_ccPrevRunning = m_ccRunning; m_ccRunning = ccRunning; }
+ /// Gets a flag indicating whether the P25 control channel is running.
+ bool getCCHalted() { return m_ccHalted; }
+ /// Sets a flag indicating whether the P25 control channel is halted.
+ void setCCHalted(bool ccHalted) { m_ccHalted = ccHalted; }
/// Process a data frame from the RF interface.
bool processFrame(uint8_t* data, uint32_t len);
@@ -94,12 +102,8 @@ namespace p25
/// Helper to write P25 adjacent site information to the network.
void writeAdjSSNetwork();
- /// Helper to write control channel frame data.
- bool writeControlRF();
- /// Helper to write end of control channel frame data.
- bool writeControlEndRF();
- /// Helper to write end of frame data.
- bool writeEndRF();
+ /// Helper to write end of voice call frame data.
+ bool writeRF_VoiceEnd();
/// Updates the processor by the passed number of milliseconds.
void clock(uint32_t ms);
@@ -154,15 +158,17 @@ namespace p25
uint32_t m_netLastDstId;
bool m_tailOnIdle;
- bool m_ccOnIdle;
bool m_ccRunning;
- uint32_t m_ccBcstInterval;
+ bool m_ccPrevRunning;
+ bool m_ccHalted;
Timer m_rfTimeout;
Timer m_rfTGHang;
Timer m_netTimeout;
Timer m_networkWatchdog;
+ Timer m_ccPacketInterval;
+
uint32_t m_hangCount;
uint32_t m_tduPreambleCount;
@@ -180,13 +186,13 @@ namespace p25
uint32_t m_aveRSSI;
uint32_t m_rssiCount;
+ bool m_writeImmediate; // This is essentially a "latch" that will auto-reset after a writeRF_Queue() call.
+
bool m_verbose;
bool m_debug;
- /// Write data processed from RF to the data ring buffer.
- void writeQueueRF(const uint8_t* data, uint32_t length);
- /// Write data processed from the network to the data ring buffer.
- void writeQueueNet(const uint8_t* data, uint32_t length);
+ /// Add data frame to the data ring buffer.
+ void addFrame(const uint8_t* data, uint32_t length, bool net = false);
#if ENABLE_DFSI_SUPPORT
/// Process a DFSI data frame from the RF interface.
@@ -196,6 +202,11 @@ namespace p25
/// Process a data frames from the network.
void processNetwork();
+ /// Helper to write control channel frame data.
+ bool writeRF_ControlData();
+ /// Helper to write end of control channel frame data.
+ bool writeRF_ControlEnd();
+
/// Helper to write data nulls.
void writeRF_Nulls();
/// Helper to write TDU preamble packet burst.
diff --git a/p25/DataPacket.cpp b/p25/DataPacket.cpp
index 57bb4acc..0f3ca9eb 100644
--- a/p25/DataPacket.cpp
+++ b/p25/DataPacket.cpp
@@ -47,9 +47,16 @@ using namespace p25::data;
#include
#include
+// ---------------------------------------------------------------------------
+// Constants
+// ---------------------------------------------------------------------------
+
+const uint32_t CONN_WAIT_TIMEOUT = 1U;
+
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Resets the data states for the RF interface.
///
@@ -86,7 +93,7 @@ bool DataPacket::process(uint8_t* data, uint32_t len)
// are we interrupting a running CC?
if (m_p25->m_ccRunning) {
- g_interruptP25Control = true;
+ m_p25->m_ccHalted = true;
}
// handle individual DUIDs
@@ -227,7 +234,7 @@ bool DataPacket::process(uint8_t* data, uint32_t len)
}
}
- writeNetworkRF(m_rfDataBlockCnt, m_pduUserData + dataOffset, (m_rfDataHeader.getFormat() == PDU_FMT_CONFIRMED) ? P25_PDU_CONFIRMED_DATA_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES);
+ writeNetwork(m_rfDataBlockCnt, m_pduUserData + dataOffset, (m_rfDataHeader.getFormat() == PDU_FMT_CONFIRMED) ? P25_PDU_CONFIRMED_DATA_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES);
m_rfDataBlockCnt++;
}
else {
@@ -273,34 +280,30 @@ bool DataPacket::process(uint8_t* data, uint32_t len)
ulong64_t ipAddr = (m_pduUserData[8U] << 24) + (m_pduUserData[9U] << 16) +
(m_pduUserData[10U] << 8) + m_pduUserData[11U];
+ if (m_rfDataHeader.getAckNeeded()) {
+ m_p25->m_writeImmediate = true;
+ writeRF_PDU_Ack_Response(PDU_ACK_CLASS_ACK, PDU_ACK_TYPE_ACK, llId);
+ }
+
if (m_verbose) {
LogMessage(LOG_RF, P25_PDU_STR ", PDU_REG_TYPE_REQ_CNCT (Registration Request Connect), llId = %u, ipAddr = %s", llId, __IP_FROM_ULONG(ipAddr).c_str());
}
- writeRF_PDU_Ack_Response(PDU_ACK_CLASS_ACK, PDU_ACK_TYPE_ACK, llId);
+ m_connQueueTable[llId] = ipAddr;
- if (!acl::AccessControl::validateSrcId(llId)) {
- LogWarning(LOG_RF, P25_PDU_STR ", PDU_REG_TYPE_RSP_DENY (Registration Response Deny), llId = %u, ipAddr = %s", llId, __IP_FROM_ULONG(ipAddr).c_str());
- writeRF_PDU_Reg_Response(PDU_REG_TYPE_RSP_DENY, llId, ipAddr);
- }
- else {
- if (!hasLLIdFNEReg(llId)) {
- // update dynamic FNE registration table entry
- m_fneRegTable[llId] = ipAddr;
- }
-
- if (m_verbose) {
- LogMessage(LOG_RF, P25_PDU_STR ", PDU_REG_TYPE_RSP_ACCPT (Registration Response Accept), llId = %u, ipAddr = %s", llId, __IP_FROM_ULONG(ipAddr).c_str());
- }
-
- writeRF_PDU_Reg_Response(PDU_REG_TYPE_RSP_ACCPT, llId, ipAddr);
- }
+ m_connTimerTable[llId] = Timer(1000U, CONN_WAIT_TIMEOUT);
+ m_connTimerTable[llId].start();
}
break;
case PDU_REG_TYPE_REQ_DISCNCT:
{
uint32_t llId = (m_pduUserData[1U] << 16) + (m_pduUserData[2U] << 8) + m_pduUserData[3U];
+ if (m_rfDataHeader.getAckNeeded()) {
+ m_p25->m_writeImmediate = true;
+ writeRF_PDU_Ack_Response(PDU_ACK_CLASS_ACK, PDU_ACK_TYPE_ACK, llId);
+ }
+
if (m_verbose) {
LogMessage(LOG_RF, P25_PDU_STR ", PDU_REG_TYPE_REQ_DISCNCT (Registration Request Disconnect), llId = %u", llId);
}
@@ -502,9 +505,54 @@ bool DataPacket::hasLLIdFNEReg(uint32_t llId) const
}
}
+///
+/// Updates the processor by the passed number of milliseconds.
+///
+///
+void DataPacket::clock(uint32_t ms)
+{
+ // clock all the connect timers
+ std::vector connToClear = std::vector();
+ for (auto it = m_connQueueTable.begin(); it != m_connQueueTable.end(); ++it) {
+ uint32_t llId = it->first;
+
+ m_connTimerTable[llId].clock(ms);
+ if (m_connTimerTable[llId].isRunning() && m_connTimerTable[llId].hasExpired()) {
+ connToClear.push_back(llId);
+ }
+ }
+
+ // handle PDU connection registration
+ for (auto it = connToClear.begin(); it != connToClear.end(); ++it) {
+ uint32_t llId = *it;
+ uint64_t ipAddr = m_connQueueTable[llId];
+
+ m_p25->m_writeImmediate = true;
+ if (!acl::AccessControl::validateSrcId(llId)) {
+ LogWarning(LOG_RF, P25_PDU_STR ", PDU_REG_TYPE_RSP_DENY (Registration Response Deny), llId = %u, ipAddr = %s", llId, __IP_FROM_ULONG(ipAddr).c_str());
+ writeRF_PDU_Reg_Response(PDU_REG_TYPE_RSP_DENY, llId, ipAddr);
+ }
+ else {
+ if (!hasLLIdFNEReg(llId)) {
+ // update dynamic FNE registration table entry
+ m_fneRegTable[llId] = ipAddr;
+ }
+
+ if (m_verbose) {
+ LogMessage(LOG_RF, P25_PDU_STR ", PDU_REG_TYPE_RSP_ACCPT (Registration Response Accept), llId = %u, ipAddr = %s", llId, __IP_FROM_ULONG(ipAddr).c_str());
+ }
+
+ writeRF_PDU_Reg_Response(PDU_REG_TYPE_RSP_ACCPT, llId, ipAddr);
+ }
+
+ m_connQueueTable.erase(llId);
+ }
+}
+
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the DataPacket class.
///
@@ -537,6 +585,8 @@ DataPacket::DataPacket(Control* p25, network::BaseNetwork* network, bool dumpPDU
m_pduUserData(NULL),
m_pduUserDataLength(0U),
m_fneRegTable(),
+ m_connQueueTable(),
+ m_connTimerTable(),
m_dumpPDUData(dumpPDUData),
m_repeatPDU(repeatPDU),
m_verbose(verbose),
@@ -556,6 +606,8 @@ DataPacket::DataPacket(Control* p25, network::BaseNetwork* network, bool dumpPDU
::memset(m_pduUserData, 0x00U, P25_MAX_PDU_COUNT * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U);
m_fneRegTable.clear();
+ m_connQueueTable.clear();
+ m_connTimerTable.clear();
}
///
@@ -574,7 +626,7 @@ DataPacket::~DataPacket()
///
///
///
-void DataPacket::writeNetworkRF(const uint8_t currentBlock, const uint8_t *data, uint32_t len)
+void DataPacket::writeNetwork(const uint8_t currentBlock, const uint8_t *data, uint32_t len)
{
assert(data != NULL);
@@ -624,7 +676,8 @@ void DataPacket::writeRF_PDU(const uint8_t* pdu, uint32_t bitLength, bool noNull
if (m_p25->m_duplex) {
data[0U] = modem::TAG_DATA;
data[1U] = 0x00U;
- m_p25->writeQueueRF(data, newByteLength + 2U);
+
+ m_p25->addFrame(data, newByteLength + 2U);
}
// add trailing null pad; only if control data isn't being transmitted
@@ -805,7 +858,8 @@ void DataPacket::writeRF_PDU_Reg_Response(uint8_t regType, uint32_t llId, ulong6
///
///
///
-void DataPacket::writeRF_PDU_Ack_Response(uint8_t ackClass, uint8_t ackType, uint32_t llId)
+///
+void DataPacket::writeRF_PDU_Ack_Response(uint8_t ackClass, uint8_t ackType, uint32_t llId, bool noNulls)
{
if (ackClass == PDU_ACK_CLASS_ACK && ackType != PDU_ACK_TYPE_ACK)
return;
@@ -839,6 +893,6 @@ void DataPacket::writeRF_PDU_Ack_Response(uint8_t ackClass, uint8_t ackType, uin
rspHeader.encode(block);
Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS);
- writeRF_PDU(data, bitLength, true);
+ writeRF_PDU(data, bitLength, noNulls);
delete[] data;
}
diff --git a/p25/DataPacket.h b/p25/DataPacket.h
index 8a77c34e..b321f8a8 100644
--- a/p25/DataPacket.h
+++ b/p25/DataPacket.h
@@ -38,6 +38,7 @@
#include "p25/lc/LC.h"
#include "p25/Control.h"
#include "network/BaseNetwork.h"
+#include "Timer.h"
#include
#include
@@ -48,6 +49,7 @@ namespace p25
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
+
class HOST_SW_API Control;
// ---------------------------------------------------------------------------
@@ -68,6 +70,9 @@ namespace p25
/// Helper to check if a logical link ID has registered with data services.
bool hasLLIdFNEReg(uint32_t llId) const;
+ /// Updates the processor by the passed number of milliseconds.
+ void clock(uint32_t ms);
+
private:
friend class Control;
Control* m_p25;
@@ -99,6 +104,9 @@ namespace p25
std::unordered_map m_fneRegTable;
+ std::unordered_map m_connQueueTable;
+ std::unordered_map m_connTimerTable;
+
bool m_dumpPDUData;
bool m_repeatPDU;
@@ -111,7 +119,7 @@ namespace p25
~DataPacket();
/// Write data processed from RF to the network.
- void writeNetworkRF(const uint8_t currentBlock, const uint8_t* data, uint32_t len);
+ void writeNetwork(const uint8_t currentBlock, const uint8_t* data, uint32_t len);
/// Helper to write a P25 PDU packet.
void writeRF_PDU(const uint8_t* pdu, uint32_t bitLength, bool noNulls = false);
@@ -122,7 +130,7 @@ namespace p25
/// Helper to write a PDU registration response.
void writeRF_PDU_Reg_Response(uint8_t regType, uint32_t llId, ulong64_t ipAddr);
/// Helper to write a PDU acknowledge response.
- void writeRF_PDU_Ack_Response(uint8_t ackClass, uint8_t ackType, uint32_t llId);
+ void writeRF_PDU_Ack_Response(uint8_t ackClass, uint8_t ackType, uint32_t llId, bool noNulls = false);
};
} // namespace p25
diff --git a/p25/TrunkPacket.cpp b/p25/TrunkPacket.cpp
index f54fa0bf..5e686426 100644
--- a/p25/TrunkPacket.cpp
+++ b/p25/TrunkPacket.cpp
@@ -44,6 +44,7 @@ using namespace p25::data;
// ---------------------------------------------------------------------------
// Macros
// ---------------------------------------------------------------------------
+
// Make sure control data is supported.
#define IS_SUPPORT_CONTROL_CHECK(_PCKT_STR, _PCKT, _SRCID) \
if (!m_p25->m_control) { \
@@ -136,6 +137,7 @@ const uint8_t CONV_FALLBACK_PACKET_DELAY = 8U;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Resets the data states for the RF interface.
///
@@ -1290,6 +1292,7 @@ void TrunkPacket::setTSBKVerbose(bool verbose)
// ---------------------------------------------------------------------------
// Protected Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the TrunkPacket class.
///
@@ -1353,7 +1356,7 @@ TrunkPacket::TrunkPacket(Control* p25, network::BaseNetwork* network, bool dumpT
m_grantChTable.clear();
m_grantTimers.clear();
- m_adjSiteUpdateInterval = ADJ_SITE_TIMER_TIMEOUT + m_p25->m_ccBcstInterval;
+ m_adjSiteUpdateInterval = ADJ_SITE_TIMER_TIMEOUT;
m_adjSiteUpdateTimer.setTimeout(m_adjSiteUpdateInterval);
m_adjSiteUpdateTimer.start();
}
@@ -1548,7 +1551,7 @@ void TrunkPacket::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
data[0U] = modem::TAG_EOT;
data[1U] = 0x00U;
- m_p25->writeQueueRF(data, P25_TDULC_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(data, P25_TDULC_FRAME_LENGTH_BYTES + 2U);
}
//if (m_verbose) {
@@ -1669,7 +1672,7 @@ void TrunkPacket::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool f
data[0U] = modem::TAG_DATA;
data[1U] = 0x00U;
- m_p25->writeQueueRF(data, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(data, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
}
}
@@ -1768,7 +1771,7 @@ void TrunkPacket::writeRF_TSDU_MBF(bool clearBeforeWrite)
m_p25->m_queue.clear();
}
- m_p25->writeQueueRF(data, P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(data, P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES + 2U);
::memset(m_rfMBF, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U);
m_mbfCnt = 0U;
@@ -2161,6 +2164,7 @@ bool TrunkPacket::writeRF_TSDU_Grant(bool grp, bool skip, bool net, bool skipNet
// transmit group grant
m_rfTSBK.setLCO(TSBK_IOSP_GRP_VCH);
+ m_p25->m_writeImmediate = true;
writeRF_TSDU_SBF(false, true, net);
}
else {
@@ -2175,6 +2179,7 @@ bool TrunkPacket::writeRF_TSDU_Grant(bool grp, bool skip, bool net, bool skipNet
// transmit private grant
m_rfTSBK.setLCO(TSBK_IOSP_UU_VCH);
+ m_p25->m_writeImmediate = true;
writeRF_TSDU_SBF(false, true, net);
}
@@ -2652,7 +2657,7 @@ void TrunkPacket::writeNet_TDULC(lc::TDULC lc)
// Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true);
- m_p25->writeQueueNet(buffer, P25_TDULC_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_TDULC_FRAME_LENGTH_BYTES + 2U, true);
if (m_verbose) {
LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc.getLCO(), lc.getSrcId());
@@ -2702,7 +2707,7 @@ void TrunkPacket::writeNet_TSDU()
// Set first busy bits to 1,1
m_p25->setBusyBits(buffer + 2U, P25_SS0_START, true, true);
- m_p25->writeQueueNet(buffer, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_TSDU_FRAME_LENGTH_BYTES + 2U, true);
if (m_network != NULL)
m_network->resetP25();
diff --git a/p25/VoicePacket.cpp b/p25/VoicePacket.cpp
index 39cb78e8..74162536 100644
--- a/p25/VoicePacket.cpp
+++ b/p25/VoicePacket.cpp
@@ -56,6 +56,7 @@ const uint32_t VOC_LDU1_COUNT = 3U;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Resets the data states for the RF interface.
///
@@ -123,7 +124,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
// are we interrupting a running CC?
if (m_p25->m_ccRunning) {
- g_interruptP25Control = true;
+ m_p25->m_ccHalted = true;
}
if (m_p25->m_rfState != RS_RF_LISTENING) {
@@ -138,8 +139,10 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
if (duid == P25_DUID_HDU) {
m_lastDUID = P25_DUID_HDU;
- if (m_p25->m_rfState == RS_RF_LISTENING && m_p25->m_ccRunning) {
- m_p25->m_modem->clearP25Data();
+ if (m_p25->m_rfState == RS_RF_LISTENING) {
+ if (!m_p25->m_dedicatedControl) {
+ m_p25->m_modem->clearP25Data();
+ }
m_p25->m_queue.clear();
resetRF();
resetNet();
@@ -196,6 +199,16 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
m_lastDUID = P25_DUID_LDU1;
if (m_p25->m_rfState == RS_RF_LISTENING) {
+ // if this is a late entry call, clear states
+ if (m_rfLastHDU.getDstId() == 0U) {
+ if (!m_p25->m_dedicatedControl) {
+ m_p25->m_modem->clearP25Data();
+ }
+ m_p25->m_queue.clear();
+ resetRF();
+ resetNet();
+ }
+
if (m_p25->m_control) {
if (!m_p25->m_ccRunning && m_p25->m_voiceOnControl) {
m_p25->m_trunk->writeRF_ControlData(255U, 0U, false);
@@ -350,7 +363,6 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
m_p25->m_trunk->writeRF_TSDU_Grant(group, true);
}
@@ -390,12 +402,13 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
// Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_HDU_FRAME_LENGTH_BITS, false, true);
- writeNetworkRF(buffer, P25_DUID_HDU);
+ writeNetwork(buffer, P25_DUID_HDU);
if (m_p25->m_duplex) {
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueRF(buffer, P25_HDU_FRAME_LENGTH_BYTES + 2U);
+
+ m_p25->addFrame(buffer, P25_HDU_FRAME_LENGTH_BYTES + 2U);
}
if (m_verbose) {
@@ -515,12 +528,13 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
// Add busy bits
m_p25->addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
- writeNetworkRF(data + 2U, P25_DUID_LDU1);
+ writeNetwork(data + 2U, P25_DUID_LDU1);
if (m_p25->m_duplex) {
data[0U] = modem::TAG_DATA;
data[1U] = 0x00U;
- m_p25->writeQueueRF(data, P25_LDU_FRAME_LENGTH_BYTES + 2U);
+
+ m_p25->addFrame(data, P25_LDU_FRAME_LENGTH_BYTES + 2U);
}
if (m_verbose) {
@@ -593,12 +607,13 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
// Add busy bits
m_p25->addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
- writeNetworkRF(data + 2U, P25_DUID_LDU2);
+ writeNetwork(data + 2U, P25_DUID_LDU2);
if (m_p25->m_duplex) {
data[0U] = modem::TAG_DATA;
data[1U] = 0x00U;
- m_p25->writeQueueRF(data, P25_LDU_FRAME_LENGTH_BYTES + 2U);
+
+ m_p25->addFrame(data, P25_LDU_FRAME_LENGTH_BYTES + 2U);
}
if (m_verbose) {
@@ -729,12 +744,7 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d
if (m_p25->m_netState == RS_NET_IDLE) {
// are we interrupting a running CC?
if (m_p25->m_ccRunning) {
- g_interruptP25Control = true;
- }
-
- // single-channel trunking or voice on control support?
- if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
+ m_p25->m_ccHalted = true;
}
}
@@ -833,40 +843,10 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d
return true;
}
-///
-/// Helper to write end of frame data.
-///
-///
-bool VoicePacket::writeEndRF()
-{
- if (m_p25->m_netState == RS_NET_IDLE && m_p25->m_rfState == RS_RF_LISTENING) {
- writeRF_EndOfVoice();
-
- // this should have been cleared by writeRF_EndOfVoice; but if it hasn't clear it
- // to prevent badness
- if (m_hadVoice) {
- m_hadVoice = false;
- }
-
- if (m_p25->m_control && !m_p25->m_ccRunning) {
- m_p25->m_trunk->writeRF_ControlData(255U, 0U, false);
- m_p25->writeControlEndRF();
- }
-
- m_p25->m_tailOnIdle = false;
-
- if (m_network != NULL)
- m_network->resetP25();
-
- return true;
- }
-
- return false;
-}
-
// ---------------------------------------------------------------------------
// Protected Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the VoicePacket class.
///
@@ -929,7 +909,7 @@ VoicePacket::~VoicePacket()
///
///
///
-void VoicePacket::writeNetworkRF(const uint8_t *data, uint8_t duid)
+void VoicePacket::writeNetwork(const uint8_t *data, uint8_t duid)
{
assert(data != NULL);
@@ -1004,7 +984,7 @@ void VoicePacket::writeNet_TDU()
// Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_TDU_FRAME_LENGTH_BITS, true, true);
- m_p25->writeQueueNet(buffer, P25_TDU_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_TDU_FRAME_LENGTH_BYTES + 2U, true);
if (m_verbose) {
LogMessage(LOG_NET, P25_TDU_STR ", srcId = %u", m_netLC.getSrcId());
@@ -1188,7 +1168,6 @@ void VoicePacket::writeNet_LDU1()
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
if (!m_p25->m_trunk->writeRF_TSDU_Grant(group, false, true)) {
if (m_network != NULL)
m_network->resetP25();
@@ -1241,7 +1220,8 @@ void VoicePacket::writeNet_LDU1()
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueNet(buffer, P25_HDU_FRAME_LENGTH_BYTES + 2U);
+
+ m_p25->addFrame(buffer, P25_HDU_FRAME_LENGTH_BYTES + 2U, true);
if (m_verbose) {
LogMessage(LOG_NET, P25_HDU_STR ", dstId = %u, algo = $%02X, kid = $%04X", m_netLC.getDstId(), m_netLC.getAlgId(), m_netLC.getKId());
@@ -1299,7 +1279,8 @@ void VoicePacket::writeNet_LDU1()
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
+
+ m_p25->addFrame(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U, true);
if (m_verbose) {
uint32_t loss = 0;
@@ -1403,7 +1384,8 @@ void VoicePacket::writeNet_LDU2()
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
+
+ m_p25->addFrame(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U, true);
if (m_verbose) {
uint32_t loss = 0;
diff --git a/p25/VoicePacket.h b/p25/VoicePacket.h
index 86dc584c..f2974768 100644
--- a/p25/VoicePacket.h
+++ b/p25/VoicePacket.h
@@ -68,9 +68,6 @@ namespace p25
/// Process a data frame from the network.
virtual bool processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::LowSpeedData& lsd, uint8_t& duid);
- /// Helper to write end of frame data.
- bool writeEndRF();
-
protected:
friend class TrunkPacket;
friend class Control;
@@ -121,7 +118,7 @@ namespace p25
virtual ~VoicePacket();
/// Write data processed from RF to the network.
- void writeNetworkRF(const uint8_t* data, uint8_t duid);
+ void writeNetwork(const uint8_t* data, uint8_t duid);
/// Helper to write end of voice frame data.
void writeRF_EndOfVoice();
diff --git a/p25/dfsi/DFSITrunkPacket.cpp b/p25/dfsi/DFSITrunkPacket.cpp
index 9a7c9935..301ad89d 100644
--- a/p25/dfsi/DFSITrunkPacket.cpp
+++ b/p25/dfsi/DFSITrunkPacket.cpp
@@ -38,6 +38,7 @@ using namespace p25::dfsi;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Resets the data states for the RF interface.
///
@@ -94,6 +95,7 @@ bool DFSITrunkPacket::process(uint8_t* data, uint32_t len, bool preDecoded)
// ---------------------------------------------------------------------------
// Protected Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the DFSITrunkPacket class.
///
@@ -189,7 +191,7 @@ void DFSITrunkPacket::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bo
data[0U] = modem::TAG_DATA;
data[1U] = 0x00U;
- m_p25->writeQueueRF(data, P25_DFSI_TSBK_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(data, P25_DFSI_TSBK_FRAME_LENGTH_BYTES + 2U);
writeRF_DSFI_Stop(P25_DFSI_TYPE_TSBK);
}
@@ -209,7 +211,7 @@ void DFSITrunkPacket::writeNet_TSDU()
m_netDFSILC.tsbk(m_netTSBK);
m_netDFSILC.encodeTSBK(buffer + 2U);
- m_p25->writeQueueNet(buffer, P25_DFSI_TSBK_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_DFSI_TSBK_FRAME_LENGTH_BYTES + 2U, true);
if (m_network != NULL)
m_network->resetP25();
@@ -235,7 +237,7 @@ void DFSITrunkPacket::writeRF_DFSI_Start(uint8_t type)
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueRF(buffer, P25_DFSI_SS_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_DFSI_SS_FRAME_LENGTH_BYTES + 2U);
}
///
@@ -260,6 +262,6 @@ void DFSITrunkPacket::writeRF_DSFI_Stop(uint8_t type)
// for whatever reason this is almost always sent twice
for (uint8_t i = 0; i < 2;i ++) {
- m_p25->writeQueueRF(buffer, P25_DFSI_SS_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_DFSI_SS_FRAME_LENGTH_BYTES + 2U);
}
}
diff --git a/p25/dfsi/DFSIVoicePacket.cpp b/p25/dfsi/DFSIVoicePacket.cpp
index 0b8322f7..2ad913d7 100644
--- a/p25/dfsi/DFSIVoicePacket.cpp
+++ b/p25/dfsi/DFSIVoicePacket.cpp
@@ -50,6 +50,7 @@ const uint32_t VOC_LDU1_COUNT = 3U;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
+
///
/// Resets the data states for the RF interface.
///
@@ -90,7 +91,7 @@ bool DFSIVoicePacket::process(uint8_t* data, uint32_t len)
uint8_t frameType = m_rfDFSILC.getFrameType();
if (frameType == P25_DFSI_VHDR2) {
if (m_p25->m_rfState == RS_RF_LISTENING && m_p25->m_ccRunning) {
- m_p25->m_modem->clearP25Data();
+ //m_p25->m_modem->clearP25Data();
m_p25->m_queue.clear();
resetRF();
resetNet();
@@ -333,7 +334,6 @@ bool DFSIVoicePacket::process(uint8_t* data, uint32_t len)
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
m_p25->m_trunk->writeRF_TSDU_Grant(group, true);
}
@@ -373,7 +373,7 @@ bool DFSIVoicePacket::process(uint8_t* data, uint32_t len)
// Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_HDU_FRAME_LENGTH_BITS, false, true);
- writeNetworkRF(buffer, P25_DUID_HDU);
+ writeNetwork(buffer, P25_DUID_HDU);
if (m_verbose) {
LogMessage(LOG_RF, P25_HDU_STR " DFSI, dstId = %u, algo = $%02X, kid = $%04X", m_rfLC.getDstId(), m_rfLC.getAlgId(), m_rfLC.getKId());
@@ -448,7 +448,7 @@ bool DFSIVoicePacket::process(uint8_t* data, uint32_t len)
// Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
- writeNetworkRF(buffer + 2U, P25_DUID_LDU1);
+ writeNetwork(buffer + 2U, P25_DUID_LDU1);
if (m_verbose) {
LogMessage(LOG_RF, P25_LDU1_STR " DFSI, audio, srcId = %u, dstId = %u, group = %u, emerg = %u, encrypt = %u, prio = %u",
@@ -540,7 +540,7 @@ bool DFSIVoicePacket::process(uint8_t* data, uint32_t len)
// Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
- writeNetworkRF(buffer + 2U, P25_DUID_LDU2);
+ writeNetwork(buffer + 2U, P25_DUID_LDU2);
if (m_verbose) {
LogMessage(LOG_RF, P25_LDU2_STR " DFSI, audio, algo = $%02X, kid = $%04X",
@@ -571,7 +571,7 @@ bool DFSIVoicePacket::process(uint8_t* data, uint32_t len)
// Add busy bits
m_p25->addBusyBits(data + 2U, P25_TDU_FRAME_LENGTH_BITS, true, true);
- writeNetworkRF(data + 2U, P25_DUID_TDU);
+ writeNetwork(data + 2U, P25_DUID_TDU);
m_lastDUID = P25_DUID_TDU;
@@ -675,12 +675,7 @@ bool DFSIVoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& contro
if (m_p25->m_netState == RS_NET_IDLE) {
// are we interrupting a running CC?
if (m_p25->m_ccRunning) {
- g_interruptP25Control = true;
- }
-
- // single-channel trunking or voice on control support?
- if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
+ m_p25->m_ccHalted = true;
}
}
@@ -782,6 +777,7 @@ bool DFSIVoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& contro
// ---------------------------------------------------------------------------
// Protected Class Members
// ---------------------------------------------------------------------------
+
///
/// Initializes a new instance of the DFSIVoicePacket class.
///
@@ -990,7 +986,6 @@ void DFSIVoicePacket::writeNet_LDU1()
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
if (!m_p25->m_trunk->writeRF_TSDU_Grant(group, false, true)) {
if (m_network != NULL)
m_network->resetP25();
@@ -1039,7 +1034,7 @@ void DFSIVoicePacket::writeNet_LDU1()
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueNet(buffer, P25_DFSI_VHDR1_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_DFSI_VHDR1_FRAME_LENGTH_BYTES + 2U, true);
// Generate Voice Header 2
m_netDFSILC.setFrameType(P25_DFSI_VHDR2);
@@ -1047,7 +1042,7 @@ void DFSIVoicePacket::writeNet_LDU1()
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueNet(buffer, P25_DFSI_VHDR2_FRAME_LENGTH_BYTES + 2U);
+ m_p25->addFrame(buffer, P25_DFSI_VHDR2_FRAME_LENGTH_BYTES + 2U, true);
if (m_verbose) {
LogMessage(LOG_NET, P25_HDU_STR " DFSI, dstId = %u, algo = $%02X, kid = $%04X", m_netLC.getDstId(), m_netLC.getAlgId(), m_netLC.getKId());
@@ -1124,7 +1119,8 @@ void DFSIVoicePacket::writeNet_LDU1()
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueNet(buffer, len + 2U);
+
+ m_p25->addFrame(buffer, len + 2U, true);
}
if (m_verbose) {
@@ -1239,7 +1235,8 @@ void DFSIVoicePacket::writeNet_LDU2()
buffer[0U] = modem::TAG_DATA;
buffer[1U] = 0x00U;
- m_p25->writeQueueNet(buffer, len + 2U);
+
+ m_p25->addFrame(buffer, len + 2U, true);
}
if (m_verbose) {