diff --git a/dmr/DMRDefines.h b/dmr/DMRDefines.h
index e0f8ba79..ef94cd9d 100644
--- a/dmr/DMRDefines.h
+++ b/dmr/DMRDefines.h
@@ -237,6 +237,21 @@ namespace dmr
const uint8_t MS_DENY_RSN_UNSUPPORTED_SVC = 0x00U;
+ // Random Access Service Kind
+ const uint8_t SVC_KIND_IND_VOICE_CALL = 0x00U; // Individual Voice Call
+ const uint8_t SVC_KIND_GRP_VOICE_CALL = 0x01U; // Group Voice Call
+ const uint8_t SVC_KIND_IND_DATA_CALL = 0x02U; // Individual Data Call
+ const uint8_t SVC_KIND_GRP_DATA_CALL = 0x03U; // Group Data Call
+ const uint8_t SVC_KIND_IND_UDT_DATA_CALL = 0x04U; // Individual UDT Short Data Call
+ const uint8_t SVC_KIND_GRP_UDT_DATA_CALL = 0x05U; // Group UDT Short Data Call
+ const uint8_t SVC_KIND_UDT_SHORT_POLL = 0x06U; // UDT Short Data Polling Service
+ const uint8_t SVC_KIND_STATUS_TRANSPORT = 0x07U; // Status Transport Service
+ const uint8_t SVC_KIND_CALL_DIVERSION = 0x08U; // Call Diversion Service
+ const uint8_t SVC_KIND_CALL_ANSWER = 0x09U; // Call Answer Service
+ const uint8_t SVC_KIND_SUPPLEMENTARY_SVC = 0x0DU; // Supplementary Service
+ const uint8_t SVC_KIND_REG_SVC = 0x0EU; // Registration Service
+ const uint8_t SVC_KIND_CANCEL_CALL = 0x0FU; // Cancel Call Service
+
// Broadcast Announcement Type(s)
const uint8_t BCAST_ANNC_ANN_WD_TSCC = 0x00U; // Announce-WD TSCC Channel
const uint8_t BCAST_ANNC_CALL_TIMER_PARMS = 0x01U; // Specify Call Timer Parameters
diff --git a/dmr/lc/CSBK.cpp b/dmr/lc/CSBK.cpp
index 9f3b75ef..4074364a 100644
--- a/dmr/lc/CSBK.cpp
+++ b/dmr/lc/CSBK.cpp
@@ -153,8 +153,6 @@ bool CSBK::decode(const uint8_t* data)
{
case FID_DMRA:
m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag
- m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; //
- m_CBF = (uint8_t)((csbkValue >> 48) & 0xFFU); // Blocks to Follow
m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
break;
@@ -165,13 +163,15 @@ bool CSBK::decode(const uint8_t* data)
m_supplementData = (((csbkValue >> 56) & 0xFFU) & 0x20U) == 0x20U; // Supplementary Data Flag
m_broadcast = (((csbkValue >> 56) & 0xFFU) & 0x10U) == 0x10U; // Broadcast Flag
m_priority = (((csbkValue >> 56) & 0xFFU) & 0x03U); // Priority
+ m_serviceData = (uint8_t)((csbkValue >> 52U) & 0x0FU); // Service Data
+ m_serviceType = (uint8_t)((csbkValue >> 48U) & 0x0FU); // Service Type
m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
break;
}
case CSBKO_EXT_FNCT:
m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; //
- m_CBF = (uint8_t)((csbkValue >> 48) & 0xFFU); // Blocks to Follow
+ m_serviceType = (uint8_t)((csbkValue >> 48) & 0xFFU); // Service Type
m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
break;
@@ -463,6 +463,7 @@ CSBK::CSBK(SiteData siteData) :
m_priority(0U),
m_broadcast(false),
m_backoffNo(1U),
+ m_serviceData(0U),
m_serviceType(0U),
m_targetAddress(TGT_ADRS_TGID),
m_response(0U),
diff --git a/dmr/lc/CSBK.h b/dmr/lc/CSBK.h
index b5170e3d..069ad9e2 100644
--- a/dmr/lc/CSBK.h
+++ b/dmr/lc/CSBK.h
@@ -109,8 +109,10 @@ namespace dmr
/// Backoff Number.
__PROPERTY(uint8_t, backoffNo, BackoffNo);
+ /// Service Data.
+ __PROPERTY(uint8_t, serviceData, ServiceData);
/// Service Type.
- __PROPERTY(uint8_t, serviceType, serviceType);
+ __PROPERTY(uint8_t, serviceType, ServiceType);
/// Destination/Target address type.
__PROPERTY(uint8_t, targetAddress, TargetAddress);
diff --git a/dmr/packet/ControlSignaling.cpp b/dmr/packet/ControlSignaling.cpp
index dcbf19dc..b3e25139 100644
--- a/dmr/packet/ControlSignaling.cpp
+++ b/dmr/packet/ControlSignaling.cpp
@@ -123,99 +123,111 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len)
}
}
- // Regenerate the CSBK data
- csbk.encode(data + 2U);
-
- // Regenerate the Slot Type
- slotType.encode(data + 2U);
-
- // Convert the Data Sync to be from the BS or MS as needed
- Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
-
- m_slot->m_rfSeqNo = 0U;
-
- data[0U] = modem::TAG_DATA;
- data[1U] = 0x00U;
-
- if (m_slot->m_duplex)
- m_slot->addFrame(data);
-
- m_slot->writeNetwork(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_PRIVATE, srcId, dstId);
-
- if (m_verbose) {
- switch (csbko) {
- case CSBKO_UU_V_REQ:
+ bool handled = false;
+ switch (csbko) {
+ case CSBKO_UU_V_REQ:
+ if (m_verbose) {
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_UU_V_REQ (Unit to Unit Voice Service Request), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ }
+ break;
+ case CSBKO_UU_ANS_RSP:
+ if (m_verbose) {
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_UU_ANS_RSP (Unit to Unit Voice Service Answer Response), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ }
+ break;
+ case CSBKO_RAND:
+ if (csbk.getFID() == FID_DMRA) {
if (m_verbose) {
- LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_UU_V_REQ (Unit to Unit Voice Service Request), src = %u, dst = %s%u",
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u",
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
}
- break;
- case CSBKO_UU_ANS_RSP:
+
+ ::ActivityLog("DMR", true, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
+ } else {
if (m_verbose) {
- LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_UU_ANS_RSP (Unit to Unit Voice Service Answer Response), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), emerg = %u, prio = %u, serviceType = %02X, serviceData = %02X, srcId = %u, dstId = %u",
+ m_slot->m_slotNo, csbk.getEmergency(), csbk.getPriority(), csbk.getServiceType(), csbk.getServiceData(), csbk.getSrcId(), csbk.getDstId());
}
+ }
+ break;
+ case CSBKO_ACK_RSP:
+ if (m_verbose) {
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_ACK_RSP (Acknowledge Response), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ }
+
+ ::ActivityLog("DMR", true, "Slot %u ack response from %u to %u", m_slot->m_slotNo, srcId, dstId);
+ break;
+ case CSBKO_EXT_FNCT:
+ if (m_verbose) {
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u",
+ m_slot->m_slotNo, csbk.getServiceType(), dstId, srcId);
+ }
+
+ // generate activity log entry
+ switch (csbk.getServiceType()) {
+ case DMR_EXT_FNCT_CHECK:
+ ::ActivityLog("DMR", true, "Slot %u radio check request from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_NACK_RSP:
- if (m_verbose) {
- LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_NACK_RSP (Negative Acknowledgment Response), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
- }
+ case DMR_EXT_FNCT_INHIBIT:
+ ::ActivityLog("DMR", true, "Slot %u radio inhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_RAND:
- if (csbk.getFID() == FID_DMRA) {
- if (m_verbose) {
- LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
- }
-
- ::ActivityLog("DMR", true, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
- }
+ case DMR_EXT_FNCT_UNINHIBIT:
+ ::ActivityLog("DMR", true, "Slot %u radio uninhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_ACK_RSP:
- if (m_verbose) {
- LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_ACK_RSP (Acknowledge Response), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
- }
-
- ::ActivityLog("DMR", true, "Slot %u ack response from %u to %u", m_slot->m_slotNo, srcId, dstId);
+ case DMR_EXT_FNCT_CHECK_ACK:
+ ::ActivityLog("DMR", true, "Slot %u radio check response from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_EXT_FNCT:
- if (m_verbose) {
- LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u",
- m_slot->m_slotNo, csbk.getCBF(), dstId, srcId);
- }
-
- // generate activity log entry
- if (csbk.getCBF() == DMR_EXT_FNCT_CHECK) {
- ::ActivityLog("DMR", true, "Slot %u radio check request from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_INHIBIT) {
- ::ActivityLog("DMR", true, "Slot %u radio inhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_UNINHIBIT) {
- ::ActivityLog("DMR", true, "Slot %u radio uninhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_CHECK_ACK) {
- ::ActivityLog("DMR", true, "Slot %u radio check response from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_INHIBIT_ACK) {
- ::ActivityLog("DMR", true, "Slot %u radio inhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_UNINHIBIT_ACK) {
- ::ActivityLog("DMR", true, "Slot %u radio uninhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
+ case DMR_EXT_FNCT_INHIBIT_ACK:
+ ::ActivityLog("DMR", true, "Slot %u radio inhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_PRECCSBK:
- if (m_verbose) {
- LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_PRECCSBK (%s Preamble CSBK), toFollow = %u, src = %u, dst = %s%u",
- m_slot->m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), srcId, gi ? "TG " : "", dstId);
- }
+ case DMR_EXT_FNCT_UNINHIBIT_ACK:
+ ::ActivityLog("DMR", true, "Slot %u radio uninhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
default:
- LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, unhandled CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk.getFID());
+ LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), unhandled op, op = $%02X", m_slot->m_slotNo, csbk.getServiceType());
break;
}
+ break;
+ case CSBKO_NACK_RSP:
+ if (m_verbose) {
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_NACK_RSP (Negative Acknowledgment Response), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ }
+ break;
+ case CSBKO_PRECCSBK:
+ if (m_verbose) {
+ LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_PRECCSBK (%s Preamble CSBK), toFollow = %u, src = %u, dst = %s%u",
+ m_slot->m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), srcId, gi ? "TG " : "", dstId);
+ }
+ break;
+ default:
+ LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, unhandled CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk.getFID());
+ // should we drop the CSBK and not repeat it?
+ break;
+ }
+
+ if (!handled) {
+ // Regenerate the CSBK data
+ csbk.encode(data + 2U);
+
+ // Regenerate the Slot Type
+ slotType.encode(data + 2U);
+
+ // Convert the Data Sync to be from the BS or MS as needed
+ Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
+
+ m_slot->m_rfSeqNo = 0U;
+
+ data[0U] = modem::TAG_DATA;
+ data[1U] = 0x00U;
+
+ if (m_slot->m_duplex)
+ m_slot->addFrame(data);
+
+ m_slot->writeNetwork(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_PRIVATE, srcId, dstId);
}
return true;
@@ -255,119 +267,131 @@ void ControlSignaling::processNetwork(const data::Data & dmrData)
CHECK_TG_HANG(dstId);
- // Regenerate the CSBK data
- csbk.encode(data + 2U);
-
- // Regenerate the Slot Type
- SlotType slotType;
- slotType.decode(data + 2U);
- slotType.setColorCode(m_slot->m_colorCode);
- slotType.encode(data + 2U);
-
- // Convert the Data Sync to be from the BS or MS as needed
- Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
-
- data[0U] = modem::TAG_DATA;
- data[1U] = 0x00U;
-
- if (csbko == CSBKO_PRECCSBK && csbk.getDataContent()) {
- uint32_t cbf = NO_PREAMBLE_CSBK + csbk.getCBF() - 1U;
- for (uint32_t i = 0U; i < NO_PREAMBLE_CSBK; i++, cbf--) {
- // Change blocks to follow
- csbk.setCBF(cbf);
-
- // Regenerate the CSBK data
- csbk.encode(data + 2U);
-
- // Regenerate the Slot Type
- SlotType slotType;
- slotType.decode(data + 2U);
- slotType.setColorCode(m_slot->m_colorCode);
- slotType.encode(data + 2U);
-
- // Convert the Data Sync to be from the BS or MS as needed
- Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
-
- m_slot->addFrame(data, true);
+ bool handled = false;
+ switch (csbko) {
+ case CSBKO_UU_V_REQ:
+ if (m_verbose) {
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_UU_V_REQ (Unit to Unit Voice Service Request), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
}
- }
- else
- m_slot->addFrame(data, true);
-
- if (m_verbose) {
- switch (csbko) {
- case CSBKO_UU_V_REQ:
+ break;
+ case CSBKO_UU_ANS_RSP:
+ if (m_verbose) {
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_UU_ANS_RSP (Unit to Unit Voice Service Answer Response), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ }
+ break;
+ case CSBKO_RAND:
+ if (csbk.getFID() == FID_DMRA) {
if (m_verbose) {
- LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_UU_V_REQ (Unit to Unit Voice Service Request), src = %u, dst = %s%u",
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u",
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
}
- break;
- case CSBKO_UU_ANS_RSP:
+
+ ::ActivityLog("DMR", false, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
+ } else {
if (m_verbose) {
- LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_UU_ANS_RSP (Unit to Unit Voice Service Answer Response), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), emerg = %u, prio = %u, serviceType = %02X, serviceData = %02X, srcId = %u, dstId = %u",
+ m_slot->m_slotNo, csbk.getEmergency(), csbk.getPriority(), csbk.getServiceType(), csbk.getServiceData(), csbk.getSrcId(), csbk.getDstId());
}
+ }
+ break;
+ case CSBKO_ACK_RSP:
+ if (m_verbose) {
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_ACK_RSP (Acknowledge Response), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ }
+
+ ::ActivityLog("DMR", false, "Slot %u ack response from %u to %u", m_slot->m_slotNo, srcId, dstId);
+ break;
+ case CSBKO_EXT_FNCT:
+ if (m_verbose) {
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u",
+ m_slot->m_slotNo, csbk.getCBF(), dstId, srcId);
+ }
+
+ // generate activity log entry
+ switch (csbk.getServiceType()) {
+ case DMR_EXT_FNCT_CHECK:
+ ::ActivityLog("DMR", false, "Slot %u radio check request from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_NACK_RSP:
- if (m_verbose) {
- LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_NACK_RSP (Negative Acknowledgment Response), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
- }
+ case DMR_EXT_FNCT_INHIBIT:
+ ::ActivityLog("DMR", false, "Slot %u radio inhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_RAND:
- if (csbk.getFID() == FID_DMRA) {
- if (m_verbose) {
- LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
- }
-
- ::ActivityLog("DMR", false, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
- }
+ case DMR_EXT_FNCT_UNINHIBIT:
+ ::ActivityLog("DMR", false, "Slot %u radio uninhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_ACK_RSP:
- if (m_verbose) {
- LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_ACK_RSP (Acknowledge Response), src = %u, dst = %s%u",
- m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
- }
-
- ::ActivityLog("DMR", false, "Slot %u ack response from %u to %u", m_slot->m_slotNo, srcId, dstId);
+ case DMR_EXT_FNCT_CHECK_ACK:
+ ::ActivityLog("DMR", false, "Slot %u radio check response from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_EXT_FNCT:
- if (m_verbose) {
- LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u",
- m_slot->m_slotNo, csbk.getCBF(), dstId, srcId);
- }
-
- // generate activity log entry
- if (csbk.getCBF() == DMR_EXT_FNCT_CHECK) {
- ::ActivityLog("DMR", false, "Slot %u radio check request from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_INHIBIT) {
- ::ActivityLog("DMR", false, "Slot %u radio inhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_UNINHIBIT) {
- ::ActivityLog("DMR", false, "Slot %u radio uninhibit request from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_CHECK_ACK) {
- ::ActivityLog("DMR", false, "Slot %u radio check response from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_INHIBIT_ACK) {
- ::ActivityLog("DMR", false, "Slot %u radio inhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
- else if (csbk.getCBF() == DMR_EXT_FNCT_UNINHIBIT_ACK) {
- ::ActivityLog("DMR", false, "Slot %u radio uninhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
- }
+ case DMR_EXT_FNCT_INHIBIT_ACK:
+ ::ActivityLog("DMR", false, "Slot %u radio inhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
- case CSBKO_PRECCSBK:
- if (m_verbose) {
- LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_PRECCSBK (%s Preamble CSBK), toFollow = %u, src = %u, dst = %s%u",
- m_slot->m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), srcId, gi ? "TG " : "", dstId);
- }
+ case DMR_EXT_FNCT_UNINHIBIT_ACK:
+ ::ActivityLog("DMR", false, "Slot %u radio uninhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId);
break;
default:
- LogWarning(LOG_NET, "DMR Slot %u, DT_CSBK, unhandled network CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk.getFID());
+ LogWarning(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), unhandled op, op = $%02X", m_slot->m_slotNo, csbk.getServiceType());
break;
}
+ break;
+ case CSBKO_NACK_RSP:
+ if (m_verbose) {
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_NACK_RSP (Negative Acknowledgment Response), src = %u, dst = %s%u",
+ m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
+ }
+ break;
+ case CSBKO_PRECCSBK:
+ if (m_verbose) {
+ LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_PRECCSBK (%s Preamble CSBK), toFollow = %u, src = %u, dst = %s%u",
+ m_slot->m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), srcId, gi ? "TG " : "", dstId);
+ }
+ break;
+ default:
+ LogWarning(LOG_NET, "DMR Slot %u, DT_CSBK, unhandled network CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk.getFID());
+ // should we drop the CSBK and not repeat it?
+ break;
+ }
+
+ if (!handled) {
+ // Regenerate the CSBK data
+ csbk.encode(data + 2U);
+
+ // Regenerate the Slot Type
+ SlotType slotType;
+ slotType.decode(data + 2U);
+ slotType.setColorCode(m_slot->m_colorCode);
+ slotType.encode(data + 2U);
+
+ // Convert the Data Sync to be from the BS or MS as needed
+ Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
+
+ data[0U] = modem::TAG_DATA;
+ data[1U] = 0x00U;
+
+ if (csbko == CSBKO_PRECCSBK && csbk.getDataContent()) {
+ uint32_t cbf = NO_PREAMBLE_CSBK + csbk.getCBF() - 1U;
+ for (uint32_t i = 0U; i < NO_PREAMBLE_CSBK; i++, cbf--) {
+ // Change blocks to follow
+ csbk.setCBF(cbf);
+
+ // Regenerate the CSBK data
+ csbk.encode(data + 2U);
+
+ // Regenerate the Slot Type
+ SlotType slotType;
+ slotType.decode(data + 2U);
+ slotType.setColorCode(m_slot->m_colorCode);
+ slotType.encode(data + 2U);
+
+ // Convert the Data Sync to be from the BS or MS as needed
+ Sync::addDMRDataSync(data + 2U, m_slot->m_duplex);
+
+ m_slot->addFrame(data, true);
+ }
+ }
+ else
+ m_slot->addFrame(data, true);
}
}
else {
diff --git a/host/Host.cpp b/host/Host.cpp
index 42006eb6..83e3bf36 100644
--- a/host/Host.cpp
+++ b/host/Host.cpp
@@ -411,6 +411,11 @@ int Host::run()
LogInfo(" TX Hang: %us", txHang);
LogInfo(" Queue Size: %u (%u bytes)", queueSize, queueSizeBytes);
+ // forcibly enable beacons when TSCC is enabled but not in dedicated mode
+ if (m_dmrTSCCData && !dmrCtrlChannel && !m_dmrBeacons) {
+ m_dmrBeacons = true;
+ }
+
LogInfo(" Roaming Beacons: %s", m_dmrBeacons ? "yes" : "no");
if (m_dmrBeacons) {
uint32_t dmrBeaconInterval = dmrProtocol["beacons"]["interval"].as(60U);
@@ -566,17 +571,17 @@ int Host::run()
bool nxdnVerbose = nxdnProtocol["verbose"].as(true);
bool nxdnDebug = nxdnProtocol["debug"].as(false);
- // clamp queue size to no less then 24 and no greater the 100
- if (queueSize <= 24U) {
- LogWarning(LOG_HOST, "NXDN queue size must be greater then 24 frames, defaulting to 24 frames!");
- queueSize = 24U;
+ // clamp queue size to no less then 5 and no greater the 100 frames
+ if (queueSize <= 10U) {
+ LogWarning(LOG_HOST, "NXDN queue size must be greater then 10 frames, defaulting to 10 frames!");
+ queueSize = 10U;
}
if (queueSize > 100U) {
LogWarning(LOG_HOST, "NXDN queue size must be less then 100 frames, defaulting to 100 frames!");
queueSize = 100U;
}
- if (queueSize > 60U) {
- LogWarning(LOG_HOST, "NXDN queue size is excessive, >60 frames!");
+ if (queueSize > 30U) {
+ LogWarning(LOG_HOST, "NXDN queue size is excessive, >30 frames!");
}
uint32_t queueSizeBytes = queueSize * (nxdn::NXDN_FRAME_LENGTH_BYTES * 5U);
@@ -725,21 +730,8 @@ int Host::run()
bool killed = false;
if (!g_killed) {
- // fixed more or P25 control channel will force a state change
- if (m_fixedMode || m_p25CtrlChannel) {
-#if defined(ENABLE_P25)
- if (m_p25CtrlChannel) {
- m_fixedMode = true;
- setState(STATE_P25);
- }
-#endif // defined(ENABLE_P25)
-#if defined(ENABLE_NXDN)
- if (m_nxdnCtrlChannel) {
- m_fixedMode = true;
- setState(STATE_NXDN);
- }
-#endif // defined(ENABLE_NXDN)
-
+ // fixed mode will force a state change
+ if (m_fixedMode) {
#if defined(ENABLE_DMR)
if (dmr != NULL)
setState(STATE_DMR);
@@ -754,6 +746,12 @@ int Host::run()
#endif // defined(ENABLE_NXDN)
}
else {
+#if defined(ENABLE_DMR)
+ if (m_dmrCtrlChannel) {
+ m_fixedMode = true;
+ setState(STATE_DMR);
+ }
+#endif // defined(ENABLE_DMR)
#if defined(ENABLE_P25)
if (m_p25CtrlChannel) {
m_fixedMode = true;
@@ -976,9 +974,11 @@ int Host::run()
}
// if there is a P25 CC running; halt the CC
- if (p25->getCCRunning() && !p25->getCCHalted()) {
- p25->setCCHalted(true);
- INTERRUPT_P25_CONTROL;
+ if (p25 != NULL) {
+ if (p25->getCCRunning() && !p25->getCCHalted()) {
+ p25->setCCHalted(true);
+ INTERRUPT_P25_CONTROL;
+ }
}
// if there is a NXDN CC running; halt the CC