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