cleanup and refactor how TSBK, TDULC, CSBK buffers are handled (optimization to buffer sizes); fix use of magic numbers in NXDN RCCH handlers;

3.56-maint
Bryan Biedenkapp 2 years ago
parent e4e677fa2b
commit d40960bba5

@ -109,7 +109,7 @@ typedef unsigned long long ulong64_t;
#define __PROG_NAME__ "Digital Voice Modem (DVM) Host"
#define __NET_NAME__ "DVM_DMR_P25"
#define __EXE_NAME__ "dvmhost"
#define __VER__ "D03.55.00 (" __GIT_VER__ ")"
#define __VER__ "D03.56.00 (" __GIT_VER__ ")"
#define __BUILD__ __DATE__ " " __TIME__
#define HOST_SW_API

@ -192,59 +192,62 @@ bool CSBK::regenerate(uint8_t* data, uint8_t dataType)
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to convert CSBK bytes to a 64-bit long value.
/// Internal helper to convert payload bytes to a 64-bit long value.
/// </summary>
/// <param name="tsbk"></param>
/// <param name="payload"></param>
/// <returns></returns>
ulong64_t CSBK::toValue(const uint8_t* csbk)
ulong64_t CSBK::toValue(const uint8_t* payload)
{
ulong64_t csbkValue = 0U;
ulong64_t value = 0U;
// combine bytes into ulong64_t (8 byte) value
csbkValue = csbk[2U];
csbkValue = (csbkValue << 8) + csbk[3U];
csbkValue = (csbkValue << 8) + csbk[4U];
csbkValue = (csbkValue << 8) + csbk[5U];
csbkValue = (csbkValue << 8) + csbk[6U];
csbkValue = (csbkValue << 8) + csbk[7U];
csbkValue = (csbkValue << 8) + csbk[8U];
csbkValue = (csbkValue << 8) + csbk[9U];
return csbkValue;
value = payload[0U];
value = (value << 8) + payload[1U];
value = (value << 8) + payload[2U];
value = (value << 8) + payload[3U];
value = (value << 8) + payload[4U];
value = (value << 8) + payload[5U];
value = (value << 8) + payload[6U];
value = (value << 8) + payload[7U];
return value;
}
/// <summary>
/// Internal helper to convert a 64-bit long value to CSBK bytes.
/// Internal helper to convert a 64-bit long value to payload bytes.
/// </summary>
/// <param name="csbkValue"></param>
/// <param name="value"></param>
/// <returns></returns>
UInt8Array CSBK::fromValue(const ulong64_t csbkValue)
UInt8Array CSBK::fromValue(const ulong64_t value)
{
__UNIQUE_UINT8_ARRAY(csbk, DMR_CSBK_LENGTH_BYTES);
__UNIQUE_UINT8_ARRAY(payload, DMR_CSBK_LENGTH_BYTES - 4U);
// split ulong64_t (8 byte) value into bytes
csbk[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
csbk[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
csbk[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
csbk[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
csbk[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
csbk[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
csbk[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
csbk[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
return csbk;
payload[0U] = (uint8_t)((value >> 56) & 0xFFU);
payload[1U] = (uint8_t)((value >> 48) & 0xFFU);
payload[2U] = (uint8_t)((value >> 40) & 0xFFU);
payload[3U] = (uint8_t)((value >> 32) & 0xFFU);
payload[4U] = (uint8_t)((value >> 24) & 0xFFU);
payload[5U] = (uint8_t)((value >> 16) & 0xFFU);
payload[6U] = (uint8_t)((value >> 8) & 0xFFU);
payload[7U] = (uint8_t)((value >> 0) & 0xFFU);
return payload;
}
/// <summary>
/// Internal helper to decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
/// <returns>True, if TSBK was decoded, otherwise false.</returns>
bool CSBK::decode(const uint8_t* data, uint8_t* csbk)
/// <param name="payload"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK::decode(const uint8_t* data, uint8_t* payload)
{
assert(data != nullptr);
assert(csbk != nullptr);
assert(payload != nullptr);
uint8_t csbk[DMR_CSBK_LENGTH_BYTES];
::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES);
// decode BPTC (196,96) FEC
edac::BPTC19696 bptc;
@ -291,6 +294,7 @@ bool CSBK::decode(const uint8_t* data, uint8_t* csbk)
m_dataContent = false;
m_CBF = 0U;
::memcpy(payload, csbk + 2U, DMR_CSBK_LENGTH_BYTES - 4U);
return true;
}
@ -298,58 +302,56 @@ bool CSBK::decode(const uint8_t* data, uint8_t* csbk)
/// Internal helper to encode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
/// <param name="rawTSBK"></param>
/// <param name="noTrellis"></param>
void CSBK::encode(uint8_t* data, const uint8_t* csbk)
/// <param name="payload"></param>
void CSBK::encode(uint8_t* data, const uint8_t* payload)
{
assert(data != nullptr);
assert(csbk != nullptr);
assert(payload != nullptr);
uint8_t outCsbk[DMR_CSBK_LENGTH_BYTES];
::memset(outCsbk, 0x00U, DMR_CSBK_LENGTH_BYTES);
::memcpy(outCsbk, csbk, DMR_CSBK_LENGTH_BYTES);
uint8_t csbk[DMR_CSBK_LENGTH_BYTES];
::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES);
::memcpy(csbk + 2U, payload, DMR_CSBK_LENGTH_BYTES - 4U);
outCsbk[0U] = m_CSBKO; // CSBKO
outCsbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
csbk[0U] = m_CSBKO; // CSBKO
csbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
if (!m_Cdef) {
outCsbk[1U] = m_FID; // Feature ID
csbk[1U] = m_FID; // Feature ID
}
else {
outCsbk[1U] = m_colorCode & 0x0FU; // Cdef uses Color Code
csbk[1U] = m_colorCode & 0x0FU; // Cdef uses Color Code
}
switch (m_dataType) {
case DT_CSBK:
outCsbk[10U] ^= CSBK_CRC_MASK[0U];
outCsbk[11U] ^= CSBK_CRC_MASK[1U];
csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U];
break;
case DT_MBC_HEADER:
outCsbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
outCsbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break;
}
edac::CRC::addCCITT162(outCsbk, 12U);
edac::CRC::addCCITT162(csbk, 12U);
switch (m_dataType) {
case DT_CSBK:
outCsbk[10U] ^= CSBK_CRC_MASK[0U];
outCsbk[11U] ^= CSBK_CRC_MASK[1U];
csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U];
break;
case DT_MBC_HEADER:
outCsbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
outCsbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break;
}
if (m_verbose) {
Utils::dump(2U, "Encoded CSBK", outCsbk, DMR_CSBK_LENGTH_BYTES);
Utils::dump(2U, "Encoded CSBK", csbk, DMR_CSBK_LENGTH_BYTES);
}
// encode BPTC (196,96) FEC
edac::BPTC19696 bptc;
bptc.encode(outCsbk, data);
bptc.encode(csbk, data);
}
/// <summary>

@ -149,15 +149,15 @@ namespace dmr
/** Local Site data */
static SiteData m_siteData;
/// <summary>Internal helper to convert CSBK bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const uint8_t* Csbk);
/// <summary>Internal helper to convert a 64-bit long value to CSBK bytes.</summary>
static UInt8Array fromValue(const ulong64_t csbkValue);
/// <summary>Internal helper to convert payload bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const uint8_t* payload);
/// <summary>Internal helper to convert a 64-bit long value to payload bytes.</summary>
static UInt8Array fromValue(const ulong64_t value);
/// <summary>Internal helper to decode a control signalling block.</summary>
bool decode(const uint8_t* data, uint8_t* csbk);
bool decode(const uint8_t* data, uint8_t* payload);
/// <summary>Internal helper to encode a control signalling block.</summary>
void encode(uint8_t* data, const uint8_t* csbk);
void encode(uint8_t* data, const uint8_t* payload);
__PROTECTED_COPY(CSBK);
};

@ -57,7 +57,7 @@ void MESSAGE_TYPE_DCALL_HDR::decode(const uint8_t* data, uint32_t length, uint32
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -81,7 +81,7 @@ void MESSAGE_TYPE_DCALL_HDR::encode(uint8_t* data, uint32_t length, uint32_t off
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag

@ -57,7 +57,7 @@ void MESSAGE_TYPE_DST_ID_INFO::decode(const uint8_t* data, uint32_t length, uint
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -73,7 +73,7 @@ void MESSAGE_TYPE_DST_ID_INFO::encode(uint8_t* data, uint32_t length, uint32_t o
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[1U] = 0xC0U + NXDN_CALLSIGN_LENGTH_BYTES; // Station ID Option - Start / End / Character Count

@ -57,7 +57,7 @@ void MESSAGE_TYPE_GRP_REG::decode(const uint8_t* data, uint32_t length, uint32_t
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -77,7 +77,7 @@ void MESSAGE_TYPE_GRP_REG::encode(uint8_t* data, uint32_t length, uint32_t offse
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[2U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address

@ -57,7 +57,7 @@ void MESSAGE_TYPE_IDLE::decode(const uint8_t* data, uint32_t length, uint32_t of
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -73,7 +73,7 @@ void MESSAGE_TYPE_IDLE::encode(uint8_t* data, uint32_t length, uint32_t offset)
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::encode(data, rcch, length, offset);

@ -57,7 +57,7 @@ void MESSAGE_TYPE_REG::decode(const uint8_t* data, uint32_t length, uint32_t off
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -80,7 +80,7 @@ void MESSAGE_TYPE_REG::encode(uint8_t* data, uint32_t length, uint32_t offset)
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...

@ -57,7 +57,7 @@ void MESSAGE_TYPE_REG_C::decode(const uint8_t* data, uint32_t length, uint32_t o
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -77,7 +77,7 @@ void MESSAGE_TYPE_REG_C::encode(uint8_t* data, uint32_t length, uint32_t offset)
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID

@ -57,7 +57,7 @@ void MESSAGE_TYPE_REG_COMM::decode(const uint8_t* data, uint32_t length, uint32_
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -73,7 +73,7 @@ void MESSAGE_TYPE_REG_COMM::encode(uint8_t* data, uint32_t length, uint32_t offs
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // Location ID

@ -62,7 +62,7 @@ void MESSAGE_TYPE_SITE_INFO::decode(const uint8_t* data, uint32_t length, uint32
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -78,7 +78,7 @@ void MESSAGE_TYPE_SITE_INFO::encode(uint8_t* data, uint32_t length, uint32_t off
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[1U] = (m_siteData.locId() >> 16) & 0xFFU; // Location ID

@ -57,7 +57,7 @@ void MESSAGE_TYPE_SRV_INFO::decode(const uint8_t* data, uint32_t length, uint32_
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -73,7 +73,7 @@ void MESSAGE_TYPE_SRV_INFO::encode(uint8_t* data, uint32_t length, uint32_t offs
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[1U] = (m_siteData.locId() >> 16) & 0xFFU; // Location ID

@ -57,7 +57,7 @@ void MESSAGE_TYPE_VCALL_ASSGN::decode(const uint8_t* data, uint32_t length, uint
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -73,7 +73,7 @@ void MESSAGE_TYPE_VCALL_ASSGN::encode(uint8_t* data, uint32_t length, uint32_t o
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag

@ -57,7 +57,7 @@ void MESSAGE_TYPE_VCALL_CONN::decode(const uint8_t* data, uint32_t length, uint3
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
RCCH::decode(data, rcch, length, offset);
@ -81,7 +81,7 @@ void MESSAGE_TYPE_VCALL_CONN::encode(uint8_t* data, uint32_t length, uint32_t of
{
assert(data != NULL);
uint8_t rcch[22U];
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag

@ -78,6 +78,7 @@ namespace p25
const uint32_t P25_TDULC_FEC_LENGTH_BYTES = 36U;
const uint32_t P25_TDULC_LENGTH_BYTES = 18U;
const uint32_t P25_TDULC_PAYLOAD_LENGTH_BYTES = 8U;
const uint32_t P25_TSBK_FEC_LENGTH_BYTES = 25U;
const uint32_t P25_TSBK_FEC_LENGTH_BITS = P25_TSBK_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits

@ -81,9 +81,10 @@ void AMBT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to convert TSBK bytes to a 64-bit long value.
/// Internal helper to convert AMBT bytes to a 64-bit long value.
/// </summary>
/// <param name="tsbk"></param>
/// <param name="dataHeader"></param>
/// <param name="pduUserData"></param>
/// <returns></returns>
ulong64_t AMBT::toValue(const data::DataHeader& dataHeader, const uint8_t* pduUserData)
{
@ -125,7 +126,7 @@ bool AMBT::decode(const data::DataHeader& dataHeader, const data::DataBlock* blo
}
m_lco = dataHeader.getAMBTOpcode(); // LCO
m_lastBlock = true;
m_lastBlock = true; // Last Block Marker
m_mfId = dataHeader.getMFId(); // Mfg Id.
if (dataHeader.getOutbound()) {
@ -159,7 +160,7 @@ void AMBT::encode(data::DataHeader& dataHeader, uint8_t* pduUserData)
assert(pduUserData != nullptr);
dataHeader.setFormat(PDU_FMT_AMBT);
dataHeader.setMFId(m_mfId);
dataHeader.setMFId(m_mfId); // Mfg Id.
dataHeader.setAckNeeded(false);
dataHeader.setOutbound(true);
dataHeader.setSAP(PDU_SAP_TRUNK_CTRL);
@ -170,7 +171,7 @@ void AMBT::encode(data::DataHeader& dataHeader, uint8_t* pduUserData)
dataHeader.setBlocksToFollow(1U);
}
dataHeader.setAMBTOpcode(m_lco);
dataHeader.setAMBTOpcode(m_lco); // LCO
// generate packet CRC-32 and set data blocks
if (dataHeader.getBlocksToFollow() > 1U) {

@ -56,7 +56,7 @@ namespace p25
void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
protected:
/// <summary>Internal helper to convert TSBK bytes to a 64-bit long value.</summary>
/// <summary>Internal helper to convert AMBT bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const data::DataHeader& dataHeader, const uint8_t* pduUserData);
/// <summary>Internal helper to decode a trunking signalling block.</summary>

@ -120,59 +120,64 @@ TDULC::~TDULC()
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to convert RS bytes to a 64-bit long value.
/// Internal helper to convert payload bytes to a 64-bit long value.
/// </summary>
/// <param name="tsbk"></param>
/// <returns></returns>
ulong64_t TDULC::toValue(const uint8_t* rs)
ulong64_t TDULC::toValue(const uint8_t* payload)
{
ulong64_t rsValue = 0U;
assert(payload != nullptr);
ulong64_t value = 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 rsValue;
value = payload[0U];
value = (value << 8) + payload[1U];
value = (value << 8) + payload[2U];
value = (value << 8) + payload[3U];
value = (value << 8) + payload[4U];
value = (value << 8) + payload[5U];
value = (value << 8) + payload[6U];
value = (value << 8) + payload[7U];
return value;
}
/// <summary>
/// Internal helper to convert a 64-bit long value to RS bytes.
/// Internal helper to convert a 64-bit long value to payload bytes.
/// </summary>
/// <param name="rsValue"></param>
/// <returns></returns>
UInt8Array TDULC::fromValue(const ulong64_t rsValue)
UInt8Array TDULC::fromValue(const ulong64_t value)
{
__UNIQUE_UINT8_ARRAY(rs, P25_TDULC_LENGTH_BYTES);
__UNIQUE_UINT8_ARRAY(payload, P25_TDULC_PAYLOAD_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;
payload[0U] = (uint8_t)((value >> 56) & 0xFFU);
payload[1U] = (uint8_t)((value >> 48) & 0xFFU);
payload[2U] = (uint8_t)((value >> 40) & 0xFFU);
payload[3U] = (uint8_t)((value >> 32) & 0xFFU);
payload[4U] = (uint8_t)((value >> 24) & 0xFFU);
payload[5U] = (uint8_t)((value >> 16) & 0xFFU);
payload[6U] = (uint8_t)((value >> 8) & 0xFFU);
payload[7U] = (uint8_t)((value >> 0) & 0xFFU);
return payload;
}
/// <summary>
/// Internal helper to decode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <param name="rs"></param>
/// <param name="payload"></param>
/// <returns>True, if TDULC was decoded, otherwise false.</returns>
bool TDULC::decode(const uint8_t* data, uint8_t* rs)
bool TDULC::decode(const uint8_t* data, uint8_t* payload)
{
assert(data != nullptr);
assert(rs != nullptr);
assert(payload != nullptr);
uint8_t rs[P25_TDULC_LENGTH_BYTES];
::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES);
// deinterleave
uint8_t raw[P25_TDULC_FEC_LENGTH_BYTES + 1U];
@ -202,6 +207,7 @@ bool TDULC::decode(const uint8_t* data, uint8_t* rs)
Utils::dump(2U, "TDULC::decode(), TDULC Value", rs, P25_TDULC_LENGTH_BYTES);
}
::memcpy(payload, rs + 1U, P25_TDULC_PAYLOAD_LENGTH_BYTES);
return true;
}
@ -209,36 +215,36 @@ bool TDULC::decode(const uint8_t* data, uint8_t* rs)
/// Internal helper to encode a terminator data unit w/ link control.
/// </summary>
/// <param name="data"></param>
/// <param name="rs"></param>
void TDULC::encode(uint8_t* data, const uint8_t* rs)
/// <param name="payload"></param>
void TDULC::encode(uint8_t* data, const uint8_t* payload)
{
assert(data != nullptr);
assert(rs != nullptr);
assert(payload != nullptr);
uint8_t outRs[P25_TDULC_LENGTH_BYTES];
::memset(outRs, 0x00U, P25_TDULC_LENGTH_BYTES);
::memcpy(outRs, rs, P25_TDULC_LENGTH_BYTES);
uint8_t rs[P25_TDULC_LENGTH_BYTES];
::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES);
::memcpy(rs + 1U, payload, P25_TDULC_PAYLOAD_LENGTH_BYTES);
outRs[0U] = m_lco; // LCO
rs[0U] = m_lco; // LCO
if (m_implicit)
outRs[0U] |= 0x40U; // Implicit Operation
rs[0U] |= 0x40U; // Implicit Operation
if (m_verbose) {
Utils::dump(2U, "TDULC::encode(), TDULC Value", outRs, P25_TDULC_LENGTH_BYTES);
Utils::dump(2U, "TDULC::encode(), TDULC Value", rs, P25_TDULC_LENGTH_BYTES);
}
// encode RS (24,12,13) FEC
m_rs.encode241213(outRs);
m_rs.encode241213(rs);
#if DEBUG_P25_TDULC
Utils::dump(2U, "TDULC::encode(), TDULC RS", outRs, P25_TDULC_LENGTH_BYTES);
Utils::dump(2U, "TDULC::encode(), TDULC RS", rs, 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, outRs, P25_TDULC_LENGTH_BYTES);
edac::Golay24128::encode24128(raw, rs, P25_TDULC_LENGTH_BYTES);
// interleave
P25Utils::encode(raw, data, 114U, 410U);

@ -121,15 +121,15 @@ namespace p25
/** Local Site data */
static SiteData m_siteData;
/// <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 UInt8Array fromValue(const ulong64_t rsValue);
/// <summary>Internal helper to convert payload bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const uint8_t* payload);
/// <summary>Internal helper to convert a 64-bit long value to payload bytes.</summary>
static UInt8Array fromValue(const ulong64_t value);
/// <summary>Internal helper to decode terminator data unit w/ link control.</summary>
bool decode(const uint8_t* data, uint8_t* rs);
bool decode(const uint8_t* data, uint8_t* payload);
/// <summary>Internal helper to encode terminator data unit w/ link control.</summary>
void encode(uint8_t* data, const uint8_t* rs);
void encode(uint8_t* data, const uint8_t* payload);
__PROTECTED_COPY(TDULC);
};

@ -47,7 +47,7 @@ bool TSBK::m_warnCRC = true;
bool TSBK::m_warnCRC = false;
#endif
uint8_t *TSBK::m_siteCallsign = nullptr;
uint8_t* TSBK::m_siteCallsign = nullptr;
SiteData TSBK::m_siteData = SiteData();
// ---------------------------------------------------------------------------
@ -163,62 +163,67 @@ void TSBK::setCallsign(std::string callsign)
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to convert TSBK bytes to a 64-bit long value.
/// Internal helper to convert payload bytes to a 64-bit long value.
/// </summary>
/// <param name="tsbk"></param>
/// <returns></returns>
ulong64_t TSBK::toValue(const uint8_t* tsbk)
ulong64_t TSBK::toValue(const uint8_t* payload)
{
ulong64_t tsbkValue = 0U;
assert(payload != nullptr);
ulong64_t value = 0U;
// combine bytes into ulong64_t (8 byte) value
tsbkValue = tsbk[2U];
tsbkValue = (tsbkValue << 8) + tsbk[3U];
tsbkValue = (tsbkValue << 8) + tsbk[4U];
tsbkValue = (tsbkValue << 8) + tsbk[5U];
tsbkValue = (tsbkValue << 8) + tsbk[6U];
tsbkValue = (tsbkValue << 8) + tsbk[7U];
tsbkValue = (tsbkValue << 8) + tsbk[8U];
tsbkValue = (tsbkValue << 8) + tsbk[9U];
return tsbkValue;
value = payload[0U];
value = (value << 8) + payload[1U];
value = (value << 8) + payload[2U];
value = (value << 8) + payload[3U];
value = (value << 8) + payload[4U];
value = (value << 8) + payload[5U];
value = (value << 8) + payload[6U];
value = (value << 8) + payload[7U];
return value;
}
/// <summary>
/// Internal helper to convert a 64-bit long value to TSBK bytes.
/// Internal helper to convert a 64-bit long value to payload bytes.
/// </summary>
/// <param name="tsbkValue"></param>
/// <param name="value"></param>
/// <returns></returns>
UInt8Array TSBK::fromValue(const ulong64_t tsbkValue)
UInt8Array TSBK::fromValue(const ulong64_t value)
{
__UNIQUE_UINT8_ARRAY(tsbk, P25_TSBK_LENGTH_BYTES);
__UNIQUE_UINT8_ARRAY(payload, P25_TSBK_LENGTH_BYTES - 4U);
// split ulong64_t (8 byte) value into bytes
tsbk[2U] = (uint8_t)((tsbkValue >> 56) & 0xFFU);
tsbk[3U] = (uint8_t)((tsbkValue >> 48) & 0xFFU);
tsbk[4U] = (uint8_t)((tsbkValue >> 40) & 0xFFU);
tsbk[5U] = (uint8_t)((tsbkValue >> 32) & 0xFFU);
tsbk[6U] = (uint8_t)((tsbkValue >> 24) & 0xFFU);
tsbk[7U] = (uint8_t)((tsbkValue >> 16) & 0xFFU);
tsbk[8U] = (uint8_t)((tsbkValue >> 8) & 0xFFU);
tsbk[9U] = (uint8_t)((tsbkValue >> 0) & 0xFFU);
return tsbk;
payload[0U] = (uint8_t)((value >> 56) & 0xFFU);
payload[1U] = (uint8_t)((value >> 48) & 0xFFU);
payload[2U] = (uint8_t)((value >> 40) & 0xFFU);
payload[3U] = (uint8_t)((value >> 32) & 0xFFU);
payload[4U] = (uint8_t)((value >> 24) & 0xFFU);
payload[5U] = (uint8_t)((value >> 16) & 0xFFU);
payload[6U] = (uint8_t)((value >> 8) & 0xFFU);
payload[7U] = (uint8_t)((value >> 0) & 0xFFU);
return payload;
}
/// <summary>
/// Internal helper to decode a trunking signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
/// <param name="payload"></param>
/// <param name="rawTSBK"></param>
/// <returns>True, if TSBK was decoded, otherwise false.</returns>
bool TSBK::decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK)
bool TSBK::decode(const uint8_t* data, uint8_t* payload, bool rawTSBK)
{
assert(data != nullptr);
assert(tsbk != nullptr);
assert(payload != nullptr);
if (rawTSBK) {
uint8_t tsbk[P25_TSBK_LENGTH_BYTES];
::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
if (rawTSBK)
{
::memcpy(tsbk, data, P25_TSBK_LENGTH_BYTES);
bool ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES);
@ -274,6 +279,7 @@ bool TSBK::decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK)
m_lastBlock = (tsbk[0U] & 0x80U) == 0x80U; // Last Block Marker
m_mfId = tsbk[1U]; // Mfg Id.
::memcpy(payload, tsbk + 2U, P25_TSBK_LENGTH_BYTES - 4U);
return true;
}
@ -281,40 +287,39 @@ bool TSBK::decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK)
/// Internal helper to eecode a trunking signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
/// <param name="payload"></param>
/// <param name="rawTSBK"></param>
/// <param name="noTrellis"></param>
void TSBK::encode(uint8_t* data, const uint8_t* tsbk, bool rawTSBK, bool noTrellis)
void TSBK::encode(uint8_t* data, const uint8_t* payload, bool rawTSBK, bool noTrellis)
{
assert(data != nullptr);
assert(tsbk != nullptr);
uint8_t outTsbk[P25_TSBK_LENGTH_BYTES];
::memset(outTsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
::memcpy(outTsbk, tsbk, P25_TSBK_LENGTH_BYTES);
assert(payload != nullptr);
outTsbk[0U] = m_lco; // LCO
outTsbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
uint8_t tsbk[P25_TSBK_LENGTH_BYTES];
::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
::memcpy(tsbk + 2U, payload, P25_TSBK_LENGTH_BYTES - 4U);
outTsbk[1U] = m_mfId;
tsbk[0U] = m_lco; // LCO
tsbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
tsbk[1U] = m_mfId; // Mfg Id.
// compute CRC-CCITT 16
edac::CRC::addCCITT162(outTsbk, P25_TSBK_LENGTH_BYTES);
edac::CRC::addCCITT162(tsbk, P25_TSBK_LENGTH_BYTES);
if (m_verbose) {
Utils::dump(2U, "TSBK::encode(), TSBK Value", outTsbk, P25_TSBK_LENGTH_BYTES);
Utils::dump(2U, "TSBK::encode(), TSBK Value", tsbk, P25_TSBK_LENGTH_BYTES);
}
uint8_t raw[P25_TSBK_FEC_LENGTH_BYTES];
::memset(raw, 0x00U, P25_TSBK_FEC_LENGTH_BYTES);
// encode 1/2 rate Trellis
m_trellis.encode12(outTsbk, raw);
m_trellis.encode12(tsbk, raw);
// are we encoding a raw TSBK?
if (rawTSBK) {
if (noTrellis) {
::memcpy(data, outTsbk, P25_TSBK_LENGTH_BYTES);
::memcpy(data, tsbk, P25_TSBK_LENGTH_BYTES);
}
else {
::memcpy(data, raw, P25_TSBK_FEC_LENGTH_BYTES);

@ -160,15 +160,15 @@ namespace p25
static uint8_t* m_siteCallsign;
static SiteData m_siteData;
/// <summary>Internal helper to convert TSBK bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const uint8_t* tsbk);
/// <summary>Internal helper to convert a 64-bit long value to TSBK bytes.</summary>
static UInt8Array fromValue(const ulong64_t tsbkValue);
/// <summary>Internal helper to convert payload bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const uint8_t* payload);
/// <summary>Internal helper to convert a 64-bit long value to payload bytes.</summary>
static UInt8Array fromValue(const ulong64_t value);
/// <summary>Internal helper to decode a trunking signalling block.</summary>
bool decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK = false);
bool decode(const uint8_t* data, uint8_t* payload, bool rawTSBK = false);
/// <summary>Internal helper to encode a trunking signalling block.</summary>
void encode(uint8_t* data, const uint8_t* tsbk, bool rawTSBK = false, bool noTrellis = false);
void encode(uint8_t* data, const uint8_t* payload, bool rawTSBK = false, bool noTrellis = false);
__PROTECTED_COPY(TSBK);
};

Loading…
Cancel
Save

Powered by TurnKey Linux.