refactor TDULC into factory code pattern;

3.0-rcon_maint
Bryan Biedenkapp 3 years ago
parent de4b6ea30d
commit 471a00fa04

@ -33,6 +33,8 @@ file(GLOB dvmhost_SRC
"p25/edac/*.cpp"
"p25/lc/*.h"
"p25/lc/*.cpp"
"p25/lc/tdulc/*.h"
"p25/lc/tdulc/*.cpp"
"p25/lc/tsbk/*.h"
"p25/lc/tsbk/*.cpp"
"p25/lookups/*.h"
@ -105,6 +107,7 @@ option(ENABLE_DMR "Enable DMR Digtial Mode" on)
option(ENABLE_P25 "Enable P25 Digital Mode" on)
option(ENABLE_NXDN "Enable NXDN Digital Mode" off)
option(ENABLE_DFSI_SUPPORT "Enable P25 DFSI Transport Support" off)
option(ENABLE_TESTS "Enable compilation of test suite" off)
message(CHECK_START "DMR Digital Mode")
if (ENABLE_DMR)
@ -134,6 +137,12 @@ if (ENABLE_DFSI_SUPPORT)
else ()
message(CHECK_PASS "disabled")
endif (ENABLE_DFSI_SUPPORT)
message(CHECK_START "Enable test suite compilation")
if (ENABLE_TESTS)
message(CHECK_PASS "enabled")
else ()
message(CHECK_PASS "disabled")
endif (ENABLE_TESTS)
# debug options
option(DEBUG_DMR_PDU_DATA "" off)
@ -267,6 +276,7 @@ add_executable(dvmcmd ${dvmcmd_SRC})
target_link_libraries(dvmcmd PRIVATE Threads::Threads)
target_include_directories(dvmcmd PRIVATE .)
if (ENABLE_TESTS)
project(dvmtest)
Include(FetchContent)
@ -281,3 +291,4 @@ find_package(Threads REQUIRED)
add_executable(dvmtests ${dvmtests_SRC})
target_link_libraries(dvmtests PRIVATE Catch2::Catch2WithMain Threads::Threads util)
target_include_directories(dvmtests PRIVATE .)
endif (ENABLE_TESTS)

@ -300,8 +300,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
}
}
lc::TDULC::setIdenEntry(m_idenEntry);
std::vector<uint32_t> availCh = voiceChNo;
m_siteData.setChCnt((uint8_t)availCh.size());

@ -101,7 +101,7 @@ DFSITrunk::~DFSITrunk()
/// </summary>
/// <param name="lc"></param>
/// <param name="noNetwork"></param>
void DFSITrunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
void DFSITrunk::writeRF_TDULC(lc::TDULC* lc, bool noNetwork)
{
// for now this is ignored...
}

@ -65,7 +65,7 @@ namespace p25
virtual ~DFSITrunk();
/// <summary>Helper to write a P25 TDU w/ link control packet.</summary>
virtual void writeRF_TDULC(lc::TDULC lc, bool noNetwork);
virtual void writeRF_TDULC(lc::TDULC* lc, bool noNetwork);
/// <summary>Helper to write a single-block P25 TSDU packet.</summary>
virtual void writeRF_TSDU_SBF(lc::TSBK* tsbk, bool noNetwork, bool clearBeforeWrite = false, bool force = false);

@ -47,7 +47,6 @@ using namespace p25;
bool TDULC::m_verbose = false;
SiteData TDULC::m_siteData = SiteData();
::lookups::IdenTable TDULC::m_siteIdenEntry = ::lookups::IdenTable();
// ---------------------------------------------------------------------------
// Public Class Members
@ -96,17 +95,13 @@ TDULC::TDULC() :
m_srcId(0U),
m_dstId(0U),
m_grpVchNo(0U),
m_adjCFVA(P25_CFVA_FAILURE),
m_adjRfssId(0U),
m_adjSiteId(0U),
m_adjChannelId(0U),
m_adjChannelNo(0U),
m_adjServiceClass(P25_SVC_CLS_INVALID),
m_emergency(false),
m_encrypted(false),
m_priority(4U),
m_group(true),
m_siteIdenEntry(lookups::IdenTable()),
m_rs(),
m_implicit(false),
m_callTimer(0U)
{
m_grpVchNo = m_siteData.channelNo();
@ -120,31 +115,66 @@ TDULC::~TDULC()
/* stub */
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Equals operator.
/// Internal helper to convert RS bytes to a 64-bit long value.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
/// <returns></returns>
TDULC& TDULC::operator=(const TDULC& data)
ulong64_t TDULC::toValue(const uint8_t* rs)
{
if (this != &data) {
copy(data);
}
ulong64_t rsValue = 0U;
// combine bytes into ulong64_t (8 byte) value
rsValue = rs[1U];
rsValue = (rsValue << 8) + rs[2U];
rsValue = (rsValue << 8) + rs[3U];
rsValue = (rsValue << 8) + rs[4U];
rsValue = (rsValue << 8) + rs[5U];
rsValue = (rsValue << 8) + rs[6U];
rsValue = (rsValue << 8) + rs[7U];
rsValue = (rsValue << 8) + rs[8U];
return *this;
return rsValue;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// Internal helper to convert a 64-bit long value to RS bytes.
/// </summary>
/// <param name="rsValue"></param>
/// <returns></returns>
std::unique_ptr<uint8_t[]> TDULC::fromValue(const ulong64_t rsValue)
{
__UNIQUE_BUFFER(rs, uint8_t, P25_TDULC_LENGTH_BYTES);
// split ulong64_t (8 byte) value into bytes
rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU);
rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU);
rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU);
rs[4U] = (uint8_t)((rsValue >> 32) & 0xFFU);
rs[5U] = (uint8_t)((rsValue >> 24) & 0xFFU);
rs[6U] = (uint8_t)((rsValue >> 16) & 0xFFU);
rs[7U] = (uint8_t)((rsValue >> 8) & 0xFFU);
rs[8U] = (uint8_t)((rsValue >> 0) & 0xFFU);
return rs;
}
/// <summary>
/// Internal helper to decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <param name="rs"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool TDULC::decode(const uint8_t* data)
bool TDULC::decode(const uint8_t* data, uint8_t* rs)
{
assert(data != nullptr);
assert(rs != nullptr);
// deinterleave
uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U];
uint8_t raw[P25_TDULC_FEC_LENGTH_BYTES + 1U];
P25Utils::decode(data, raw, 114U, 410U);
@ -172,39 +202,42 @@ bool TDULC::decode(const uint8_t* data)
Utils::dump(2U, "Decoded TDULC", rs, P25_TDULC_LENGTH_BYTES);
}
return decodeLC(rs);
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// Internal helper to encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
void TDULC::encode(uint8_t * data)
/// <param name="rs"></param>
void TDULC::encode(uint8_t* data, const uint8_t* rs)
{
assert(data != nullptr);
uint8_t rs[P25_TDULC_LENGTH_BYTES];
::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES);
encodeLC(rs);
assert(rs != nullptr);
if (m_verbose) {
Utils::dump(2U, "Encoded TDULC", rs, P25_TDULC_LENGTH_BYTES);
}
uint8_t outRs[P25_TDULC_LENGTH_BYTES];
::memset(outRs, 0x00U, P25_TDULC_LENGTH_BYTES);
::memcpy(outRs, rs, P25_TDULC_LENGTH_BYTES);
if (m_implicit)
outRs[0U] |= 0x40U; // Implicit Operation
// encode RS (24,12,13) FEC
m_rs.encode241213(rs);
m_rs.encode241213(outRs);
#if DEBUG_P25_TDULC
Utils::dump(2U, "TDULC::encode(), TDULC RS", rs, P25_TDULC_LENGTH_BYTES);
Utils::dump(2U, "TDULC::encode(), TDULC RS", outRs, P25_TDULC_LENGTH_BYTES);
#endif
uint8_t raw[P25_TDULC_FEC_LENGTH_BYTES + 1U];
::memset(raw, 0x00U, P25_TDULC_FEC_LENGTH_BYTES + 1U);
// encode Golay (24,12,8) FEC
edac::Golay24128::encode24128(raw, rs, P25_TDULC_LENGTH_BYTES);
edac::Golay24128::encode24128(raw, outRs, P25_TDULC_LENGTH_BYTES);
// interleave
P25Utils::encode(raw, data, 114U, 410U);
@ -214,10 +247,6 @@ void TDULC::encode(uint8_t * data)
#endif
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
@ -234,13 +263,6 @@ void TDULC::copy(const TDULC& data)
m_grpVchNo = data.m_grpVchNo;
m_adjCFVA = data.m_adjCFVA;
m_adjRfssId = data.m_adjRfssId;
m_adjSiteId = data.m_adjSiteId;
m_adjChannelId = data.m_adjChannelId;
m_adjChannelNo = data.m_adjChannelNo;
m_adjServiceClass = data.m_adjServiceClass;
m_emergency = data.m_emergency;
m_encrypted = data.m_encrypted;
m_priority = data.m_priority;
@ -252,241 +274,3 @@ void TDULC::copy(const TDULC& data)
m_siteData = data.m_siteData;
m_siteIdenEntry = data.m_siteIdenEntry;
}
/// <summary>
/// Decode link control.
/// </summary>
/// <param name="rs"></param>
/// <returns></returns>
bool TDULC::decodeLC(const uint8_t* rs)
{
ulong64_t rsValue = 0U;
// combine bytes into ulong64_t (8 byte) value
rsValue = rs[1U];
rsValue = (rsValue << 8) + rs[2U];
rsValue = (rsValue << 8) + rs[3U];
rsValue = (rsValue << 8) + rs[4U];
rsValue = (rsValue << 8) + rs[5U];
rsValue = (rsValue << 8) + rs[6U];
rsValue = (rsValue << 8) + rs[7U];
rsValue = (rsValue << 8) + rs[8U];
m_protect = (rs[0U] & 0x80U) == 0x80U; // Protect Flag
m_lco = rs[0U] & 0x3FU; // LCO
// standard P25 reference opcodes
switch (m_lco) {
case LC_GROUP:
m_mfId = rs[1U]; // Mfg Id.
m_group = true;
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag
m_priority = (rs[2U] & 0x07U); // Priority
m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Talkgroup Address
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address
break;
case LC_PRIVATE:
m_mfId = rs[1U]; // Mfg Id.
m_group = false;
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag
m_priority = (rs[2U] & 0x07U); // Priority
m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFFFU); // Target Radio Address
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address
break;
case LC_TEL_INT_VCH_USER:
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag
m_priority = (rs[2U] & 0x07U); // Priority
m_callTimer = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Call Timer
if (m_srcId == 0U) {
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source/Target Address
}
break;
default:
LogError(LOG_P25, "TDULC::decodeLC(), unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
return false;
}
// sanity check priority (per TIA-102.AABC-B) it should never be 0, if its 0, default to 4
if (m_priority == 0) {
m_priority = 4U;
}
return true;
}
/// <summary>
/// Encode link control.
/// </summary>
/// <param name="rs"></param>
void TDULC::encodeLC(uint8_t* rs)
{
const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT;
ulong64_t rsValue = 0U;
rs[0U] = m_lco; // LCO
// standard P25 reference opcodes
switch (m_lco) {
case LC_GROUP:
rsValue = m_mfId;
rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
(m_priority & 0x07U); // Priority
rsValue = (rsValue << 24) + m_dstId; // Talkgroup Address
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
break;
case LC_GROUP_UPDT:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = m_siteData.channelId(); // Group A - Channel ID
rsValue = (rsValue << 12) + m_grpVchNo; // Group A - Channel Number
rsValue = (rsValue << 16) + m_dstId; // Group A - Talkgroup Address
rsValue = (rsValue << 4) + m_siteData.channelId(); // Group B - Channel ID
rsValue = (rsValue << 12) + m_grpVchNo; // Group B - Channel Number
rsValue = (rsValue << 16) + m_dstId; // Group B - Talkgroup Address
break;
case LC_PRIVATE:
rsValue = m_mfId;
rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
(m_priority & 0x07U); // Priority
rsValue = (rsValue << 24) + m_dstId; // Target Radio Address
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
break;
case LC_TEL_INT_VCH_USER:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
(m_priority & 0x07U); // Priority
rsValue = (rsValue << 16) + m_callTimer; // Call Timer
rsValue = (rsValue << 24) + m_srcId; // Source/Target Radio Address
break;
case LC_CALL_TERM:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = 0U;
rsValue = (rsValue << 24) + P25_WUID_FNE; // System Radio Address
break;
case LC_IDEN_UP:
rs[0U] |= 0x40U; // Implicit Operation
{
if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) &&
(m_siteIdenEntry.txOffsetMhz() != 0U) && (m_siteIdenEntry.baseFrequency() != 0U)) {
if (m_siteIdenEntry.baseFrequency() < 762000000U) {
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) / m_siteIdenEntry.chSpaceKhz()) * 1000.0F;
uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? P25_IDEN_UP_VU_BW_125K : P25_IDEN_UP_VU_BW_625K;
rsValue = m_siteIdenEntry.channelId(); // Channel ID
rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth
rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset
rsValue = (rsValue << 10) + calcSpace; // Channel Spacing
rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency
} else {
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) * 1000000.0F) / 250000.0F;
uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
uint16_t chanBw = (uint16_t)((m_siteIdenEntry.chBandwidthKhz() * 1000) / 125);
rsValue = m_siteIdenEntry.channelId(); // Channel ID
rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth
rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset
rsValue = (rsValue << 10) + calcSpace; // Channel Spacing
rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency
}
}
else {
LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_IDEN_UP, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz",
m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(),
m_siteIdenEntry.chSpaceKhz());
return; // blatently ignore creating this TSBK
}
}
break;
case LC_SYS_SRV_BCAST:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = 0U;
rsValue = (rsValue << 16) + services; // System Services Available
rsValue = (rsValue << 24) + services; // System Services Supported
break;
case LC_ADJ_STS_BCAST:
rs[0U] |= 0x40U; // Implicit Operation
{
if ((m_adjRfssId != 0U) && (m_adjSiteId != 0U) && (m_adjChannelNo != 0U)) {
if (m_adjSysId == 0U) {
m_adjSysId = m_siteData.sysId();
}
rsValue = m_siteData.lra(); // Location Registration Area
rsValue = (rsValue << 12) + m_adjSysId; // System ID
rsValue = (rsValue << 8) + m_adjRfssId; // RF Sub-System ID
rsValue = (rsValue << 8) + m_adjSiteId; // Site ID
rsValue = (rsValue << 4) + m_adjChannelId; // Channel ID
rsValue = (rsValue << 12) + m_adjChannelNo; // Channel Number
rsValue = (rsValue << 8) + m_adjServiceClass; // System Service Class
}
else {
LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_ADJ_STS_BCAST, tsbkAdjSiteRFSSId = $%02X, tsbkAdjSiteId = $%02X, tsbkAdjSiteChannel = $%02X",
m_adjRfssId, m_adjSiteId, m_adjChannelNo);
return; // blatently ignore creating this TSBK
}
}
break;
case LC_RFSS_STS_BCAST:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = m_siteData.lra(); // Location Registration Area
rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID
rsValue = (rsValue << 8) + m_siteData.rfssId(); // RF Sub-System ID
rsValue = (rsValue << 8) + m_siteData.siteId(); // Site ID
rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID
rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number
rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class
break;
case LC_NET_STS_BCAST:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = 0U;
rsValue = (rsValue << 20) + m_siteData.netId(); // Network ID
rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID
rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID
rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number
rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class
break;
case LC_CONV_FALLBACK:
rsValue = 0U;
rsValue = (rsValue << 48) + m_siteData.channelId(); // Channel ID 6
rsValue = (rsValue << 40) + m_siteData.channelId(); // Channel ID 5
rsValue = (rsValue << 32) + m_siteData.channelId(); // Channel ID 4
rsValue = (rsValue << 24) + m_siteData.channelId(); // Channel ID 3
rsValue = (rsValue << 16) + m_siteData.channelId(); // Channel ID 2
rsValue = (rsValue << 8) + m_siteData.channelId(); // Channel ID 1
break;
default:
LogError(LOG_P25, "TDULC::encodeLC(), unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
break;
}
// split ulong64_t (8 byte) value into bytes
rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU);
rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU);
rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU);
rs[4U] = (uint8_t)((rsValue >> 32) & 0xFFU);
rs[5U] = (uint8_t)((rsValue >> 24) & 0xFFU);
rs[6U] = (uint8_t)((rsValue >> 16) & 0xFFU);
rs[7U] = (uint8_t)((rsValue >> 8) & 0xFFU);
rs[8U] = (uint8_t)((rsValue >> 0) & 0xFFU);
}

@ -61,15 +61,12 @@ namespace p25
/// <summary>Initializes a new instance of the TDULC class.</summary>
TDULC();
/// <summary>Finalizes a instance of the TDULC class.</summary>
~TDULC();
/// <summary>Equals operator.</summary>
TDULC& operator=(const TDULC& data);
virtual ~TDULC();
/// <summary>Decode a terminator data unit w/ link control.</summary>
bool decode(const uint8_t* data);
virtual bool decode(const uint8_t* data) = 0;
/// <summary>Encode a terminator data unit w/ link control.</summary>
void encode(uint8_t* data);
virtual void encode(uint8_t* data) = 0;
/// <summary>Sets the flag indicating verbose log output.</summary>
static void setVerbose(bool verbose) { m_verbose = verbose; }
@ -79,74 +76,62 @@ namespace p25
static SiteData getSiteData() { return m_siteData; }
/// <summary>Sets the local site data.</summary>
static void setSiteData(SiteData siteData) { m_siteData = siteData; }
/// <summary>Gets the local site identity entry.</summary>
static ::lookups::IdenTable getIdenEntry() { return m_siteIdenEntry; }
/// <summary>Sets the local site identity entry.</summary>
static void setIdenEntry(::lookups::IdenTable entry) { m_siteIdenEntry = entry; }
public:
/** Common Data */
/// <summary>Flag indicating the link control data is protected.</summary>
__PROPERTY(bool, protect, Protect);
__PROTECTED_PROPERTY(bool, protect, Protect);
/// <summary>Link control opcode.</summary>
__PROPERTY(uint8_t, lco, LCO);
__PROTECTED_PROPERTY(uint8_t, lco, LCO);
/// <summary>Manufacturer ID.</summary>
__PROPERTY(uint8_t, mfId, MFId);
__PROTECTED_PROPERTY(uint8_t, mfId, MFId);
/// <summary>Source ID.</summary>
__PROPERTY(uint32_t, srcId, SrcId);
__PROTECTED_PROPERTY(uint32_t, srcId, SrcId);
/// <summary>Destination ID.</summary>
__PROPERTY(uint32_t, dstId, DstId);
__PROTECTED_PROPERTY(uint32_t, dstId, DstId);
/// <summary>Voice channel number.</summary>
__PROPERTY(uint32_t, grpVchNo, GrpVchNo);
/** Adjacent Site Data */
/// <summary>Adjacent site CFVA flags.</summary>
__PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA);
/// <summary>Adjacent site system ID.</summary>
__PROPERTY(uint32_t, adjSysId, AdjSiteSysId);
/// <summary>Adjacent site RFSS ID.</summary>
__PROPERTY(uint8_t, adjRfssId, AdjSiteRFSSId);
/// <summary>Adjacent site ID.</summary>
__PROPERTY(uint8_t, adjSiteId, AdjSiteId);
/// <summary>Adjacent site channel ID.</summary>
__PROPERTY(uint8_t, adjChannelId, AdjSiteChnId);
/// <summary>Adjacent site channel number.</summary>
__PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo);
/// <summary>Adjacent site service class.</summary>
__PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass);
__PROTECTED_PROPERTY(uint32_t, grpVchNo, GrpVchNo);
/** Service Options */
/// <summary>Flag indicating the emergency bits are set.</summary>
__PROPERTY(bool, emergency, Emergency);
__PROTECTED_PROPERTY(bool, emergency, Emergency);
/// <summary>Flag indicating that encryption is enabled.</summary>
__PROPERTY(bool, encrypted, Encrypted);
__PROTECTED_PROPERTY(bool, encrypted, Encrypted);
/// <summary>Priority level for the traffic.</summary>
__PROPERTY(uint8_t, priority, Priority);
__PROTECTED_PROPERTY(uint8_t, priority, Priority);
/// <summary>Flag indicating a group/talkgroup operation.</summary>
__PROPERTY(bool, group, Group);
__PROTECTED_PROPERTY(bool, group, Group);
/** Local Site data */
/// <summary>Local Site Identity Entry.</summary>
__PROTECTED_PROPERTY_PLAIN(::lookups::IdenTable, siteIdenEntry, siteIdenEntry);
protected:
friend class LC;
friend class TSBK;
edac::RS634717 m_rs;
bool m_implicit;
uint32_t m_callTimer;
static bool m_verbose;
/** Local Site data */
static SiteData m_siteData;
static ::lookups::IdenTable m_siteIdenEntry;
/// <summary>Internal helper to copy the class.</summary>
void copy(const TDULC& data);
/// <summary>Internal helper to convert RS bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const uint8_t* rs);
/// <summary>Internal helper to convert a 64-bit long value to RS bytes.</summary>
static std::unique_ptr<uint8_t[]> fromValue(const ulong64_t rsValue);
/// <summary>Internal helper to decode terminator data unit w/ link control.</summary>
bool decode(const uint8_t* data, uint8_t* rs);
/// <summary>Internal helper to encode terminator data unit w/ link control.</summary>
void encode(uint8_t* data, const uint8_t* rs);
/// <summary>Decode link control.</summary>
bool decodeLC(const uint8_t* rs);
/// <summary>Encode link control.</summary>
void encodeLC(uint8_t* rs);
__PROTECTED_COPY(TDULC);
};
} // namespace lc
} // namespace p25

@ -0,0 +1,123 @@
/**
* 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 "p25/lc/tdulc/LC_ADJ_STS_BCAST.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_ADJ_STS_BCAST class.
/// </summary>
LC_ADJ_STS_BCAST::LC_ADJ_STS_BCAST() : TDULC(),
m_adjCFVA(P25_CFVA_FAILURE),
m_adjRfssId(0U),
m_adjSiteId(0U),
m_adjChannelId(0U),
m_adjChannelNo(0U),
m_adjServiceClass(P25_SVC_CLS_INVALID)
{
m_lco = p25::LC_ADJ_STS_BCAST;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_ADJ_STS_BCAST::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_ADJ_STS_BCAST::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
m_implicit = true;
if ((m_adjRfssId != 0U) && (m_adjSiteId != 0U) && (m_adjChannelNo != 0U)) {
if (m_adjSysId == 0U) {
m_adjSysId = m_siteData.sysId();
}
rsValue = m_siteData.lra(); // Location Registration Area
rsValue = (rsValue << 12) + m_adjSysId; // System ID
rsValue = (rsValue << 8) + m_adjRfssId; // RF Sub-System ID
rsValue = (rsValue << 8) + m_adjSiteId; // Site ID
rsValue = (rsValue << 4) + m_adjChannelId; // Channel ID
rsValue = (rsValue << 12) + m_adjChannelNo; // Channel Number
rsValue = (rsValue << 8) + m_adjServiceClass; // System Service Class
}
else {
LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_ADJ_STS_BCAST, tsbkAdjSiteRFSSId = $%02X, tsbkAdjSiteId = $%02X, tsbkAdjSiteChannel = $%02X",
m_adjRfssId, m_adjSiteId, m_adjChannelNo);
return; // blatently ignore creating this TSBK
}
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
void LC_ADJ_STS_BCAST::copy(const LC_ADJ_STS_BCAST& data)
{
TDULC::copy(data);
m_adjCFVA = data.m_adjCFVA;
m_adjRfssId = data.m_adjRfssId;
m_adjSiteId = data.m_adjSiteId;
m_adjChannelId = data.m_adjChannelId;
m_adjChannelNo = data.m_adjChannelNo;
m_adjServiceClass = data.m_adjServiceClass;
}

@ -0,0 +1,75 @@
/**
* 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(__P25_LC_TSBK__LC_ADJ_STS_BCAST_H__)
#define __P25_LC_TSBK__LC_ADJ_STS_BCAST_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements ADJ STS BCAST - Adjacent Site Status Broadcast
// ---------------------------------------------------------------------------
class HOST_SW_API LC_ADJ_STS_BCAST : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_ADJ_STS_BCAST class.</summary>
LC_ADJ_STS_BCAST();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Adjacent site CFVA flags.</summary>
__PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA);
/// <summary>Adjacent site system ID.</summary>
__PROPERTY(uint32_t, adjSysId, AdjSiteSysId);
/// <summary>Adjacent site RFSS ID.</summary>
__PROPERTY(uint8_t, adjRfssId, AdjSiteRFSSId);
/// <summary>Adjacent site ID.</summary>
__PROPERTY(uint8_t, adjSiteId, AdjSiteId);
/// <summary>Adjacent site channel ID.</summary>
__PROPERTY(uint8_t, adjChannelId, AdjSiteChnId);
/// <summary>Adjacent site channel number.</summary>
__PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo);
/// <summary>Adjacent site service class.</summary>
__PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass);
__COPY(LC_ADJ_STS_BCAST);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_ADJ_STS_BCAST_H__

@ -0,0 +1,81 @@
/**
* 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 "p25/lc/tdulc/LC_CALL_TERM.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_CALL_TERM class.
/// </summary>
LC_CALL_TERM::LC_CALL_TERM() : TDULC()
{
m_lco = p25::LC_CALL_TERM;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_CALL_TERM::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_CALL_TERM::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
m_implicit = true;
rsValue = 0U;
rsValue = (rsValue << 24) + P25_WUID_FNE; // System Radio Address
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_CALL_TERM_H__)
#define __P25_LC_TSBK__LC_CALL_TERM_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements CALL TERM - Call Termination or Cancellation
// ---------------------------------------------------------------------------
class HOST_SW_API LC_CALL_TERM : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_CALL_TERM class.</summary>
LC_CALL_TERM();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_CALL_TERM_H__

@ -0,0 +1,83 @@
/**
* 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 "p25/lc/tdulc/LC_CONV_FALLBACK.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_CONV_FALLBACK class.
/// </summary>
LC_CONV_FALLBACK::LC_CONV_FALLBACK() : TDULC()
{
m_lco = p25::LC_CONV_FALLBACK;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_CONV_FALLBACK::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_CONV_FALLBACK::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
rsValue = (rsValue << 48) + m_siteData.channelId(); // Channel ID 6
rsValue = (rsValue << 40) + m_siteData.channelId(); // Channel ID 5
rsValue = (rsValue << 32) + m_siteData.channelId(); // Channel ID 4
rsValue = (rsValue << 24) + m_siteData.channelId(); // Channel ID 3
rsValue = (rsValue << 16) + m_siteData.channelId(); // Channel ID 2
rsValue = (rsValue << 8) + m_siteData.channelId(); // Channel ID 1
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_CONV_FALLBACK_H__)
#define __P25_LC_TSBK__LC_CONV_FALLBACK_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements CONV FALLBACK - Conventional Fallback
// ---------------------------------------------------------------------------
class HOST_SW_API LC_CONV_FALLBACK : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_CONV_FALLBACK class.</summary>
LC_CONV_FALLBACK();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_CONV_FALLBACK_H__

@ -0,0 +1,99 @@
/**
* 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 "p25/lc/tdulc/LC_GROUP.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_GROUP class.
/// </summary>
LC_GROUP::LC_GROUP() : TDULC()
{
m_lco = p25::LC_GROUP;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_GROUP::decode(const uint8_t* data)
{
assert(data != NULL);
uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U];
::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES);
bool ret = TDULC::decode(data, rs);
if (!ret)
return false;
ulong64_t rsValue = TDULC::toValue(rs);
m_mfId = rs[1U]; // Mfg Id.
m_group = true;
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag
m_priority = (rs[2U] & 0x07U); // Priority
m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Talkgroup Address
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_GROUP::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
rsValue = m_mfId;
rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
(m_priority & 0x07U); // Priority
rsValue = (rsValue << 24) + m_dstId; // Talkgroup Address
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_GROUP_H__)
#define __P25_LC_TSBK__LC_GROUP_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements GRP VCH USER - Group Voice Channel User
// ---------------------------------------------------------------------------
class HOST_SW_API LC_GROUP : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_GROUP class.</summary>
LC_GROUP();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_GROUP_H__

@ -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 "p25/lc/tdulc/LC_GROUP_UPDT.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_GROUP_UPDT class.
/// </summary>
LC_GROUP_UPDT::LC_GROUP_UPDT() : TDULC()
{
m_lco = p25::LC_GROUP_UPDT;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_GROUP_UPDT::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_GROUP_UPDT::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
m_implicit = true;
rsValue = m_siteData.channelId(); // Group A - Channel ID
rsValue = (rsValue << 12) + m_grpVchNo; // Group A - Channel Number
rsValue = (rsValue << 16) + m_dstId; // Group A - Talkgroup Address
rsValue = (rsValue << 4) + m_siteData.channelId(); // Group B - Channel ID
rsValue = (rsValue << 12) + m_grpVchNo; // Group B - Channel Number
rsValue = (rsValue << 16) + m_dstId; // Group B - Talkgroup Address
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_GROUP_UPDT_H__)
#define __P25_LC_TSBK__LC_GROUP_UPDT_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements GRP VCH UPDT - Group Voice Channel Update
// ---------------------------------------------------------------------------
class HOST_SW_API LC_GROUP_UPDT : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_GROUP_UPDT class.</summary>
LC_GROUP_UPDT();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_GROUP_UPDT_H__

@ -0,0 +1,121 @@
/**
* 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 "p25/lc/tdulc/LC_IDEN_UP.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_IDEN_UP class.
/// </summary>
LC_IDEN_UP::LC_IDEN_UP() : TDULC()
{
m_lco = p25::LC_IDEN_UP;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_IDEN_UP::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_IDEN_UP::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
m_implicit = true;
if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) &&
(m_siteIdenEntry.txOffsetMhz() != 0U) && (m_siteIdenEntry.baseFrequency() != 0U)) {
if (m_siteIdenEntry.baseFrequency() < 762000000U) {
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) / m_siteIdenEntry.chSpaceKhz()) * 1000.0F;
uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? P25_IDEN_UP_VU_BW_125K : P25_IDEN_UP_VU_BW_625K;
rsValue = m_siteIdenEntry.channelId(); // Channel ID
rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth
rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset
rsValue = (rsValue << 10) + calcSpace; // Channel Spacing
rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency
} else {
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) * 1000000.0F) / 250000.0F;
uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
uint16_t chanBw = (uint16_t)((m_siteIdenEntry.chBandwidthKhz() * 1000) / 125);
rsValue = m_siteIdenEntry.channelId(); // Channel ID
rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth
rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset
rsValue = (rsValue << 10) + calcSpace; // Channel Spacing
rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency
}
}
else {
LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_IDEN_UP, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz",
m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(),
m_siteIdenEntry.chSpaceKhz());
return; // blatently ignore creating this TSBK
}
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_IDEN_UP_H__)
#define __P25_LC_TSBK__LC_IDEN_UP_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements IDEN UP - Channel Identifier Update
// ---------------------------------------------------------------------------
class HOST_SW_API LC_IDEN_UP : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_IDEN_UP class.</summary>
LC_IDEN_UP();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_IDEN_UP_H__

@ -0,0 +1,84 @@
/**
* 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 "p25/lc/tdulc/LC_NET_STS_BCAST.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_NET_STS_BCAST class.
/// </summary>
LC_NET_STS_BCAST::LC_NET_STS_BCAST() : TDULC()
{
m_lco = p25::LC_NET_STS_BCAST;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_NET_STS_BCAST::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_NET_STS_BCAST::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
m_implicit = true;
rsValue = (rsValue << 20) + m_siteData.netId(); // Network ID
rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID
rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID
rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number
rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_NET_STS_BCAST_H__)
#define __P25_LC_TSBK__LC_NET_STS_BCAST_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements NET STS BCAST - Network Status Broadcast
// ---------------------------------------------------------------------------
class HOST_SW_API LC_NET_STS_BCAST : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_NET_STS_BCAST class.</summary>
LC_NET_STS_BCAST();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_NET_STS_BCAST_H__

@ -0,0 +1,99 @@
/**
* 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 "p25/lc/tdulc/LC_PRIVATE.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_PRIVATE class.
/// </summary>
LC_PRIVATE::LC_PRIVATE() : TDULC()
{
m_lco = p25::LC_PRIVATE;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_PRIVATE::decode(const uint8_t* data)
{
assert(data != NULL);
uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U];
::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES);
bool ret = TDULC::decode(data, rs);
if (!ret)
return false;
ulong64_t rsValue = TDULC::toValue(rs);
m_mfId = rs[1U]; // Mfg Id.
m_group = false;
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag
m_priority = (rs[2U] & 0x07U); // Priority
m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFFFU); // Target Radio Address
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_PRIVATE::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
rsValue = m_mfId;
rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
(m_priority & 0x07U); // Priority
rsValue = (rsValue << 24) + m_dstId; // Target Radio Address
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_PRIVATE_H__)
#define __P25_LC_TSBK__LC_PRIVATE_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements UU VCH USER - Unit-to-Unit Voice Channel User
// ---------------------------------------------------------------------------
class HOST_SW_API LC_PRIVATE : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_PRIVATE class.</summary>
LC_PRIVATE();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_PRIVATE_H__

@ -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 "p25/lc/tdulc/LC_RFSS_STS_BCAST.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_RFSS_STS_BCAST class.
/// </summary>
LC_RFSS_STS_BCAST::LC_RFSS_STS_BCAST() : TDULC()
{
m_lco = p25::LC_RFSS_STS_BCAST;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_RFSS_STS_BCAST::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_RFSS_STS_BCAST::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
m_implicit = true;
rsValue = m_siteData.lra(); // Location Registration Area
rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID
rsValue = (rsValue << 8) + m_siteData.rfssId(); // RF Sub-System ID
rsValue = (rsValue << 8) + m_siteData.siteId(); // Site ID
rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID
rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number
rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_RFSS_STS_BCAST_H__)
#define __P25_LC_TSBK__LC_RFSS_STS_BCAST_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements RFSS STS BCAST - RFSS Status Broadcast
// ---------------------------------------------------------------------------
class HOST_SW_API LC_RFSS_STS_BCAST : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_RFSS_STS_BCAST class.</summary>
LC_RFSS_STS_BCAST();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_RFSS_STS_BCAST_H__

@ -0,0 +1,84 @@
/**
* 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 "p25/lc/tdulc/LC_SYS_SRV_BCAST.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_SYS_SRV_BCAST class.
/// </summary>
LC_SYS_SRV_BCAST::LC_SYS_SRV_BCAST() : TDULC()
{
m_lco = p25::LC_SYS_SRV_BCAST;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_SYS_SRV_BCAST::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_SYS_SRV_BCAST::encode(uint8_t* data)
{
assert(data != NULL);
const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT;
ulong64_t rsValue = 0U;
m_implicit = true;
rsValue = 0U;
rsValue = (rsValue << 16) + services; // System Services Available
rsValue = (rsValue << 24) + services; // System Services Supported
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_SYS_SRV_BCAST_H__)
#define __P25_LC_TSBK__LC_SYS_SRV_BCAST_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements SYS SRV BCAST - System Service Broadcast
// ---------------------------------------------------------------------------
class HOST_SW_API LC_SYS_SRV_BCAST : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_SYS_SRV_BCAST class.</summary>
LC_SYS_SRV_BCAST();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_SYS_SRV_BCAST_H__

@ -0,0 +1,101 @@
/**
* 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 "p25/lc/tdulc/LC_TEL_INT_VCH_USER.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the LC_TEL_INT_VCH_USER class.
/// </summary>
LC_TEL_INT_VCH_USER::LC_TEL_INT_VCH_USER() : TDULC()
{
m_lco = p25::LC_TEL_INT_VCH_USER;
}
/// <summary>
/// Decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool LC_TEL_INT_VCH_USER::decode(const uint8_t* data)
{
assert(data != NULL);
uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U];
::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES);
bool ret = TDULC::decode(data, rs);
if (!ret)
return false;
ulong64_t rsValue = TDULC::toValue(rs);
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag
m_priority = (rs[2U] & 0x07U); // Priority
m_callTimer = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Call Timer
if (m_srcId == 0U) {
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source/Target Address
}
return true;
}
/// <summary>
/// Encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
void LC_TEL_INT_VCH_USER::encode(uint8_t* data)
{
assert(data != NULL);
ulong64_t rsValue = 0U;
m_implicit = true;
rsValue = m_mfId;
rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
(m_priority & 0x07U); // Priority
rsValue = (rsValue << 24) + m_dstId; // Target Radio Address
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get());
}

@ -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(__P25_LC_TSBK__LC_TEL_INT_VCH_USER_H__)
#define __P25_LC_TSBK__LC_TEL_INT_VCH_USER_H__
#include "Defines.h"
#include "p25/lc/TDULC.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements TEL INT VCH USER - Telephone Interconnect Voice Channel User
// ---------------------------------------------------------------------------
class HOST_SW_API LC_TEL_INT_VCH_USER : public TDULC {
public:
/// <summary>Initializes a new instance of the LC_TEL_INT_VCH_USER class.</summary>
LC_TEL_INT_VCH_USER();
/// <summary>Decode a terminator data unit w/ link control.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a terminator data unit w/ link control.</summary>
virtual void encode(uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__LC_TEL_INT_VCH_USER_H__

@ -0,0 +1,136 @@
/**
* 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 "p25/lc/tdulc/TDULCFactory.h"
#include "edac/Golay24128.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
#include <cassert>
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
::edac::RS634717 TDULCFactory::m_rs = ::edac::RS634717();
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the TDULCFactory class.
/// </summary>
TDULCFactory::TDULCFactory()
{
/* stub */
}
/// <summary>
/// Finalizes a instance of TDULCFactory class.
/// </summary>
TDULCFactory::~TDULCFactory()
{
/* stub */
}
/// <summary>
/// Create an instance of a TDULC.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
std::unique_ptr<TDULC> TDULCFactory::createTDULC(const uint8_t* data)
{
assert(data != nullptr);
// deinterleave
uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U];
uint8_t raw[P25_TDULC_FEC_LENGTH_BYTES + 1U];
P25Utils::decode(data, raw, 114U, 410U);
// decode Golay (24,12,8) FEC
edac::Golay24128::decode24128(rs, raw, P25_TDULC_LENGTH_BYTES);
#if DEBUG_P25_TDULC
Utils::dump(2U, "TDULCFactory::decode(), TDULC RS", rs, P25_TDULC_LENGTH_BYTES);
#endif
// decode RS (24,12,13) FEC
try {
bool ret = m_rs.decode241213(rs);
if (!ret) {
LogError(LOG_P25, "TDULCFactory::decode(), failed to decode RS (24,12,13) FEC");
return nullptr;
}
}
catch (...) {
Utils::dump(2U, "P25, RS excepted with input data", rs, P25_TDULC_LENGTH_BYTES);
return nullptr;
}
uint8_t lco = rs[0U] & 0x3FU; // LCO
// standard P25 reference opcodes
switch (lco) {
case p25::LC_GROUP:
return decode(new LC_GROUP(), data);
case p25::LC_PRIVATE:
return decode(new LC_PRIVATE(), data);
case p25::LC_TEL_INT_VCH_USER:
return decode(new LC_TEL_INT_VCH_USER(), data);
default:
LogError(LOG_P25, "TDULCFactory::create(), unknown TDULC LCO value, lco = $%02X", lco);
break;
}
return nullptr;
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="tdulc"></param>
/// <param name="data"></param>
/// <returns></returns>
std::unique_ptr<TDULC> TDULCFactory::decode(TDULC* tdulc, const uint8_t* data)
{
assert(tdulc != nullptr);
assert(data != nullptr);
if (!tdulc->decode(data)) {
return nullptr;
}
return std::unique_ptr<TDULC>(tdulc);
}

@ -0,0 +1,76 @@
/**
* 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(__P25_LC__TDULC_FACTORY_H__)
#define __P25_LC__TDULC_FACTORY_H__
#include "Defines.h"
#include "edac/RS634717.h"
#include "p25/lc/TDULC.h"
#include "p25/lc/tdulc/LC_ADJ_STS_BCAST.h"
#include "p25/lc/tdulc/LC_CALL_TERM.h"
#include "p25/lc/tdulc/LC_CONV_FALLBACK.h"
#include "p25/lc/tdulc/LC_GROUP_UPDT.h"
#include "p25/lc/tdulc/LC_GROUP.h"
#include "p25/lc/tdulc/LC_IDEN_UP.h"
#include "p25/lc/tdulc/LC_NET_STS_BCAST.h"
#include "p25/lc/tdulc/LC_PRIVATE.h"
#include "p25/lc/tdulc/LC_RFSS_STS_BCAST.h"
#include "p25/lc/tdulc/LC_SYS_SRV_BCAST.h"
#include "p25/lc/tdulc/LC_TEL_INT_VCH_USER.h"
namespace p25
{
namespace lc
{
namespace tdulc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Helper class to instantiate an instance of a TDULC.
// ---------------------------------------------------------------------------
class HOST_SW_API TDULCFactory {
public:
/// <summary>Initializes a new instance of the TDULCFactory class.</summary>
TDULCFactory();
/// <summary>Finalizes a instance of the TDULCFactory class.</summary>
~TDULCFactory();
/// <summary>Create an instance of a TDULC.</summary>
static std::unique_ptr<TDULC> createTDULC(const uint8_t* data);
private:
static edac::RS634717 m_rs;
/// <summary></summary>
static std::unique_ptr<TDULC> decode(TDULC* tdulc, const uint8_t* data);
};
} // namespace tdulc
} // namespace lc
} // namespace p25
#endif // __P25_LC__TDULC_FACTORY_H__

@ -30,6 +30,7 @@
#include "p25/packet/Trunk.h"
#include "p25/acl/AccessControl.h"
#include "p25/lc/tsbk/TSBKFactory.h"
#include "p25/lc/tdulc/TDULCFactory.h"
#include "p25/lookups/P25AffiliationLookup.h"
#include "p25/P25Utils.h"
#include "p25/Sync.h"
@ -1265,7 +1266,7 @@ void Trunk::writeNetworkRF(lc::TSBK* tsbk, const uint8_t* data, bool autoReset)
/// <param name="tduLc"></param>
/// <param name="data"></param>
/// <param name="autoReset"></param>
void Trunk::writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset)
void Trunk::writeNetworkRF(lc::TDULC* tduLc, const uint8_t* data, bool autoReset)
{
assert(data != nullptr);
@ -1276,10 +1277,10 @@ void Trunk::writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset
return;
lc::LC lc = lc::LC();
lc.setLCO(tduLc.getLCO());
lc.setMFId(tduLc.getMFId());
lc.setSrcId(tduLc.getSrcId());
lc.setDstId(tduLc.getDstId());
lc.setLCO(tduLc->getLCO());
lc.setMFId(tduLc->getMFId());
lc.setSrcId(tduLc->getSrcId());
lc.setDstId(tduLc->getDstId());
m_network->writeP25TSDU(lc, data);
if (autoReset)
@ -1301,11 +1302,10 @@ void Trunk::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS)
bool fallbackTx = (frameCnt % 253U) == 0U;
if (fallbackTx && n == 7U) {
if (m_convFallbackPacketDelay >= CONV_FALLBACK_PACKET_DELAY) {
lc::TDULC lc = lc::TDULC();
lc.setLCO(LC_CONV_FALLBACK);
std::unique_ptr<lc::tdulc::LC_CONV_FALLBACK> lc = new_unique(lc::tdulc::LC_CONV_FALLBACK);
for (uint8_t i = 0U; i < 3U; i++) {
writeRF_TDULC(lc, true);
writeRF_TDULC(lc.get(), true);
}
m_convFallbackPacketDelay = 0U;
@ -1434,7 +1434,7 @@ void Trunk::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS)
/// </summary>
/// <param name="lc"></param>
/// <param name="noNetwork"></param>
void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
void Trunk::writeRF_TDULC(lc::TDULC* lc, bool noNetwork)
{
uint8_t data[P25_TDULC_FRAME_LENGTH_BYTES + 2U];
::memset(data + 2U, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES);
@ -1446,7 +1446,7 @@ void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
m_p25->m_nid.encode(data + 2U, P25_DUID_TDULC);
// Generate TDULC Data
lc.encode(data + 2U);
lc->encode(data + 2U);
// Add busy bits
m_p25->addBusyBits(data + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true);
@ -1472,7 +1472,7 @@ void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
/// Helper to write a network P25 TDU w/ link control packet.
/// </summary>
/// <param name="lc"></param>
void Trunk::writeNet_TDULC(lc::TDULC lc)
void Trunk::writeNet_TDULC(lc::TDULC* lc)
{
uint8_t buffer[P25_TDULC_FRAME_LENGTH_BYTES + 2U];
::memset(buffer, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES + 2U);
@ -1487,7 +1487,7 @@ void Trunk::writeNet_TDULC(lc::TDULC lc)
m_p25->m_nid.encode(buffer + 2U, P25_DUID_TDULC);
// Regenerate TDULC Data
lc.encode(buffer + 2U);
lc->encode(buffer + 2U);
// Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true);
@ -1495,7 +1495,7 @@ void Trunk::writeNet_TDULC(lc::TDULC lc)
m_p25->addFrame(buffer, P25_TDULC_FRAME_LENGTH_BYTES + 2U, true);
if (m_verbose) {
LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc.getLCO(), lc.getSrcId());
LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc->getLCO(), lc->getSrcId());
}
if (m_p25->m_voice->m_netFrames > 0) {
@ -1528,38 +1528,37 @@ void Trunk::writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId)
}
uint32_t count = m_p25->m_hangCount / 2;
lc::TDULC lc = lc::TDULC();
std::unique_ptr<lc::TDULC> lc = nullptr;
if (m_p25->m_control) {
for (uint32_t i = 0; i < count; i++) {
if ((srcId != 0U) && (dstId != 0U)) {
lc.setSrcId(srcId);
lc.setDstId(dstId);
lc.setEmergency(false);
if (grp) {
lc.setLCO(LC_GROUP);
writeRF_TDULC(lc, true);
}
else {
lc.setLCO(LC_PRIVATE);
writeRF_TDULC(lc, true);
lc = new_unique(lc::tdulc::LC_GROUP);
} else {
lc = new_unique(lc::tdulc::LC_PRIVATE);
}
lc->setSrcId(srcId);
lc->setDstId(dstId);
lc->setEmergency(false);
writeRF_TDULC(lc.get(), true);
}
lc.setLCO(LC_NET_STS_BCAST);
writeRF_TDULC(lc, true);
lc.setLCO(LC_RFSS_STS_BCAST);
writeRF_TDULC(lc, true);
lc = new_unique(lc::tdulc::LC_NET_STS_BCAST);
writeRF_TDULC(lc.get(), true);
lc = new_unique(lc::tdulc::LC_RFSS_STS_BCAST);
writeRF_TDULC(lc.get(), true);
}
}
if (m_verbose) {
LogMessage(LOG_RF, P25_TDULC_STR ", LC_CALL_TERM (Call Termination), srcId = %u, dstId = %u", lc.getSrcId(), lc.getDstId());
LogMessage(LOG_RF, P25_TDULC_STR ", LC_CALL_TERM (Call Termination), srcId = %u, dstId = %u", srcId, dstId);
}
lc.setLCO(LC_CALL_TERM);
writeRF_TDULC(lc, true);
lc = new_unique(lc::tdulc::LC_CALL_TERM);
writeRF_TDULC(lc.get(), true);
if (m_p25->m_control) {
writeNet_TSDU_Call_Term(srcId, dstId);

@ -157,15 +157,15 @@ namespace p25
/// <summary>Write data processed from RF to the network.</summary>
void writeNetworkRF(lc::TSBK* tsbk, const uint8_t* data, bool autoReset);
/// <summary>Write data processed from RF to the network.</summary>
void writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset);
void writeNetworkRF(lc::TDULC* tduLc, const uint8_t* data, bool autoReset);
/// <summary>Helper to write control channel packet data.</summary>
void writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS);
/// <summary>Helper to write a P25 TDU w/ link control packet.</summary>
void writeRF_TDULC(lc::TDULC lc, bool noNetwork);
void writeRF_TDULC(lc::TDULC* lc, bool noNetwork);
/// <summary>Helper to write a network P25 TDU w/ link control packet.</summary>
virtual void writeNet_TDULC(lc::TDULC lc);
virtual void writeNet_TDULC(lc::TDULC* lc);
/// <summary>Helper to write a P25 TDU w/ link control channel release packet.</summary>
void writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId);

@ -34,6 +34,7 @@
#include "p25/packet/Trunk.h"
#include "p25/acl/AccessControl.h"
#include "p25/dfsi/DFSIDefines.h"
#include "p25/lc/tdulc/TDULCFactory.h"
#include "p25/P25Utils.h"
#include "p25/Sync.h"
#include "edac/CRC.h"
@ -640,13 +641,12 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_p25->m_rfTimeout.stop();
}
else {
lc::TDULC tdulc = lc::TDULC();
bool ret = tdulc.decode(data + 2U);
if (!ret) {
std::unique_ptr<lc::TDULC> tdulc = lc::tdulc::TDULCFactory::createTDULC(data + 2U);
if (tdulc == nullptr) {
LogWarning(LOG_RF, P25_LDU2_STR ", undecodable TDULC");
}
else {
m_p25->m_trunk->writeRF_TDULC(tdulc, false);
m_p25->m_trunk->writeRF_TDULC(tdulc.get(), false);
}
}

Loading…
Cancel
Save

Powered by TurnKey Linux.