diff --git a/CMakeLists.txt b/CMakeLists.txt
index 317796ff..2266788c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,6 +49,8 @@ file(GLOB dvmhost_SRC
"nxdn/channel/*.cpp"
"nxdn/lc/*.h"
"nxdn/lc/*.cpp"
+ "nxdn/lc/rcch/*.h"
+ "nxdn/lc/rcch/*.cpp"
"nxdn/packet/*.h"
"nxdn/packet/*.cpp"
diff --git a/dmr/lc/csbk/CSBKFactory.h b/dmr/lc/csbk/CSBKFactory.h
index e7c78511..d90f6643 100644
--- a/dmr/lc/csbk/CSBKFactory.h
+++ b/dmr/lc/csbk/CSBKFactory.h
@@ -69,7 +69,7 @@ namespace dmr
private:
///
- static std::unique_ptr decode(CSBK* tsbk, const uint8_t* data);
+ static std::unique_ptr decode(CSBK* csbk, const uint8_t* data);
};
} // namespace csbk
} // namespace lc
diff --git a/nxdn/Control.cpp b/nxdn/Control.cpp
index 25fd41ee..ed3a9030 100644
--- a/nxdn/Control.cpp
+++ b/nxdn/Control.cpp
@@ -34,6 +34,7 @@
#include "nxdn/acl/AccessControl.h"
#include "nxdn/channel/SACCH.h"
#include "nxdn/channel/FACCH1.h"
+#include "nxdn/lc/RCCH.h"
#include "nxdn/lc/RTCH.h"
#include "nxdn/Sync.h"
#include "nxdn/NXDNUtils.h"
@@ -142,12 +143,12 @@ Control::Control(uint32_t ran, uint32_t callHang, uint32_t queueSize, uint32_t t
acl::AccessControl::init(m_ridLookup, m_tidLookup);
- m_voice = new Voice(this, network, dumpRCCHData, debug, verbose);
- m_trunk = new Trunk(this, network, dumpRCCHData, debug, verbose);
+ m_voice = new Voice(this, network, debug, verbose);
+ m_trunk = new Trunk(this, network, debug, verbose);
m_data = new Data(this, network, debug, verbose);
- m_rfLC.setVerbose(m_dumpRCCH);
- m_netLC.setVerbose(m_dumpRCCH);
+ lc::RCCH::setVerbose(dumpRCCHData);
+ lc::RTCH::setVerbose(dumpRCCHData);
}
///
@@ -187,13 +188,11 @@ void Control::reset()
m_queue.clear();
m_rfMask = 0x00U;
- m_rfLC.setVerbose(m_dumpRCCH);
m_rfLC.reset();
m_netState = RS_NET_IDLE;
m_netMask = 0x00U;
- m_netLC.setVerbose(m_dumpRCCH);
m_netLC.reset();
}
@@ -248,6 +247,9 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
m_siteData = SiteData(locId, channelId, channelNo, serviceClass, false);
m_siteData.setCallsign(cwCallsign);
+ lc::RCCH::setSiteData(m_siteData);
+ lc::RCCH::setCallsign(cwCallsign);
+
std::vector entries = m_idenTable->list();
for (auto it = entries.begin(); it != entries.end(); ++it) {
lookups::IdenTable entry = *it;
@@ -281,11 +283,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
if (m_data != nullptr) {
m_data->resetRF();
}
-
- if (m_trunk != nullptr) {
- m_trunk->resetRF();
- m_trunk->resetNet();
- }
}
///
@@ -613,6 +610,8 @@ void Control::setDebugVerbose(bool debug, bool verbose)
void Control::setRCCHVerbose(bool verbose)
{
m_dumpRCCH = verbose;
+ lc::RCCH::setVerbose(verbose);
+ lc::RTCH::setVerbose(verbose);
}
// ---------------------------------------------------------------------------
@@ -731,8 +730,8 @@ bool Control::writeRF_ControlData()
return false;
}
- const uint8_t maxSeq = m_trunk->m_rfLC.getBcchCnt() + (m_trunk->m_rfLC.getCcchPagingCnt() + m_trunk->m_rfLC.getCcchMultiCnt()) *
- m_trunk->m_rfLC.getRcchGroupingCnt() * m_trunk->m_rfLC.getRcchIterateCount();
+ const uint8_t maxSeq = m_trunk->m_bcchCnt + (m_trunk->m_ccchPagingCnt + m_trunk->m_ccchMultiCnt) *
+ m_trunk->m_rcchGroupingCnt * m_trunk->m_rcchIterateCnt;
if (m_ccSeq == maxSeq) {
m_ccSeq = 0U;
}
diff --git a/nxdn/lc/RCCH.cpp b/nxdn/lc/RCCH.cpp
index b317d010..8ce5691e 100644
--- a/nxdn/lc/RCCH.cpp
+++ b/nxdn/lc/RCCH.cpp
@@ -39,6 +39,15 @@ using namespace nxdn::lc;
#include
#include
+// ---------------------------------------------------------------------------
+// Static Class Members
+// ---------------------------------------------------------------------------
+
+bool RCCH::m_verbose = false;
+
+uint8_t *RCCH::m_siteCallsign = nullptr;
+SiteData RCCH::m_siteData = SiteData();
+
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
@@ -47,7 +56,7 @@ using namespace nxdn::lc;
/// Initializes a copy instance of the RCCH class.
///
///
-RCCH::RCCH(const RCCH& data) : RCCH(SiteData())
+RCCH::RCCH(const RCCH& data) : RCCH()
{
copy(data);
}
@@ -55,23 +64,28 @@ RCCH::RCCH(const RCCH& data) : RCCH(SiteData())
///
/// Initializes a new instance of the RCCH class.
///
-///
-///
-RCCH::RCCH(SiteData siteData, lookups::IdenTable entry) : RCCH(siteData)
-{
- m_siteIdenEntry = entry;
-}
-
-///
-/// Initializes a new instance of the RCCH class.
-///
-///
-///
-///
-RCCH::RCCH(SiteData siteData, lookups::IdenTable entry, bool verbose) : RCCH(siteData)
+RCCH::RCCH() :
+ m_messageType(MESSAGE_TYPE_IDLE),
+ m_srcId(0U),
+ m_dstId(0U),
+ m_locId(0U),
+ m_regOption(0U),
+ m_version(0U),
+ m_causeRsp(NXDN_CAUSE_MM_REG_ACCEPTED),
+ m_grpVchNo(0U),
+ m_callType(CALL_TYPE_UNSPECIFIED),
+ m_emergency(false),
+ m_encrypted(false),
+ m_priority(false),
+ m_group(true),
+ m_duplex(false),
+ m_transmissionMode(TRANSMISSION_MODE_4800),
+ m_siteIdenEntry()
{
- m_verbose = verbose;
- m_siteIdenEntry = entry;
+ if (m_siteCallsign == nullptr) {
+ m_siteCallsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES];
+ ::memset(m_siteCallsign, 0x00U, NXDN_CALLSIGN_LENGTH_BYTES);
+ }
}
///
@@ -83,32 +97,43 @@ RCCH::~RCCH()
}
///
-/// Equals operator.
+/// Sets the callsign.
///
-///
-///
-RCCH& RCCH::operator=(const RCCH& data)
+/// Callsign.
+void RCCH::setCallsign(std::string callsign)
{
- if (&data != this) {
- copy(data);
+ if (m_siteCallsign == nullptr) {
+ m_siteCallsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES];
+ ::memset(m_siteCallsign, 0x00U, NXDN_CALLSIGN_LENGTH_BYTES);
}
- return *this;
+ uint32_t idLength = callsign.length();
+ if (idLength > 0) {
+ ::memset(m_siteCallsign, 0x20U, NXDN_CALLSIGN_LENGTH_BYTES);
+
+ if (idLength > NXDN_CALLSIGN_LENGTH_BYTES)
+ idLength = NXDN_CALLSIGN_LENGTH_BYTES;
+ for (uint32_t i = 0; i < idLength; i++)
+ m_siteCallsign[i] = callsign[i];
+ }
}
+/// ---------------------------------------------------------------------------
+// Protected Class Members
+// ---------------------------------------------------------------------------
+
///
-/// Decode call link control data.
+/// Internal helper to decode a trunking signalling block.
///
///
+///
///
///
/// True, if RCCH was decoded, otherwise false.
-void RCCH::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+void RCCH::decode(const uint8_t* data, uint8_t* rcch, uint32_t length, uint32_t offset)
{
assert(data != nullptr);
-
- uint8_t rcch[22U];
- ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+ assert(rcch != nullptr);
for (uint32_t i = 0U; i < length; i++, offset++) {
bool b = READ_BIT(data, offset);
@@ -119,23 +144,22 @@ void RCCH::decode(const uint8_t* data, uint32_t length, uint32_t offset)
Utils::dump(2U, "Decoded RCCH Data", rcch, NXDN_RCCH_LC_LENGTH_BYTES);
}
- decodeLC(rcch);
+ m_messageType = data[0U] & 0x3FU; // Message Type
}
///
-/// Encode call link control data.
+/// Internal helper to encode a RCCH.
///
///
+///
///
///
-void RCCH::encode(uint8_t* data, uint32_t length, uint32_t offset)
+void RCCH::encode(uint8_t* data, const uint8_t* rcch, uint32_t length, uint32_t offset)
{
assert(data != nullptr);
+ assert(rcch != nullptr);
- uint8_t rcch[22U];
- ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
-
- encodeLC(rcch);
+ data[0U] = m_messageType & 0x3FU; // Message Type
for (uint32_t i = 0U; i < length; i++, offset++) {
bool b = READ_BIT(rcch, i);
@@ -147,315 +171,13 @@ void RCCH::encode(uint8_t* data, uint32_t length, uint32_t offset)
}
}
-///
-///
-///
-void RCCH::reset()
-{
- m_messageType = MESSAGE_TYPE_IDLE;
-
- m_srcId = 0U;
- m_dstId = 0U;
-
- m_locId = 0U;
- m_regOption = 0U;
-
- m_version = 0U;
-
- m_causeRsp = NXDN_CAUSE_MM_REG_ACCEPTED;
-
- m_grpVchNo = 0U;
-
- m_emergency = false;
- m_encrypted = false;
- m_priority = false;
- m_group = true;
- m_duplex = false;
- m_transmissionMode = TRANSMISSION_MODE_4800;
-}
-
-///
-/// Sets the callsign.
-///
-/// Callsign.
-void RCCH::setCallsign(std::string callsign)
-{
- uint32_t idLength = callsign.length();
- if (idLength > 0) {
- ::memset(m_siteCallsign, 0x20U, NXDN_CALLSIGN_LENGTH_BYTES);
-
- if (idLength > NXDN_CALLSIGN_LENGTH_BYTES)
- idLength = NXDN_CALLSIGN_LENGTH_BYTES;
- for (uint32_t i = 0; i < idLength; i++)
- m_siteCallsign[i] = callsign[i];
- }
-}
-
-/// ---------------------------------------------------------------------------
-// Private Class Members
-// ---------------------------------------------------------------------------
-
-///
-/// Initializes a new instance of the RCCH class.
-///
-RCCH::RCCH() : RCCH(SiteData())
-{
- /* stub */
-}
-
-///
-/// Initializes a new instance of the RCCH class.
-///
-///
-RCCH::RCCH(SiteData siteData) :
- m_verbose(false),
- m_messageType(MESSAGE_TYPE_IDLE),
- m_srcId(0U),
- m_dstId(0U),
- m_locId(0U),
- m_regOption(0U),
- m_version(0U),
- m_causeRsp(NXDN_CAUSE_MM_REG_ACCEPTED),
- m_grpVchNo(0U),
- m_callType(CALL_TYPE_UNSPECIFIED),
- m_emergency(false),
- m_encrypted(false),
- m_priority(false),
- m_group(true),
- m_duplex(false),
- m_transmissionMode(TRANSMISSION_MODE_4800),
- m_siteData(siteData),
- m_siteIdenEntry(),
- m_bcchCnt(1U),
- m_rcchGroupingCnt(1U),
- m_ccchPagingCnt(2U),
- m_ccchMultiCnt(2U),
- m_rcchIterateCnt(2U)
-{
- m_siteCallsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES];
- ::memset(m_siteCallsign, 0x00U, NXDN_CALLSIGN_LENGTH_BYTES);
- setCallsign(siteData.callsign());
-}
-
-///
-/// Decode link control.
-///
-///
-///
-bool RCCH::decodeLC(const uint8_t* data)
-{
- assert(data != nullptr);
-
- m_messageType = data[0U] & 0x3FU; // Message Type
-
- // message type opcodes
- switch (m_messageType) {
- case RTCH_MESSAGE_TYPE_VCALL:
- case RCCH_MESSAGE_TYPE_VCALL_CONN:
- m_callType = (data[2U] >> 5) & 0x07U; // Call Type
- m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
- m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
- m_duplex = (data[2U] & 0x10U) == 0x10U; // Half/Full Duplex Flag
- m_transmissionMode = (data[2U] & 0x07U); // Transmission Mode
- m_srcId = (uint16_t)((data[3U] << 8) | data[4U]) & 0xFFFFU; // Source Radio Address
- m_dstId = (uint16_t)((data[5U] << 8) | data[6U]) & 0xFFFFU; // Target Radio Address
- break;
- case RTCH_MESSAGE_TYPE_DCALL_HDR:
- m_callType = (data[2U] >> 5) & 0x07U; // Call Type
- m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
- m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
- m_duplex = (data[2U] & 0x10U) == 0x10U; // Half/Full Duplex Flag
- m_transmissionMode = (data[2U] & 0x07U); // Transmission Mode
- m_srcId = (uint16_t)((data[3U] << 8) | data[4U]) & 0xFFFFU; // Source Radio Address
- m_dstId = (uint16_t)((data[5U] << 8) | data[6U]) & 0xFFFFU; // Target Radio Address
- break;
- case MESSAGE_TYPE_IDLE:
- break;
- case RCCH_MESSAGE_TYPE_REG:
- m_regOption = data[1U] >> 3; // Registration Option
- m_locId = (uint16_t)((data[2U] << 8) | data[3U]) & 0xFFFFU; // Location ID
- m_srcId = (uint16_t)((data[4U] << 8) | data[5U]) & 0xFFFFU; // Source Radio Address
- m_dstId = (uint16_t)((data[6U] << 8) | data[7U]) & 0xFFFFU; // Target Radio Address
- // bryanb: maybe process subscriber type? (byte 8 and 9)
- m_version = data[10U]; // Version
- break;
- case RCCH_MESSAGE_TYPE_REG_C:
- m_regOption = data[1U] >> 3; // Registration Option
- m_locId = (uint16_t)((data[2U] << 8) | data[3U]) & 0xFFFFU; // Location ID
- m_srcId = (uint16_t)((data[4U] << 8) | data[5U]) & 0xFFFFU; // Source Radio Address
- break;
- case RCCH_MESSAGE_TYPE_GRP_REG:
- m_regOption = data[1U]; // Group Registration Option
- m_srcId = (uint16_t)((data[2U] << 8) | data[3U]) & 0xFFFFU; // Source Radio Address
- m_dstId = (uint16_t)((data[4U] << 8) | data[5U]) & 0xFFFFU; // Target Radio Address
- break;
- default:
- LogError(LOG_NXDN, "RCCH::decodeRCCH(), unknown RCCH value, messageType = $%02X", m_messageType);
- return false;
- }
-
- return true;
-}
-
-///
-/// Encode link control.
-///
-///
-void RCCH::encodeLC(uint8_t* data)
-{
- assert(data != nullptr);
-
- data[0U] = m_messageType & 0x3FU; // Message Type
-
- // message type opcodes
- switch (m_messageType) {
- case RTCH_MESSAGE_TYPE_VCALL:
- case RCCH_MESSAGE_TYPE_VCALL_CONN:
- data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
- (m_priority ? 0x20U : 0x00U); // Priority Flag
- data[2U] = ((m_callType & 0x07U) << 5) + // Call Type
- (m_duplex ? 0x10U : 0x00U) + // Half/Full Duplex Flag
- (m_transmissionMode & 0x07U); // Transmission Mode
-
- data[3U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
- data[4U] = (m_srcId >> 0U) & 0xFFU; // ...
- data[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
- data[6U] = (m_dstId >> 0U) & 0xFFU; // ...
-
- data[7U] = m_causeRsp; // Cause (VD)
- data[9U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
- data[10U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- break;
- case RCCH_MESSAGE_TYPE_VCALL_ASSGN:
- case RCCH_MESSAGE_TYPE_DCALL_ASSGN:
- data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
- (m_priority ? 0x20U : 0x00U); // Priority Flag
- data[2U] = ((m_callType & 0x07U) << 5) + // Call Type
- (m_duplex ? 0x10U : 0x00U) + // Half/Full Duplex Flag
- (m_transmissionMode & 0x07U); // Transmission Mode
-
- data[3U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
- data[4U] = (m_srcId >> 0U) & 0xFFU; // ...
- data[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
- data[6U] = (m_dstId >> 0U) & 0xFFU; // ...
-
- data[7U] = (m_grpVchNo >> 10) & 0x03U; // Channel
- data[8U] = (m_grpVchNo & 0xFFU); // ...
-
- data[10U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
- data[11U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- break;
- case RTCH_MESSAGE_TYPE_DCALL_HDR:
- data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
- (m_priority ? 0x20U : 0x00U); // Priority Flag
- data[2U] = ((m_callType & 0x07U) << 5) + // Call Type
- (m_duplex ? 0x10U : 0x00U) + // Half/Full Duplex Flag
- (m_transmissionMode & 0x07U); // Transmission Mode
-
- data[3U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
- data[4U] = (m_srcId >> 0U) & 0xFFU; // ...
- data[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
- data[6U] = (m_dstId >> 0U) & 0xFFU; // ...
-
- data[7U] = m_causeRsp; // Cause (VD)
- data[9U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
- data[10U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- break;
- case MESSAGE_TYPE_IDLE:
- break;
- case MESSAGE_TYPE_DST_ID_INFO:
- data[1U] = 0xC0U + NXDN_CALLSIGN_LENGTH_BYTES; // Station ID Option - Start / End / Character Count
- data[2U] = (m_siteCallsign[0]); // Character 0
- for (uint8_t i = 1; i < NXDN_CALLSIGN_LENGTH_BYTES; i++) {
- data[i + 2U] = m_siteCallsign[i]; // Character 1 - 7
- }
- break;
- case RCCH_MESSAGE_TYPE_SITE_INFO:
- {
- data[1U] = (m_siteData.locId() >> 16) & 0xFFU; // Location ID
- data[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...
- data[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- data[4U] = ((m_bcchCnt & 0x03U) << 6) + // Channel Structure - Number of BCCH
- ((m_rcchGroupingCnt & 0x07U) << 3) + // ... - Number of Grouping
- (((m_ccchPagingCnt >> 1) & 0x07U) << 0); // ... - Number of Paging Frames
- data[5U] = ((m_ccchPagingCnt & 0x01U) << 7) + // ... - Number of Paging Frames
- ((m_ccchMultiCnt & 0x07U) << 4) + // ... - Number of Multipurpose Frames
- ((m_rcchIterateCnt & 0x0FU) << 0); // ... - Number of Iteration
-
- data[6U] = m_siteData.serviceClass(); // Service Information
- data[7U] = (m_siteData.netActive() ? NXDN_SIF2_IP_NETWORK : 0x00U); // ...
-
- // bryanb: this is currently fixed -- maybe dynamic in the future
- data[8U] = 0U; // Restriction Information - No access restriction / No cycle restriction
- data[9U] = 0x08U; // ... - No group restriction / GMS; Location Registration Restriction
- data[10U] = (!m_siteData.netActive() ? 0x01U : 0x00U); // ... - No group ratio restriction / No delay time extension / ISO
-
- // bryanb: this is currently fixed -- maybe dynamic in the future
- data[11U] = NXDN_CH_ACCESS_BASE_FREQ_SYS_DEFINED; // Channel Access Information - Channel Version / Sys Defined Step / Sys Defined Base Freq
-
- data[14U] = 1U; // Version
-
- uint16_t channelNo = m_siteData.channelNo() & 0x3FFU;
- data[15U] = (channelNo >> 6) & 0x0FU; // 1st Control Channel
- data[16U] = (channelNo & 0x3FU) << 2; // ...
- }
- break;
- case MESSAGE_TYPE_SRV_INFO:
- data[1U] = (m_siteData.locId() >> 16) & 0xFFU; // Location ID
- data[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...
- data[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- data[4U] = m_siteData.serviceClass(); // Service Information
- data[5U] = (m_siteData.netActive() ? NXDN_SIF2_IP_NETWORK : 0x00U); // ...
-
- // bryanb: this is currently fixed -- maybe dynamic in the future
- data[6U] = 0U; // Restriction Information - No access restriction / No cycle restriction
- data[7U] = 0x08U; // ... - No group restriction / GMS; Location Registration Restriction
- data[8U] = (!m_siteData.netActive() ? 0x01U : 0x00U); // ... - No group ratio restriction / No delay time extension / ISO
- break;
- case RCCH_MESSAGE_TYPE_REG:
- data[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...
- data[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- data[4U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
- data[5U] = (m_srcId >> 0U) & 0xFFU; // ...
- data[6U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
- data[7U] = (m_dstId >> 0U) & 0xFFU; // ...
- data[8U] = m_causeRsp; // Cause (MM)
- break;
- case RCCH_MESSAGE_TYPE_REG_C:
- data[2U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
- data[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- data[4U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
- data[5U] = (m_dstId >> 0U) & 0xFFU; // ...
- data[6U] = m_causeRsp; // Cause (MM)
- break;
- case RCCH_MESSAGE_TYPE_REG_COMM:
- data[2U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
- data[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- data[4U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
- data[5U] = (m_dstId >> 0U) & 0xFFU; // ...
- break;
- case RCCH_MESSAGE_TYPE_GRP_REG:
- data[2U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
- data[3U] = (m_srcId >> 0U) & 0xFFU; // ...
- data[4U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
- data[5U] = (m_dstId >> 0U) & 0xFFU; // ...
- data[6U] = m_causeRsp; // Cause (MM)
- data[8U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
- data[9U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
- break;
- default:
- LogError(LOG_NXDN, "RCCH::encodeRCCH(), unknown RCCH value, messageType = $%02X", m_messageType);
- return;
- }
-}
-
//
/// Internal helper to copy the the class.
///
///
void RCCH::copy(const RCCH& data)
{
- m_verbose = data.m_verbose;
+ m_messageType = data.m_messageType;
m_srcId = data.m_srcId;
m_dstId = data.m_dstId;
@@ -479,19 +201,5 @@ void RCCH::copy(const RCCH& data)
m_transmissionMode = data.m_transmissionMode;
- m_siteData = data.m_siteData;
m_siteIdenEntry = data.m_siteIdenEntry;
-
- delete[] m_siteCallsign;
-
- uint8_t* callsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES];
- ::memcpy(callsign, data.m_siteCallsign, NXDN_CALLSIGN_LENGTH_BYTES);
-
- m_siteCallsign = callsign;
-
- m_bcchCnt = data.m_bcchCnt;
- m_rcchGroupingCnt = data.m_rcchGroupingCnt;
- m_ccchPagingCnt = data.m_ccchPagingCnt;
- m_ccchMultiCnt = data.m_ccchMultiCnt;
- m_rcchIterateCnt = data.m_rcchIterateCnt;
}
diff --git a/nxdn/lc/RCCH.h b/nxdn/lc/RCCH.h
index b95c2ca1..ce9b1ad2 100644
--- a/nxdn/lc/RCCH.h
+++ b/nxdn/lc/RCCH.h
@@ -48,107 +48,88 @@ namespace nxdn
public:
/// Initializes a copy instance of the RCCH class.
RCCH(const RCCH& data);
- /// Initializes a new instance of the TSBK class.
- RCCH(SiteData siteData, lookups::IdenTable entry);
- /// Initializes a new instance of the TSBK class.
- RCCH(SiteData siteData, lookups::IdenTable entry, bool verbose);
+ /// Initializes a new instance of the RCCH class.
+ RCCH();
/// Finalizes a instance of the RCCH class.
- ~RCCH();
-
- /// Equals operator.
- RCCH& operator=(const RCCH& data);
+ virtual ~RCCH();
/// Decode layer 3 data.
- void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U) = 0;
/// Encode layer 3 data.
- void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U) = 0;
- ///
- void reset();
+ /// Sets the flag indicating verbose log output.
+ static void setVerbose(bool verbose) { m_verbose = verbose; }
+ /** Local Site data */
/// Sets the callsign.
- void setCallsign(std::string callsign);
+ static void setCallsign(std::string callsign);
- public:
- /// Flag indicating verbose log output.
- __PROPERTY(bool, verbose, Verbose);
+ /// Gets the local site data.
+ static SiteData getSiteData() { return m_siteData; }
+ /// Sets the local site data.
+ static void setSiteData(SiteData siteData) { m_siteData = siteData; }
+ public:
/** Common Data */
/// Message Type
- __PROPERTY(uint8_t, messageType, MessageType);
+ __PROTECTED_PROPERTY(uint8_t, messageType, MessageType);
/// Source ID.
- __PROPERTY(uint16_t, srcId, SrcId);
+ __PROTECTED_PROPERTY(uint16_t, srcId, SrcId);
/// Destination ID.
- __PROPERTY(uint16_t, dstId, DstId);
+ __PROTECTED_PROPERTY(uint16_t, dstId, DstId);
/// Location ID.
- __PROPERTY(uint32_t, locId, LocId);
+ __PROTECTED_PROPERTY(uint32_t, locId, LocId);
/// Registration Option.
- __PROPERTY(uint8_t, regOption, RegOption);
+ __PROTECTED_PROPERTY(uint8_t, regOption, RegOption);
/// Version Number.
- __PROPERTY(uint8_t, version, Version);
+ __PROTECTED_PROPERTY(uint8_t, version, Version);
/// Cause Response.
- __PROPERTY(uint8_t, causeRsp, CauseResponse);
+ __PROTECTED_PROPERTY(uint8_t, causeRsp, CauseResponse);
/// Voice channel number.
- __PROPERTY(uint32_t, grpVchNo, GrpVchNo);
+ __PROTECTED_PROPERTY(uint32_t, grpVchNo, GrpVchNo);
/** Call Data */
/// Call Type
- __PROPERTY(uint8_t, callType, CallType);
+ __PROTECTED_PROPERTY(uint8_t, callType, CallType);
/** Common Call Options */
/// Flag indicating the emergency bits are set.
- __PROPERTY(bool, emergency, Emergency);
+ __PROTECTED_PROPERTY(bool, emergency, Emergency);
/// Flag indicating that encryption is enabled.
- __PROPERTY(bool, encrypted, Encrypted);
+ __PROTECTED_PROPERTY(bool, encrypted, Encrypted);
/// Flag indicating priority paging.
- __PROPERTY(bool, priority, Priority);
+ __PROTECTED_PROPERTY(bool, priority, Priority);
/// Flag indicating a group/talkgroup operation.
- __PROPERTY(bool, group, Group);
+ __PROTECTED_PROPERTY(bool, group, Group);
/// Flag indicating a half/full duplex operation.
- __PROPERTY(bool, duplex, Duplex);
+ __PROTECTED_PROPERTY(bool, duplex, Duplex);
/// Transmission mode.
- __PROPERTY(uint8_t, transmissionMode, TransmissionMode);
+ __PROTECTED_PROPERTY(uint8_t, transmissionMode, TransmissionMode);
/** Local Site data */
- /// Local Site Data.
- __PROPERTY_PLAIN(SiteData, siteData, siteData);
/// Local Site Identity Entry.
- __PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry);
-
- /** Channel Structure Data */
- /// Count of BCCH frames per RCCH superframe.
- __PROPERTY(uint8_t, bcchCnt, BcchCnt);
- /// Count of RCCH frame groupings per RCCH superframe.
- __PROPERTY(uint8_t, rcchGroupingCnt, RcchGroupingCnt);
- /// Count of CCCH/UPCH paging frames per RCCH superframe.
- __PROPERTY(uint8_t, ccchPagingCnt, CcchPagingCnt);
- /// Count of CCCH/UPCH multi-purpose frames per RCCH superframe.
- __PROPERTY(uint8_t, ccchMultiCnt, CcchMultiCnt);
- /// Count of group iterations per RCCH superframe.
- __PROPERTY(uint8_t, rcchIterateCnt, RcchIterateCount);
-
- private:
- /// Initializes a new instance of the RCCH class.
- RCCH();
- /// Initializes a new instance of the RCCH class.
- RCCH(SiteData siteData);
+ __PROTECTED_PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry);
+
+ protected:
+ static bool m_verbose;
/** Local Site data */
- uint8_t* m_siteCallsign;
+ static uint8_t* m_siteCallsign;
+ static SiteData m_siteData;
- /// Decode link control.
- bool decodeLC(const uint8_t* data);
- /// Encode link control.
- void encodeLC(uint8_t* data);
+ /// Internal helper to decode a RCCH.
+ void decode(const uint8_t* data, uint8_t* rcch, uint32_t length, uint32_t offset = 0U);
+ /// Internal helper to encode a RCCH.
+ void encode(uint8_t* data, const uint8_t* rcch, uint32_t length, uint32_t offset = 0U);
- /// Internal helper to copy the class.
- void copy(const RCCH& data);
+ __PROTECTED_COPY(RCCH);
};
} // namespace lc
} // namespace nxdn
diff --git a/nxdn/lc/RTCH.cpp b/nxdn/lc/RTCH.cpp
index d53fb00f..ae630b85 100644
--- a/nxdn/lc/RTCH.cpp
+++ b/nxdn/lc/RTCH.cpp
@@ -40,6 +40,12 @@ using namespace nxdn::lc;
#include
#include
+// ---------------------------------------------------------------------------
+// Static Class Members
+// ---------------------------------------------------------------------------
+
+bool RTCH::m_verbose = false;
+
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
@@ -48,7 +54,6 @@ using namespace nxdn::lc;
/// Initializes a new instance of the RTCH class.
///
RTCH::RTCH() :
- m_verbose(false),
m_messageType(MESSAGE_TYPE_IDLE),
m_callType(CALL_TYPE_UNSPECIFIED),
m_srcId(0U),
@@ -77,7 +82,6 @@ RTCH::RTCH() :
///
///
RTCH::RTCH(const RTCH& data) :
- m_verbose(false),
m_messageType(MESSAGE_TYPE_IDLE),
m_callType(CALL_TYPE_UNSPECIFIED),
m_srcId(0U),
@@ -449,8 +453,6 @@ void RTCH::encodeLC(uint8_t* data)
///
void RTCH::copy(const RTCH& data)
{
- m_verbose = data.m_verbose;
-
m_messageType = data.m_messageType;
m_callType = data.m_callType;
diff --git a/nxdn/lc/RTCH.h b/nxdn/lc/RTCH.h
index 642320e4..23a5c8cf 100644
--- a/nxdn/lc/RTCH.h
+++ b/nxdn/lc/RTCH.h
@@ -63,10 +63,10 @@ namespace nxdn
///
void reset();
- public:
- /// Flag indicating verbose log output.
- __PROPERTY(bool, verbose, Verbose);
+ /// Sets the flag indicating verbose log output.
+ static void setVerbose(bool verbose) { m_verbose = verbose; }
+ public:
/** Common Data */
/// Message Type
__PROPERTY(uint8_t, messageType, MessageType);
@@ -118,6 +118,8 @@ namespace nxdn
__PROPERTY(uint8_t, causeRsp, CauseResponse);
private:
+ static bool m_verbose;
+
/** Encryption data */
uint8_t* m_mi;
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.cpp
new file mode 100644
index 00000000..2d00870b
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.cpp
@@ -0,0 +1,103 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_DCALL_HDR class.
+///
+MESSAGE_TYPE_DCALL_HDR::MESSAGE_TYPE_DCALL_HDR() : RCCH()
+{
+ m_messageType = RTCH_MESSAGE_TYPE_DCALL_HDR;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_DCALL_HDR::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+
+ m_callType = (rcch[2U] >> 5) & 0x07U; // Call Type
+ m_emergency = (rcch[1U] & 0x80U) == 0x80U; // Emergency Flag
+ m_priority = (rcch[1U] & 0x20U) == 0x20U; // Priority Flag
+ m_duplex = (rcch[2U] & 0x10U) == 0x10U; // Half/Full Duplex Flag
+ m_transmissionMode = (rcch[2U] & 0x07U); // Transmission Mode
+ m_srcId = (uint16_t)((rcch[3U] << 8) | rcch[4U]) & 0xFFFFU; // Source Radio Address
+ m_dstId = (uint16_t)((rcch[5U] << 8) | rcch[6U]) & 0xFFFFU; // Target Radio Address
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_DCALL_HDR::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
+ (m_priority ? 0x20U : 0x00U); // Priority Flag
+ rcch[2U] = ((m_callType & 0x07U) << 5) + // Call Type
+ (m_duplex ? 0x10U : 0x00U) + // Half/Full Duplex Flag
+ (m_transmissionMode & 0x07U); // Transmission Mode
+
+ rcch[3U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
+ rcch[4U] = (m_srcId >> 0U) & 0xFFU; // ...
+ rcch[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
+ rcch[6U] = (m_dstId >> 0U) & 0xFFU; // ...
+
+ rcch[7U] = m_causeRsp; // Cause (VD)
+ rcch[9U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
+ rcch[10U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h b/nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h
new file mode 100644
index 00000000..2ffd72be
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h
@@ -0,0 +1,58 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_DCALL_HDR_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_DCALL_HDR_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements VCALL_CONN - Voice Call Connection Request (ISP) and
+ // Voice Call Connection Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_DCALL_HDR : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_DCALL_HDR class.
+ MESSAGE_TYPE_DCALL_HDR();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_DCALL_HDR_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.cpp
new file mode 100644
index 00000000..a15e5f1c
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.cpp
@@ -0,0 +1,86 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_DST_ID_INFO class.
+///
+MESSAGE_TYPE_DST_ID_INFO::MESSAGE_TYPE_DST_ID_INFO() : RCCH()
+{
+ m_messageType = nxdn::MESSAGE_TYPE_DST_ID_INFO;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_DST_ID_INFO::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_DST_ID_INFO::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[1U] = 0xC0U + NXDN_CALLSIGN_LENGTH_BYTES; // Station ID Option - Start / End / Character Count
+ rcch[2U] = (m_siteCallsign[0]); // Character 0
+ for (uint8_t i = 1; i < NXDN_CALLSIGN_LENGTH_BYTES; i++) {
+ rcch[i + 2U] = m_siteCallsign[i]; // Character 1 - 7
+ }
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h b/nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h
new file mode 100644
index 00000000..73d52e0b
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_DST_ID_INFO_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_DST_ID_INFO_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements DST_ID_INFO - Digital Station ID
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_DST_ID_INFO : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_DST_ID_INFO class.
+ MESSAGE_TYPE_DST_ID_INFO();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_DST_ID_INFO_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.cpp
new file mode 100644
index 00000000..4163935e
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.cpp
@@ -0,0 +1,92 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_GRP_REG class.
+///
+MESSAGE_TYPE_GRP_REG::MESSAGE_TYPE_GRP_REG() : RCCH()
+{
+ m_messageType = RCCH_MESSAGE_TYPE_GRP_REG;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_GRP_REG::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+
+ m_regOption = rcch[1U]; // Group Registration Option
+ m_srcId = (uint16_t)((rcch[2U] << 8) | rcch[3U]) & 0xFFFFU; // Source Radio Address
+ m_dstId = (uint16_t)((rcch[4U] << 8) | rcch[5U]) & 0xFFFFU; // Target Radio Address
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_GRP_REG::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[2U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
+ rcch[3U] = (m_srcId >> 0U) & 0xFFU; // ...
+ rcch[4U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
+ rcch[5U] = (m_dstId >> 0U) & 0xFFU; // ...
+ rcch[6U] = m_causeRsp; // Cause (MM)
+ rcch[8U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
+ rcch[9U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h b/nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h
new file mode 100644
index 00000000..56ac0df1
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h
@@ -0,0 +1,58 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_GRP_REG_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_GRP_REG_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements GRP_REG - Group Registration Request (ISP) and
+ // Group Registration Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_GRP_REG : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_GRP_REG class.
+ MESSAGE_TYPE_GRP_REG();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_GRP_REG_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_IDLE.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_IDLE.cpp
new file mode 100644
index 00000000..344a6b3c
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_IDLE.cpp
@@ -0,0 +1,80 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_IDLE class.
+///
+MESSAGE_TYPE_IDLE::MESSAGE_TYPE_IDLE() : RCCH()
+{
+ m_messageType = nxdn::MESSAGE_TYPE_IDLE;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_IDLE::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_IDLE::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h b/nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h
new file mode 100644
index 00000000..868a21d3
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_IDLE_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_IDLE_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements IDLE - Idle
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_IDLE : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_IDLE class.
+ MESSAGE_TYPE_IDLE();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_IDLE_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp
new file mode 100644
index 00000000..c4699eb4
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp
@@ -0,0 +1,95 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_REG.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_REG class.
+///
+MESSAGE_TYPE_REG::MESSAGE_TYPE_REG() : RCCH()
+{
+ m_messageType = RCCH_MESSAGE_TYPE_REG;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_REG::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+
+ m_regOption = rcch[1U] >> 3; // Registration Option
+ m_locId = (uint16_t)((rcch[2U] << 8) | rcch[3U]) & 0xFFFFU; // Location ID
+ m_srcId = (uint16_t)((rcch[4U] << 8) | rcch[5U]) & 0xFFFFU; // Source Radio Address
+ m_dstId = (uint16_t)((rcch[6U] << 8) | rcch[7U]) & 0xFFFFU; // Target Radio Address
+ // bryanb: maybe process subscriber type? (byte 8 and 9)
+ m_version = rcch[10U]; // Version
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_REG::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...
+ rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+ rcch[4U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
+ rcch[5U] = (m_srcId >> 0U) & 0xFFU; // ...
+ rcch[6U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
+ rcch[7U] = (m_dstId >> 0U) & 0xFFU; // ...
+ rcch[8U] = m_causeRsp; // Cause (MM)
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_REG.h b/nxdn/lc/rcch/MESSAGE_TYPE_REG.h
new file mode 100644
index 00000000..d2914cc5
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_REG.h
@@ -0,0 +1,58 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_REG_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_REG_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements REG - Registration Request (ISP) and
+ // Registration Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_REG : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_REG class.
+ MESSAGE_TYPE_REG();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_REG_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_REG_C.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_REG_C.cpp
new file mode 100644
index 00000000..b55fe352
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_REG_C.cpp
@@ -0,0 +1,90 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_REG_C class.
+///
+MESSAGE_TYPE_REG_C::MESSAGE_TYPE_REG_C() : RCCH()
+{
+ m_messageType = RCCH_MESSAGE_TYPE_REG_C;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_REG_C::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+
+ m_regOption = rcch[1U] >> 3; // Registration Option
+ m_locId = (uint16_t)((rcch[2U] << 8) | rcch[3U]) & 0xFFFFU; // Location ID
+ m_srcId = (uint16_t)((rcch[4U] << 8) | rcch[5U]) & 0xFFFFU; // Source Radio Address
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_REG_C::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
+ rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+ rcch[4U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
+ rcch[5U] = (m_dstId >> 0U) & 0xFFU; // ...
+ rcch[6U] = m_causeRsp; // Cause (MM)
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h b/nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h
new file mode 100644
index 00000000..91322abb
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h
@@ -0,0 +1,58 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_REG_C_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_REG_C_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements REG_C - Registration Clear Request (ISP) and
+ // Registration Clear Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_REG_C : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_REG_C class.
+ MESSAGE_TYPE_REG_C();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_REG_C_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.cpp
new file mode 100644
index 00000000..f20b740d
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.cpp
@@ -0,0 +1,85 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_REG_COMM class.
+///
+MESSAGE_TYPE_REG_COMM::MESSAGE_TYPE_REG_COMM() : RCCH()
+{
+ m_messageType = RCCH_MESSAGE_TYPE_REG_COMM;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_REG_COMM::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_REG_COMM::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
+ rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+ rcch[4U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
+ rcch[5U] = (m_dstId >> 0U) & 0xFFU; // ...
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h b/nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h
new file mode 100644
index 00000000..00f8491e
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_REG_COMM_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_REG_COMM_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements REG_COMM - Registration Command
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_REG_COMM : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_REG_COMM class.
+ MESSAGE_TYPE_REG_COMM();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_REG_COMM_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.cpp
new file mode 100644
index 00000000..50a730a6
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.cpp
@@ -0,0 +1,131 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_SITE_INFO class.
+///
+MESSAGE_TYPE_SITE_INFO::MESSAGE_TYPE_SITE_INFO() : RCCH(),
+ m_bcchCnt(1U),
+ m_rcchGroupingCnt(1U),
+ m_ccchPagingCnt(2U),
+ m_ccchMultiCnt(2U),
+ m_rcchIterateCnt(2U)
+{
+ m_messageType = RCCH_MESSAGE_TYPE_SITE_INFO;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_SITE_INFO::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_SITE_INFO::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[1U] = (m_siteData.locId() >> 16) & 0xFFU; // Location ID
+ rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...
+ rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+ rcch[4U] = ((m_bcchCnt & 0x03U) << 6) + // Channel Structure - Number of BCCH
+ ((m_rcchGroupingCnt & 0x07U) << 3) + // ... - Number of Grouping
+ (((m_ccchPagingCnt >> 1) & 0x07U) << 0); // ... - Number of Paging Frames
+ rcch[5U] = ((m_ccchPagingCnt & 0x01U) << 7) + // ... - Number of Paging Frames
+ ((m_ccchMultiCnt & 0x07U) << 4) + // ... - Number of Multipurpose Frames
+ ((m_rcchIterateCnt & 0x0FU) << 0); // ... - Number of Iteration
+
+ rcch[6U] = m_siteData.serviceClass(); // Service Information
+ rcch[7U] = (m_siteData.netActive() ? NXDN_SIF2_IP_NETWORK : 0x00U); // ...
+
+ // bryanb: this is currently fixed -- maybe dynamic in the future
+ rcch[8U] = 0U; // Restriction Information - No access restriction / No cycle restriction
+ rcch[9U] = 0x08U; // ... - No group restriction / GMS; Location Registration Restriction
+ rcch[10U] = (!m_siteData.netActive() ? 0x01U : 0x00U); // ... - No group ratio restriction / No delay time extension / ISO
+
+ // bryanb: this is currently fixed -- maybe dynamic in the future
+ rcch[11U] = NXDN_CH_ACCESS_BASE_FREQ_SYS_DEFINED; // Channel Access Information - Channel Version / Sys Defined Step / Sys Defined Base Freq
+
+ rcch[14U] = 1U; // Version
+
+ uint16_t channelNo = m_siteData.channelNo() & 0x3FFU;
+ rcch[15U] = (channelNo >> 6) & 0x0FU; // 1st Control Channel
+ rcch[16U] = (channelNo & 0x3FU) << 2; // ...
+
+ RCCH::encode(data, rcch, length, offset);
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void MESSAGE_TYPE_SITE_INFO::copy(const MESSAGE_TYPE_SITE_INFO& data)
+{
+ RCCH::copy(data);
+
+ m_bcchCnt = data.m_bcchCnt;
+ m_rcchGroupingCnt = data.m_rcchGroupingCnt;
+ m_ccchPagingCnt = data.m_ccchPagingCnt;
+ m_ccchMultiCnt = data.m_ccchMultiCnt;
+ m_rcchIterateCnt = data.m_rcchIterateCnt;
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h b/nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h
new file mode 100644
index 00000000..d439865b
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h
@@ -0,0 +1,72 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_SITE_INFO_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_SITE_INFO_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SITE_INFO - Site Information
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_SITE_INFO : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_SITE_INFO class.
+ MESSAGE_TYPE_SITE_INFO();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+
+ public:
+ /** Channel Structure Data */
+ /// Count of BCCH frames per RCCH superframe.
+ __PROPERTY(uint8_t, bcchCnt, BcchCnt);
+ /// Count of RCCH frame groupings per RCCH superframe.
+ __PROPERTY(uint8_t, rcchGroupingCnt, RcchGroupingCnt);
+ /// Count of CCCH/UPCH paging frames per RCCH superframe.
+ __PROPERTY(uint8_t, ccchPagingCnt, CcchPagingCnt);
+ /// Count of CCCH/UPCH multi-purpose frames per RCCH superframe.
+ __PROPERTY(uint8_t, ccchMultiCnt, CcchMultiCnt);
+ /// Count of group iterations per RCCH superframe.
+ __PROPERTY(uint8_t, rcchIterateCnt, RcchIterateCount);
+
+ __COPY(MESSAGE_TYPE_SITE_INFO);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_SITE_INFO_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.cpp
new file mode 100644
index 00000000..2309adac
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.cpp
@@ -0,0 +1,91 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_SRV_INFO class.
+///
+MESSAGE_TYPE_SRV_INFO::MESSAGE_TYPE_SRV_INFO() : RCCH()
+{
+ m_messageType = nxdn::MESSAGE_TYPE_SRV_INFO;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_SRV_INFO::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_SRV_INFO::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[1U] = (m_siteData.locId() >> 16) & 0xFFU; // Location ID
+ rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...
+ rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+ rcch[4U] = m_siteData.serviceClass(); // Service Information
+ rcch[5U] = (m_siteData.netActive() ? NXDN_SIF2_IP_NETWORK : 0x00U); // ...
+
+ // bryanb: this is currently fixed -- maybe dynamic in the future
+ rcch[6U] = 0U; // Restriction Information - No access restriction / No cycle restriction
+ rcch[7U] = 0x08U; // ... - No group restriction / GMS; Location Registration Restriction
+ rcch[8U] = (!m_siteData.netActive() ? 0x01U : 0x00U); // ... - No group ratio restriction / No delay time extension / ISO
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h b/nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h
new file mode 100644
index 00000000..b6a6b689
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_SRV_INFO_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_SRV_INFO_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SRV_INFO - Service Information
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_SRV_INFO : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_SRV_INFO class.
+ MESSAGE_TYPE_SRV_INFO();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_SRV_INFO_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.cpp
new file mode 100644
index 00000000..a2978763
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.cpp
@@ -0,0 +1,97 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_VCALL_ASSGN class.
+///
+MESSAGE_TYPE_VCALL_ASSGN::MESSAGE_TYPE_VCALL_ASSGN() : RCCH()
+{
+ m_messageType = RCCH_MESSAGE_TYPE_VCALL_ASSGN;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_VCALL_ASSGN::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_VCALL_ASSGN::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
+ (m_priority ? 0x20U : 0x00U); // Priority Flag
+ rcch[2U] = ((m_callType & 0x07U) << 5) + // Call Type
+ (m_duplex ? 0x10U : 0x00U) + // Half/Full Duplex Flag
+ (m_transmissionMode & 0x07U); // Transmission Mode
+
+ rcch[3U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
+ rcch[4U] = (m_srcId >> 0U) & 0xFFU; // ...
+ rcch[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
+ rcch[6U] = (m_dstId >> 0U) & 0xFFU; // ...
+
+ rcch[7U] = (m_grpVchNo >> 10) & 0x03U; // Channel
+ rcch[8U] = (m_grpVchNo & 0xFFU); // ...
+
+ rcch[10U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
+ rcch[11U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h
new file mode 100644
index 00000000..b78b806b
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_VCALL_ASSGN_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_VCALL_ASSGN_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements VCALL_ASSGN - Voice Call Assignment
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_VCALL_ASSGN : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_VCALL_ASSGN class.
+ MESSAGE_TYPE_VCALL_ASSGN();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_VCALL_ASSGN_H__
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.cpp b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.cpp
new file mode 100644
index 00000000..0ee8ecee
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.cpp
@@ -0,0 +1,103 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MESSAGE_TYPE_VCALL_CONN class.
+///
+MESSAGE_TYPE_VCALL_CONN::MESSAGE_TYPE_VCALL_CONN() : RCCH()
+{
+ m_messageType = RCCH_MESSAGE_TYPE_VCALL_CONN;
+}
+
+///
+/// Decode layer 3 data.
+///
+///
+///
+///
+void MESSAGE_TYPE_VCALL_CONN::decode(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ RCCH::decode(data, rcch, length, offset);
+
+ m_callType = (rcch[2U] >> 5) & 0x07U; // Call Type
+ m_emergency = (rcch[1U] & 0x80U) == 0x80U; // Emergency Flag
+ m_priority = (rcch[1U] & 0x20U) == 0x20U; // Priority Flag
+ m_duplex = (rcch[2U] & 0x10U) == 0x10U; // Half/Full Duplex Flag
+ m_transmissionMode = (rcch[2U] & 0x07U); // Transmission Mode
+ m_srcId = (uint16_t)((rcch[3U] << 8) | rcch[4U]) & 0xFFFFU; // Source Radio Address
+ m_dstId = (uint16_t)((rcch[5U] << 8) | rcch[6U]) & 0xFFFFU; // Target Radio Address
+}
+
+///
+/// Encode a control signalling block.
+///
+///
+///
+///
+void MESSAGE_TYPE_VCALL_CONN::encode(uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != NULL);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ rcch[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
+ (m_priority ? 0x20U : 0x00U); // Priority Flag
+ rcch[2U] = ((m_callType & 0x07U) << 5) + // Call Type
+ (m_duplex ? 0x10U : 0x00U) + // Half/Full Duplex Flag
+ (m_transmissionMode & 0x07U); // Transmission Mode
+
+ rcch[3U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address
+ rcch[4U] = (m_srcId >> 0U) & 0xFFU; // ...
+ rcch[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
+ rcch[6U] = (m_dstId >> 0U) & 0xFFU; // ...
+
+ rcch[7U] = m_causeRsp; // Cause (VD)
+ rcch[9U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID
+ rcch[10U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
+
+ RCCH::encode(data, rcch, length, offset);
+}
diff --git a/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h
new file mode 100644
index 00000000..e6d5a29a
--- /dev/null
+++ b/nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h
@@ -0,0 +1,58 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC_RCCH__MESSAGE_TYPE_VCALL_CONN_H__)
+#define __NXDN_LC_RCCH__MESSAGE_TYPE_VCALL_CONN_H__
+
+#include "Defines.h"
+#include "nxdn/lc/RCCH.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements VCALL_CONN - Voice Call Connection Request (ISP) and
+ // Voice Call Connection Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MESSAGE_TYPE_VCALL_CONN : public RCCH {
+ public:
+ /// Initializes a new instance of the MESSAGE_TYPE_VCALL_CONN class.
+ MESSAGE_TYPE_VCALL_CONN();
+
+ /// Decode layer 3 data.
+ virtual void decode(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ /// Encode layer 3 data.
+ virtual void encode(uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC_RCCH__MESSAGE_TYPE_VCALL_CONN_H__
diff --git a/nxdn/lc/rcch/RCCHFactory.cpp b/nxdn/lc/rcch/RCCHFactory.cpp
new file mode 100644
index 00000000..4c28ee67
--- /dev/null
+++ b/nxdn/lc/rcch/RCCHFactory.cpp
@@ -0,0 +1,120 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "nxdn/lc/rcch/RCCHFactory.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace nxdn::lc::rcch;
+using namespace nxdn::lc;
+using namespace nxdn;
+
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the RCCHFactory class.
+///
+RCCHFactory::RCCHFactory()
+{
+ /* stub */
+}
+
+///
+/// Finalizes a instance of RCCHFactory class.
+///
+RCCHFactory::~RCCHFactory()
+{
+ /* stub */
+}
+
+///
+/// Create an instance of a RCCH.
+///
+///
+///
+///
+/// True, if RCCH was decoded, otherwise false.
+std::unique_ptr RCCHFactory::createRCCH(const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(data != nullptr);
+
+ uint8_t rcch[22U];
+ ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
+
+ for (uint32_t i = 0U; i < length; i++, offset++) {
+ bool b = READ_BIT(data, offset);
+ WRITE_BIT(rcch, i, b);
+ }
+
+ uint8_t messageType = data[0U] & 0x3FU; // Message Type
+
+ // message type opcodes
+ switch (messageType) {
+ case RTCH_MESSAGE_TYPE_VCALL:
+ case RCCH_MESSAGE_TYPE_VCALL_CONN:
+ return decode(new MESSAGE_TYPE_VCALL_CONN(), data, length, offset);
+ case RTCH_MESSAGE_TYPE_DCALL_HDR:
+ return decode(new MESSAGE_TYPE_DCALL_HDR(), data, length, offset);
+ case nxdn::MESSAGE_TYPE_IDLE:
+ return decode(new MESSAGE_TYPE_IDLE(), data, length, offset);
+ case RCCH_MESSAGE_TYPE_REG:
+ return decode(new MESSAGE_TYPE_REG(), data, length, offset);
+ case RCCH_MESSAGE_TYPE_REG_C:
+ return decode(new MESSAGE_TYPE_REG_C(), data, length, offset);
+ case RCCH_MESSAGE_TYPE_GRP_REG:
+ return decode(new MESSAGE_TYPE_GRP_REG(), data, length, offset);
+ default:
+ LogError(LOG_NXDN, "RCCH::decodeRCCH(), unknown RCCH value, messageType = $%02X", messageType);
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+///
+///
+///
+///
+///
+///
+///
+std::unique_ptr RCCHFactory::decode(RCCH* rcch, const uint8_t* data, uint32_t length, uint32_t offset)
+{
+ assert(rcch != nullptr);
+ assert(data != nullptr);
+
+ rcch->decode(data, length, offset);
+ return std::unique_ptr(rcch);
+}
diff --git a/nxdn/lc/rcch/RCCHFactory.h b/nxdn/lc/rcch/RCCHFactory.h
new file mode 100644
index 00000000..0dd83549
--- /dev/null
+++ b/nxdn/lc/rcch/RCCHFactory.h
@@ -0,0 +1,73 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__NXDN_LC__RCCH_FACTORY_H__)
+#define __NXDN_LC__RCCH_FACTORY_H__
+
+#include "Defines.h"
+
+#include "nxdn/lc/RCCH.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_REG.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h"
+#include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h"
+
+namespace nxdn
+{
+ namespace lc
+ {
+ namespace rcch
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Helper class to instantiate an instance of a RCCH.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API RCCHFactory {
+ public:
+ /// Initializes a new instance of the RCCHFactory class.
+ RCCHFactory();
+ /// Finalizes a instance of the RCCHFactory class.
+ ~RCCHFactory();
+
+ /// Create an instance of a RCCH.
+ static std::unique_ptr createRCCH(const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+
+ private:
+ ///
+ static std::unique_ptr decode(RCCH* rcch, const uint8_t* data, uint32_t length, uint32_t offset = 0U);
+ };
+ } // namespace rcch
+ } // namespace lc
+} // namespace nxdn
+
+#endif // __NXDN_LC__RCCH_FACTORY_H__
diff --git a/nxdn/packet/Trunk.cpp b/nxdn/packet/Trunk.cpp
index aeb353f7..5efe5fd8 100644
--- a/nxdn/packet/Trunk.cpp
+++ b/nxdn/packet/Trunk.cpp
@@ -32,6 +32,7 @@
#include "nxdn/channel/CAC.h"
#include "nxdn/packet/Trunk.h"
#include "nxdn/acl/AccessControl.h"
+#include "nxdn/lc/rcch/RCCHFactory.h"
#include "nxdn/Sync.h"
#include "nxdn/NXDNUtils.h"
#include "edac/CRC.h"
@@ -40,6 +41,7 @@
#include "Utils.h"
using namespace nxdn;
+using namespace nxdn::lc;
using namespace nxdn::packet;
#include
@@ -55,7 +57,7 @@ using namespace nxdn::packet;
#define IS_SUPPORT_CONTROL_CHECK(_PCKT_STR, _PCKT, _SRCID) \
if (!m_nxdn->m_control) { \
LogWarning(LOG_RF, "NXDN, " _PCKT_STR " denial, unsupported service, srcId = %u", _SRCID); \
- writeRF_Message_Deny(NXDN_CAUSE_SVC_UNAVAILABLE, _PCKT); \
+ writeRF_Message_Deny(0U, _SRCID, NXDN_CAUSE_SVC_UNAVAILABLE, _PCKT); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
}
@@ -64,7 +66,7 @@ using namespace nxdn::packet;
#define VALID_SRCID(_PCKT_STR, _PCKT, _SRCID, _RSN) \
if (!acl::AccessControl::validateSrcId(_SRCID)) { \
LogWarning(LOG_RF, "NXDN, " _PCKT_STR " denial, RID rejection, srcId = %u", _SRCID); \
- writeRF_Message_Deny(_RSN, _PCKT); \
+ writeRF_Message_Deny(0U, _SRCID, _RSN, _PCKT); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
}
@@ -73,16 +75,16 @@ using namespace nxdn::packet;
#define VALID_DSTID(_PCKT_STR, _PCKT, _DSTID, _RSN) \
if (!acl::AccessControl::validateSrcId(_DSTID)) { \
LogWarning(LOG_RF, "NXDN, " _PCKT_STR " denial, RID rejection, dstId = %u", _DSTID); \
- writeRF_Message_Deny(_RSN, _PCKT); \
+ writeRF_Message_Deny(0U, _SRCID, _RSN, _PCKT); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
}
// Validate the talkgroup ID.
-#define VALID_TGID(_PCKT_STR, _PCKT, _DSTID, _RSN) \
+#define VALID_TGID(_PCKT_STR, _PCKT, _DSTID, _SRCID, _RSN) \
if (!acl::AccessControl::validateTGId(_DSTID)) { \
LogWarning(LOG_RF, "NXDN, " _PCKT_STR " denial, TGID rejection, dstId = %u", _DSTID); \
- writeRF_Message_Deny(_RSN, _PCKT); \
+ writeRF_Message_Deny(0U, _SRCID, _RSN, _PCKT); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
}
@@ -91,7 +93,7 @@ using namespace nxdn::packet;
#define VERIFY_SRCID_REG(_PCKT_STR, _PCKT, _SRCID, _RSN) \
if (!m_nxdn->m_affiliations.isUnitReg(_SRCID) && m_verifyReg) { \
LogWarning(LOG_RF, "NXDN, " _PCKT_STR " denial, RID not registered, srcId = %u", _SRCID); \
- writeRF_Message_Deny(_RSN, _PCKT); \
+ writeRF_Message_Deny(0U, _SRCID, _RSN, _PCKT); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
}
@@ -100,7 +102,7 @@ using namespace nxdn::packet;
#define VERIFY_SRCID_AFF(_PCKT_STR, _PCKT, _SRCID, _DSTID, _RSN) \
if (!m_nxdn->m_affiliations.isGroupAff(_SRCID, _DSTID) && m_verifyAff) { \
LogWarning(LOG_RF, "NXDN, " _PCKT_STR " denial, RID not affiliated to TGID, srcId = %u, dstId = %u", _SRCID, _DSTID); \
- writeRF_Message_Deny(_RSN, _PCKT); \
+ writeRF_Message_Deny(0U, _SRCID, _RSN, _PCKT); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
}
@@ -115,24 +117,6 @@ const uint32_t GRANT_TIMER_TIMEOUT = 15U;
// Public Class Members
// ---------------------------------------------------------------------------
-///
-/// Resets the data states for the RF interface.
-///
-void Trunk::resetRF()
-{
- lc::RCCH lc = lc::RCCH(m_nxdn->m_siteData, m_nxdn->m_idenEntry, m_dumpRCCH);
- m_rfLC = lc;
-}
-
-///
-/// Resets the data states for the network.
-///
-void Trunk::resetNet()
-{
- lc::RCCH lc = lc::RCCH(m_nxdn->m_siteData, m_nxdn->m_idenEntry, m_dumpRCCH);
- m_netLC = lc;
-}
-
///
/// Process a data frame from the RF interface.
///
@@ -167,13 +151,16 @@ bool Trunk::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
uint8_t buffer[NXDN_FRAME_LENGTH_BYTES];
cac.getData(buffer);
- m_rfLC.decode(buffer, NXDN_RCCH_CAC_LC_SHORT_LENGTH_BITS);
+ std::unique_ptr rcch = rcch::RCCHFactory::createRCCH(buffer, NXDN_RCCH_CAC_LC_SHORT_LENGTH_BITS);
+ if (rcch == nullptr)
+ return false;
- uint16_t srcId = m_rfLC.getSrcId();
- uint16_t dstId = m_rfLC.getDstId();
+ uint16_t srcId = rcch->getSrcId();
+ uint16_t dstId = rcch->getDstId();
- switch (m_rfLC.getMessageType()) {
+ switch (rcch->getMessageType()) {
case RTCH_MESSAGE_TYPE_VCALL:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK(NXDN_RTCH_MSG_TYPE_VCALL_REQ, RTCH_MESSAGE_TYPE_VCALL, srcId);
@@ -181,7 +168,7 @@ bool Trunk::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
VALID_SRCID(NXDN_RTCH_MSG_TYPE_VCALL_REQ, RTCH_MESSAGE_TYPE_VCALL, srcId, NXDN_CAUSE_VD_REQ_UNIT_NOT_PERM);
// validate the talkgroup ID
- VALID_TGID(NXDN_RTCH_MSG_TYPE_VCALL_REQ, RTCH_MESSAGE_TYPE_VCALL, dstId, NXDN_CAUSE_VD_TGT_UNIT_NOT_PERM);
+ VALID_TGID(NXDN_RTCH_MSG_TYPE_VCALL_REQ, RTCH_MESSAGE_TYPE_VCALL, dstId, srcId, NXDN_CAUSE_VD_TGT_UNIT_NOT_PERM);
// verify the source RID is affiliated
VERIFY_SRCID_AFF(NXDN_RTCH_MSG_TYPE_VCALL_REQ, RTCH_MESSAGE_TYPE_VCALL, srcId, dstId, NXDN_CAUSE_VD_REQ_UNIT_NOT_REG);
@@ -190,30 +177,39 @@ bool Trunk::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
LogMessage(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ ", srcId = %u, dstId = %u", srcId, dstId);
}
- writeRF_Message_Grant(true);
- break;
+ uint8_t serviceOptions = (rcch->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (rcch->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (rcch->getPriority() & 0x07U); // Priority
+
+ writeRF_Message_Grant(srcId, dstId, serviceOptions, true);
+ }
+ break;
case RCCH_MESSAGE_TYPE_REG:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK(NXDN_RCCH_MSG_TYPE_REG_REQ, RCCH_MESSAGE_TYPE_REG, srcId);
if (m_verbose) {
- LogMessage(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_REG_REQ ", srcId = %u", srcId);
+ LogMessage(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_REG_REQ ", srcId = %u, locId = %u", srcId, rcch->getLocId());
}
- writeRF_Message_U_Reg_Rsp(srcId);
- break;
+ writeRF_Message_U_Reg_Rsp(srcId, rcch->getLocId());
+ }
+ break;
case RCCH_MESSAGE_TYPE_GRP_REG:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK(NXDN_RCCH_MSG_TYPE_GRP_REG_REQ, RCCH_MESSAGE_TYPE_GRP_REG, srcId);
if (m_verbose) {
- LogMessage(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ ", srcId = %u, dstId = %u", srcId, dstId);
+ LogMessage(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ ", srcId = %u, dstId = %u, locId = %u", srcId, dstId, rcch->getLocId());
}
- writeRF_Message_Grp_Reg_Rsp(srcId, dstId);
- break;
+ writeRF_Message_Grp_Reg_Rsp(srcId, dstId, rcch->getLocId());
+ }
+ break;
default:
- LogError(LOG_RF, "NXDN, unhandled message type, messageType = $%02X", m_rfLC.getMessageType());
+ LogError(LOG_RF, "NXDN, unhandled message type, messageType = $%02X", rcch->getMessageType());
break;
}
@@ -236,9 +232,6 @@ bool Trunk::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t
if (m_nxdn->m_netState == RS_NET_IDLE) {
m_nxdn->m_queue.clear();
-
- resetRF();
- resetNet();
}
return true;
@@ -260,11 +253,7 @@ void Trunk::clock(uint32_t ms)
// do we have a grant response?
if (m_nxdn->m_network->readGrantRsp(grp, srcId, dstId, grpVchNo)) {
- m_rfLC.setSrcId(srcId);
- m_rfLC.setDstId(dstId);
- m_rfLC.setGrpVchNo(grpVchNo);
-
- writeRF_Message_Grant(grp, true, true, true);
+ writeRF_Message_Grant(srcId, dstId, 0U, grp, true, grpVchNo, true, true);
}
}
}
@@ -283,18 +272,19 @@ void Trunk::clock(uint32_t ms)
///
/// Instance of the Control class.
/// Instance of the BaseNetwork class.
-/// Flag indicating whether RCCH data is dumped to the log.
/// Flag indicating whether NXDN debug is enabled.
/// Flag indicating whether NXDN verbose logging is enabled.
-Trunk::Trunk(Control* nxdn, network::BaseNetwork* network, bool dumpRCCHData, bool debug, bool verbose) :
+Trunk::Trunk(Control* nxdn, network::BaseNetwork* network, bool debug, bool verbose) :
m_nxdn(nxdn),
m_network(network),
+ m_bcchCnt(1U),
+ m_rcchGroupingCnt(1U),
+ m_ccchPagingCnt(2U),
+ m_ccchMultiCnt(2U),
+ m_rcchIterateCnt(2U),
m_verifyAff(false),
m_verifyReg(false),
- m_rfLC(SiteData(), lookups::IdenTable()),
- m_netLC(SiteData(), lookups::IdenTable()),
m_lastRejectId(0U),
- m_dumpRCCH(dumpRCCHData),
m_verbose(verbose),
m_debug(debug)
{
@@ -372,9 +362,10 @@ void Trunk::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS)
///
/// Helper to write a single-block RCCH packet.
///
+///
///
///
-void Trunk::writeRF_Message(bool noNetwork, bool clearBeforeWrite)
+void Trunk::writeRF_Message(RCCH* rcch, bool noNetwork, bool clearBeforeWrite)
{
if (!m_nxdn->m_control)
return;
@@ -395,8 +386,7 @@ void Trunk::writeRF_Message(bool noNetwork, bool clearBeforeWrite)
uint8_t buffer[NXDN_RCCH_LC_LENGTH_BYTES];
::memset(buffer, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES);
- m_rfLC.setVerbose(m_dumpRCCH);
- m_rfLC.encode(buffer, NXDN_RCCH_LC_LENGTH_BITS);
+ rcch->encode(buffer, NXDN_RCCH_LC_LENGTH_BITS);
// generate the CAC
channel::CAC cac;
@@ -428,19 +418,25 @@ void Trunk::writeRF_Message(bool noNetwork, bool clearBeforeWrite)
///
/// Helper to write a grant packet.
///
+///
+///
+///
///
///
+///
///
///
///
-bool Trunk::writeRF_Message_Grant(bool grp, bool skip, bool net, bool skipNetCheck)
+bool Trunk::writeRF_Message_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip, uint32_t chNo, bool net, bool skipNetCheck)
{
- uint8_t messageType = m_rfLC.getMessageType();
+ bool emergency = ((serviceOptions & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
+ bool encryption = ((serviceOptions & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
+ uint8_t priority = ((serviceOptions & 0xFFU) & 0x07U); // Priority
// do we have a network connection and are we handling grants at the network?
if (m_nxdn->m_network != nullptr) {
if (m_nxdn->m_network->isHandlingChGrants() && m_nxdn->m_siteData.netActive() && !skipNetCheck) {
- return m_nxdn->m_network->writeGrantReq(grp, m_rfLC.getSrcId(), m_rfLC.getDstId());
+ return m_nxdn->m_network->writeGrantReq(grp, srcId, dstId);
}
}
@@ -448,127 +444,137 @@ bool Trunk::writeRF_Message_Grant(bool grp, bool skip, bool net, bool skipNetChe
if (!skip) {
if (m_nxdn->m_rfState != RS_RF_LISTENING && m_nxdn->m_rfState != RS_RF_DATA) {
if (!net) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " denied, traffic in progress, dstId = %u", m_rfLC.getDstId());
- writeRF_Message_Deny(NXDN_CAUSE_VD_QUE_GRP_BUSY, RTCH_MESSAGE_TYPE_VCALL);
+ LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " denied, traffic in progress, dstId = %u", dstId);
+ writeRF_Message_Deny(0U, srcId, NXDN_CAUSE_VD_QUE_GRP_BUSY, RTCH_MESSAGE_TYPE_VCALL);
- ::ActivityLog("NXDN", true, "group grant request from %u to TG %u denied", m_rfLC.getSrcId(), m_rfLC.getDstId());
+ ::ActivityLog("NXDN", true, "group grant request from %u to TG %u denied", srcId, dstId);
m_nxdn->m_rfState = RS_RF_REJECTED;
}
- m_rfLC.setMessageType(messageType);
return false;
}
- if (m_nxdn->m_netState != RS_NET_IDLE && m_rfLC.getDstId() == m_nxdn->m_netLastDstId) {
+ if (m_nxdn->m_netState != RS_NET_IDLE && dstId == m_nxdn->m_netLastDstId) {
if (!net) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " denied, traffic in progress, dstId = %u", m_rfLC.getDstId());
- writeRF_Message_Deny(NXDN_CAUSE_VD_QUE_GRP_BUSY, RTCH_MESSAGE_TYPE_VCALL);
+ LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " denied, traffic in progress, dstId = %u", dstId);
+ writeRF_Message_Deny(0U, srcId, NXDN_CAUSE_VD_QUE_GRP_BUSY, RTCH_MESSAGE_TYPE_VCALL);
- ::ActivityLog("NXDN", true, "group grant request from %u to TG %u denied", m_rfLC.getSrcId(), m_rfLC.getDstId());
+ ::ActivityLog("NXDN", true, "group grant request from %u to TG %u denied", srcId, dstId);
m_nxdn->m_rfState = RS_RF_REJECTED;
}
- m_rfLC.setMessageType(messageType);
return false;
}
// don't transmit grants if the destination ID's don't match and the network TG hang timer is running
if (m_nxdn->m_rfLastDstId != 0U) {
- if (m_nxdn->m_rfLastDstId != m_rfLC.getDstId() && (m_nxdn->m_rfTGHang.isRunning() && !m_nxdn->m_rfTGHang.hasExpired())) {
+ if (m_nxdn->m_rfLastDstId != dstId && (m_nxdn->m_rfTGHang.isRunning() && !m_nxdn->m_rfTGHang.hasExpired())) {
if (!net) {
- writeRF_Message_Deny(NXDN_CAUSE_VD_QUE_GRP_BUSY, RTCH_MESSAGE_TYPE_VCALL);
+ writeRF_Message_Deny(0U, srcId, NXDN_CAUSE_VD_QUE_GRP_BUSY, RTCH_MESSAGE_TYPE_VCALL);
m_nxdn->m_rfState = RS_RF_REJECTED;
}
- m_rfLC.setMessageType(messageType);
return false;
}
}
- if (!m_nxdn->m_affiliations.isGranted(m_rfLC.getDstId())) {
+ if (!m_nxdn->m_affiliations.isGranted(dstId)) {
if (!m_nxdn->m_affiliations.isRFChAvailable()) {
if (grp) {
if (!net) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " queued, no channels available, dstId = %u", m_rfLC.getDstId());
- writeRF_Message_Deny(NXDN_CAUSE_VD_QUE_CHN_RESOURCE_NOT_AVAIL, RTCH_MESSAGE_TYPE_VCALL);
+ LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " queued, no channels available, dstId = %u", dstId);
+ writeRF_Message_Deny(0U, srcId, NXDN_CAUSE_VD_QUE_CHN_RESOURCE_NOT_AVAIL, RTCH_MESSAGE_TYPE_VCALL);
- ::ActivityLog("NXDN", true, "group grant request from %u to TG %u queued", m_rfLC.getSrcId(), m_rfLC.getDstId());
+ ::ActivityLog("NXDN", true, "group grant request from %u to TG %u queued", srcId, dstId);
m_nxdn->m_rfState = RS_RF_REJECTED;
}
- m_rfLC.setMessageType(messageType);
return false;
}
else {
if (!net) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " queued, no channels available, dstId = %u", m_rfLC.getDstId());
- writeRF_Message_Deny(NXDN_CAUSE_VD_QUE_CHN_RESOURCE_NOT_AVAIL, RTCH_MESSAGE_TYPE_VCALL);
+ LogWarning(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_REQ " queued, no channels available, dstId = %u", dstId);
+ writeRF_Message_Deny(0U, srcId, NXDN_CAUSE_VD_QUE_CHN_RESOURCE_NOT_AVAIL, RTCH_MESSAGE_TYPE_VCALL);
- ::ActivityLog("P25", true, "unit-to-unit grant request from %u to %u queued", m_rfLC.getSrcId(), m_rfLC.getDstId());
+ ::ActivityLog("P25", true, "unit-to-unit grant request from %u to %u queued", srcId, dstId);
m_nxdn->m_rfState = RS_RF_REJECTED;
}
- m_rfLC.setMessageType(messageType);
return false;
}
}
else {
- if (m_nxdn->m_affiliations.grantCh(m_rfLC.getDstId(), GRANT_TIMER_TIMEOUT)) {
- uint32_t chNo = m_nxdn->m_affiliations.getGrantedCh(m_rfLC.getDstId());
- m_rfLC.setGrpVchNo(chNo);
+ if (m_nxdn->m_affiliations.grantCh(dstId, GRANT_TIMER_TIMEOUT)) {
+ chNo = m_nxdn->m_affiliations.getGrantedCh(dstId);
}
}
}
else {
- uint32_t chNo = m_nxdn->m_affiliations.getGrantedCh(m_rfLC.getDstId());
- m_rfLC.setGrpVchNo(chNo);
+ chNo = m_nxdn->m_affiliations.getGrantedCh(dstId);
}
}
if (grp) {
if (!net) {
- ::ActivityLog("NXDN", true, "group grant request from %u to TG %u", m_rfLC.getSrcId(), m_rfLC.getDstId());
+ ::ActivityLog("NXDN", true, "group grant request from %u to TG %u", srcId, dstId);
}
}
else {
if (!net) {
- ::ActivityLog("NXDN", true, "unit-to-unit grant request from %u to %u", m_rfLC.getSrcId(), m_rfLC.getDstId());
+ ::ActivityLog("NXDN", true, "unit-to-unit grant request from %u to %u", srcId, dstId);
}
}
+ std::unique_ptr rcch = new_unique(rcch::MESSAGE_TYPE_VCALL_CONN);
+ rcch->setMessageType(RTCH_MESSAGE_TYPE_VCALL);
+ rcch->setGrpVchNo(chNo);
+ rcch->setGroup(grp);
+ rcch->setSrcId(srcId);
+ rcch->setDstId(dstId);
+
+ rcch->setEmergency(emergency);
+ rcch->setEncrypted(encryption);
+ rcch->setPriority(priority);
+
if (m_verbose) {
LogMessage((net) ? LOG_NET : LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL_RESP ", emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u",
- m_rfLC.getEmergency(), m_rfLC.getEncrypted(), m_rfLC.getPriority(), m_rfLC.getGrpVchNo(), m_rfLC.getSrcId(), m_rfLC.getDstId());
+ rcch->getEmergency(), rcch->getEncrypted(), rcch->getPriority(), rcch->getGrpVchNo(), rcch->getSrcId(), rcch->getDstId());
}
// transmit group grant
- m_rfLC.setMessageType(RTCH_MESSAGE_TYPE_VCALL);
- writeRF_Message(false, true);
-
- m_rfLC.setMessageType(messageType);
+ writeRF_Message(rcch.get(), false, true);
return true;
}
///
/// Helper to write a deny packet.
///
+///
+///
///
///
-void Trunk::writeRF_Message_Deny(uint8_t reason, uint8_t service)
+void Trunk::writeRF_Message_Deny(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service)
{
- uint8_t messageType = m_rfLC.getMessageType();
+ std::unique_ptr rcch = nullptr;
+
+ switch (service) {
+ case RTCH_MESSAGE_TYPE_VCALL:
+ rcch = new_unique(rcch::MESSAGE_TYPE_VCALL_CONN);
+ rcch->setMessageType(RTCH_MESSAGE_TYPE_VCALL);
+ default:
+ return;
+ }
- m_rfLC.setMessageType(service);
- m_rfLC.setCauseResponse(reason);
+ rcch->setCauseResponse(reason);
+ rcch->setSrcId(srcId);
+ rcch->setDstId(dstId);
if (m_verbose) {
LogMessage(LOG_RF, "NXDN, MSG_DENIAL (Message Denial), reason = $%02X, service = $%02X, srcId = %u, dstId = %u",
- service, m_rfLC.getSrcId(), m_rfLC.getDstId());
+ service, srcId, dstId);
}
- writeRF_Message(false);
-
- m_rfLC.setMessageType(messageType);
+ writeRF_Message(rcch.get(), false);
}
///
@@ -576,49 +582,48 @@ void Trunk::writeRF_Message_Deny(uint8_t reason, uint8_t service)
///
///
///
-bool Trunk::writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstId)
+///
+bool Trunk::writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstId, uint32_t locId)
{
bool ret = false;
- m_rfLC.setMessageType(RCCH_MESSAGE_TYPE_GRP_REG);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_REG_ACCEPTED);
+ std::unique_ptr rcch = new_unique(rcch::MESSAGE_TYPE_GRP_REG);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_REG_ACCEPTED);
// validate the location ID
- if (m_rfLC.getLocId() != m_nxdn->m_siteData.locId()) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ " denial, LOCID rejection, locId = $%04X", m_rfLC.getLocId());
+ if (locId != m_nxdn->m_siteData.locId()) {
+ LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ " denial, LOCID rejection, locId = $%04X", locId);
::ActivityLog("NXDN", true, "group affiliation request from %u denied", srcId);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
}
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ " denial, RID rejection, srcId = %u", srcId);
::ActivityLog("NXDN", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
}
// validate the source RID is registered
if (!m_nxdn->m_affiliations.isUnitReg(srcId) && m_verifyReg) {
LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ " denial, RID not registered, srcId = %u", srcId);
::ActivityLog("NXDN", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_REG_REFUSED);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_REG_REFUSED);
}
// validate the talkgroup ID
- if (m_rfLC.getGroup()) {
- if (dstId == 0U) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ ", TGID 0, dstId = %u", dstId);
- }
- else {
- if (!acl::AccessControl::validateTGId(dstId)) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ " denial, TGID rejection, dstId = %u", dstId);
- ::ActivityLog("NXDN", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_LOC_ACPT_GRP_REFUSE);
- }
+ if (dstId == 0U) {
+ LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ ", TGID 0, dstId = %u", dstId);
+ }
+ else {
+ if (!acl::AccessControl::validateTGId(dstId)) {
+ LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ " denial, TGID rejection, dstId = %u", dstId);
+ ::ActivityLog("NXDN", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_LOC_ACPT_GRP_REFUSE);
}
}
- if (m_rfLC.getCauseResponse() == NXDN_CAUSE_MM_REG_ACCEPTED) {
+ if (rcch->getCauseResponse() == NXDN_CAUSE_MM_REG_ACCEPTED) {
if (m_verbose) {
LogMessage(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_GRP_REG_REQ ", srcId = %u, dstId = %u", srcId, dstId);
}
@@ -630,7 +635,7 @@ bool Trunk::writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstId)
m_nxdn->m_affiliations.groupAff(srcId, dstId);
}
- writeRF_Message(false);
+ writeRF_Message(rcch.get(), false);
return ret;
}
@@ -638,28 +643,28 @@ bool Trunk::writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstId)
/// Helper to write a unit registration response packet.
///
///
-void Trunk::writeRF_Message_U_Reg_Rsp(uint32_t srcId)
+void Trunk::writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t locId)
{
- m_rfLC.setMessageType(RCCH_MESSAGE_TYPE_REG);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_REG_ACCEPTED);
+ std::unique_ptr rcch = new_unique(rcch::MESSAGE_TYPE_REG);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_REG_ACCEPTED);
// validate the location ID
- if (m_rfLC.getLocId() != m_nxdn->m_siteData.locId()) {
- LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_REG_REQ " denial, LOCID rejection, locId = $%04X", m_rfLC.getLocId());
+ if (locId != m_nxdn->m_siteData.locId()) {
+ LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_REG_REQ " denial, LOCID rejection, locId = $%04X", locId);
::ActivityLog("NXDN", true, "unit registration request from %u denied", srcId);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
}
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
LogWarning(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_REG_REQ " denial, RID rejection, srcId = %u", srcId);
::ActivityLog("NXDN", true, "unit registration request from %u denied", srcId);
- m_rfLC.setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
+ rcch->setCauseResponse(NXDN_CAUSE_MM_REG_FAILED);
}
- if (m_rfLC.getCauseResponse() == NXDN_CAUSE_MM_REG_ACCEPTED) {
+ if (rcch->getCauseResponse() == NXDN_CAUSE_MM_REG_ACCEPTED) {
if (m_verbose) {
- LogMessage(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_REG_REQ ", srcId = %u, locId = %u", srcId, m_rfLC.getLocId());
+ LogMessage(LOG_RF, "NXDN, " NXDN_RCCH_MSG_TYPE_REG_REQ ", srcId = %u, locId = %u", srcId, locId);
}
::ActivityLog("NXDN", true, "unit registration request from %u", srcId);
@@ -670,10 +675,10 @@ void Trunk::writeRF_Message_U_Reg_Rsp(uint32_t srcId)
}
}
- m_rfLC.setSrcId(srcId);
- m_rfLC.setDstId(srcId);
+ rcch->setSrcId(srcId);
+ rcch->setDstId(srcId);
- writeRF_Message(true);
+ writeRF_Message(rcch.get(), true);
}
///
@@ -701,9 +706,14 @@ void Trunk::writeRF_CC_Message_Site_Info()
uint8_t buffer[NXDN_RCCH_LC_LENGTH_BYTES];
::memset(buffer, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES);
- m_rfLC.setVerbose(m_dumpRCCH);
- m_rfLC.setMessageType(RCCH_MESSAGE_TYPE_SITE_INFO);
- m_rfLC.encode(buffer, NXDN_RCCH_LC_LENGTH_BITS);
+ std::unique_ptr rcch = new_unique(rcch::MESSAGE_TYPE_SITE_INFO);
+ rcch->setBcchCnt(m_bcchCnt);
+ rcch->setRcchGroupingCnt(m_rcchGroupingCnt);
+ rcch->setCcchPagingCnt(m_ccchPagingCnt);
+ rcch->setCcchMultiCnt(m_ccchMultiCnt);
+ rcch->setRcchIterateCount(m_rcchIterateCnt);
+
+ rcch->encode(buffer, NXDN_RCCH_LC_LENGTH_BITS);
// generate the CAC
channel::CAC cac;
@@ -749,10 +759,9 @@ void Trunk::writeRF_CC_Message_Service_Info()
uint8_t buffer[NXDN_RCCH_LC_LENGTH_BYTES];
::memset(buffer, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES);
- m_rfLC.setVerbose(m_dumpRCCH);
- m_rfLC.setMessageType(MESSAGE_TYPE_SRV_INFO);
- m_rfLC.encode(buffer, NXDN_RCCH_LC_LENGTH_BITS / 2U);
- m_rfLC.encode(buffer, NXDN_RCCH_LC_LENGTH_BITS / 2U, NXDN_RCCH_LC_LENGTH_BITS / 2U);
+ std::unique_ptr rcch = new_unique(rcch::MESSAGE_TYPE_SRV_INFO);
+ rcch->encode(buffer, NXDN_RCCH_LC_LENGTH_BITS / 2U);
+ rcch->encode(buffer, NXDN_RCCH_LC_LENGTH_BITS / 2U, NXDN_RCCH_LC_LENGTH_BITS / 2U);
// generate the CAC
channel::CAC cac;
diff --git a/nxdn/packet/Trunk.h b/nxdn/packet/Trunk.h
index 6d01cbc2..e4d9d182 100644
--- a/nxdn/packet/Trunk.h
+++ b/nxdn/packet/Trunk.h
@@ -57,11 +57,6 @@ namespace nxdn
class HOST_SW_API Trunk {
public:
- /// Resets the data states for the RF interface.
- virtual void resetRF();
- /// Resets the data states for the network.
- virtual void resetNet();
-
/// Process a data frame from the RF interface.
virtual bool process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len);
/// Process a data frame from the network.
@@ -78,21 +73,22 @@ namespace nxdn
network::BaseNetwork* m_network;
+ uint8_t m_bcchCnt;
+ uint8_t m_rcchGroupingCnt;
+ uint8_t m_ccchPagingCnt;
+ uint8_t m_ccchMultiCnt;
+ uint8_t m_rcchIterateCnt;
+
bool m_verifyAff;
bool m_verifyReg;
- lc::RCCH m_rfLC;
- lc::RCCH m_netLC;
-
uint16_t m_lastRejectId;
- bool m_dumpRCCH;
-
bool m_verbose;
bool m_debug;
/// Initializes a new instance of the Trunk class.
- Trunk(Control* nxdn, network::BaseNetwork* network, bool dumpRCCHData, bool debug, bool verbose);
+ Trunk(Control* nxdn, network::BaseNetwork* network, bool debug, bool verbose);
/// Finalizes a instance of the Trunk class.
virtual ~Trunk();
@@ -103,16 +99,16 @@ namespace nxdn
void writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS);
/// Helper to write a single-block RCCH packet.
- void writeRF_Message(bool noNetwork, bool clearBeforeWrite = false);
+ void writeRF_Message(lc::RCCH* rcch, bool noNetwork, bool clearBeforeWrite = false);
/// Helper to write a grant packet.
- bool writeRF_Message_Grant(bool grp, bool skip = false, bool net = false, bool skipNetCheck = false);
+ bool writeRF_Message_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip = false, uint32_t chNo = 0U, bool net = false, bool skipNetCheck = false);
/// Helper to write a deny packet.
- void writeRF_Message_Deny(uint8_t reason, uint8_t service);
+ void writeRF_Message_Deny(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service);
/// Helper to write a group registration response packet.
- bool writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstId);
+ bool writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstId, uint32_t locId);
/// Helper to write a unit registration response packet.
- void writeRF_Message_U_Reg_Rsp(uint32_t srcId);
+ void writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t locId);
/// Helper to write a CC SITE_INFO broadcast packet on the RF interface.
void writeRF_CC_Message_Site_Info();
diff --git a/nxdn/packet/Voice.cpp b/nxdn/packet/Voice.cpp
index 266ae0c5..23ecf0e5 100644
--- a/nxdn/packet/Voice.cpp
+++ b/nxdn/packet/Voice.cpp
@@ -212,7 +212,6 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
facch.getData(buffer);
lc::RTCH lc;
- lc.setVerbose(m_dumpRTCH);
lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS);
uint16_t dstId = lc.getDstId();
uint16_t srcId = lc.getSrcId();
@@ -340,7 +339,6 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
facch.getData(buffer);
lc::RTCH lc;
- lc.setVerbose(m_dumpRTCH);
lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS);
hasInfo = lc.getMessageType() == RTCH_MESSAGE_TYPE_VCALL;
@@ -646,7 +644,6 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t
facch.getData(buffer);
lc::RTCH lc;
- lc.setVerbose(m_dumpRTCH);
lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS);
uint16_t dstId = lc.getDstId();
uint16_t srcId = lc.getSrcId();
@@ -753,7 +750,6 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t
facch.getData(buffer);
lc::RTCH lc;
- lc.setVerbose(m_dumpRTCH);
lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS);
hasInfo = lc.getMessageType() == RTCH_MESSAGE_TYPE_VCALL;
@@ -980,10 +976,9 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t
///
/// Instance of the Control class.
/// Instance of the BaseNetwork class.
-/// Flag indicating whether RTCH data is dumped to the log.
/// Flag indicating whether NXDN debug is enabled.
/// Flag indicating whether NXDN verbose logging is enabled.
-Voice::Voice(Control* nxdn, network::BaseNetwork* network, bool dumpRTCHData, bool debug, bool verbose) :
+Voice::Voice(Control* nxdn, network::BaseNetwork* network, bool debug, bool verbose) :
m_nxdn(nxdn),
m_network(network),
m_rfFrames(0U),
@@ -994,7 +989,6 @@ Voice::Voice(Control* nxdn, network::BaseNetwork* network, bool dumpRTCHData, bo
m_netLost(0U),
m_lastRejectId(0U),
m_silenceThreshold(DEFAULT_SILENCE_THRESHOLD),
- m_dumpRTCH(dumpRTCHData),
m_verbose(verbose),
m_debug(debug)
{
diff --git a/nxdn/packet/Voice.h b/nxdn/packet/Voice.h
index e3b60bee..e12e3689 100644
--- a/nxdn/packet/Voice.h
+++ b/nxdn/packet/Voice.h
@@ -84,13 +84,11 @@ namespace nxdn
uint32_t m_silenceThreshold;
- bool m_dumpRTCH;
-
bool m_verbose;
bool m_debug;
/// Initializes a new instance of the Voice class.
- Voice(Control* nxdn, network::BaseNetwork* network, bool dumpRTCHData, bool debug, bool verbose);
+ Voice(Control* nxdn, network::BaseNetwork* network, bool debug, bool verbose);
/// Finalizes a instance of the Voice class.
virtual ~Voice();