refactor CSBK handling; cleanup argument names for some function calls; cleanup some misleading commenting with more descriptive comments;

2.0-maint
Bryan Biedenkapp 3 years ago
parent d853175f93
commit 051fa78ba4

@ -69,6 +69,7 @@ namespace dmr
const uint32_t DMR_AMBE_LENGTH_BYTES = 27U; const uint32_t DMR_AMBE_LENGTH_BYTES = 27U;
const uint32_t DMR_LC_HEADER_LENGTH_BYTES = 12U; const uint32_t DMR_LC_HEADER_LENGTH_BYTES = 12U;
const uint32_t DMR_CSBK_LENGTH_BYTES = 12U;
const uint8_t BS_SOURCED_AUDIO_SYNC[] = { 0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U }; const uint8_t BS_SOURCED_AUDIO_SYNC[] = { 0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U };
const uint8_t BS_SOURCED_DATA_SYNC[] = { 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U }; const uint8_t BS_SOURCED_DATA_SYNC[] = { 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U };
@ -212,6 +213,30 @@ namespace dmr
const uint8_t SLCO_ACT = 0x01U; const uint8_t SLCO_ACT = 0x01U;
const uint8_t SLCO_TSCC = 0x02U; const uint8_t SLCO_TSCC = 0x02U;
// Reason Code(s)
const uint8_t TS_ACK_RSN_MSG = 0x60U; // TS - Message Accepted
const uint8_t TS_ACK_RSN_REG = 0x62U; // TS - Registration Accepted
const uint8_t TS_ACK_RSN_AUTH_RESP = 0x64U; // TS - Authentication Challenge Response
const uint8_t TS_ACK_RSN_REG_SUB_ATTACH = 0x65U; // TS - Registration Response with subscription
const uint8_t MS_ACK_RSN_MSG = 0x44U; // MS - Message Accepted
const uint8_t MS_ACK_RSN_AUTH_RESP = 0x48U; // MS - Authentication Challenge Response
const uint8_t TS_DENY_RSN_SYS_UNSUPPORTED_SVC = 0x20U;
const uint8_t TS_DENY_RSN_PERM_USER_REFUSED = 0x21U;
const uint8_t TS_DENY_RSN_TEMP_USER_REFUSED = 0x22U;
const uint8_t TS_DENY_RSN_TRSN_SYS_REFUSED = 0x23U;
const uint8_t TS_DENY_RSN_TGT_NOT_REG = 0x24U;
const uint8_t TS_DENY_RSN_TGT_UNAVAILABLE = 0x25U;
const uint8_t TS_DENY_RSN_SYS_BUSY = 0x27U;
const uint8_t TS_DENY_RSN_SYS_NOT_READY = 0x28U;
const uint8_t TS_DENY_RSN_CALL_CNCL_REFUSED = 0x29U;
const uint8_t TS_DENY_RSN_REG_REFUSED = 0x2AU;
const uint8_t TS_DENY_RSN_REG_DENIED = 0x2BU;
const uint8_t TS_DENY_RSN_MS_NOT_REG = 0x2DU;
const uint8_t TS_DENY_RSN_TGT_GROUP_NOT_VALID = 0x2FU;
const uint8_t MS_DENY_RSN_UNSUPPORTED_SVC = 0x00U;
// Broadcast Announcement Type(s) // Broadcast Announcement Type(s)
const uint8_t BCAST_ANNC_ANN_WD_TSCC = 0x00U; // Announce-WD TSCC Channel const uint8_t BCAST_ANNC_ANN_WD_TSCC = 0x00U; // Announce-WD TSCC Channel
const uint8_t BCAST_ANNC_CALL_TIMER_PARMS = 0x01U; // Specify Call Timer Parameters const uint8_t BCAST_ANNC_CALL_TIMER_PARMS = 0x01U; // Specify Call Timer Parameters
@ -238,7 +263,6 @@ namespace dmr
const uint8_t CSBKO_CTCSBK = 0x07U; // CT CSBK - Channel Timing CSBK const uint8_t CSBKO_CTCSBK = 0x07U; // CT CSBK - Channel Timing CSBK
const uint8_t CSBKO_ALOHA = 0x19U; // ALOHA - Aloha PDUs for the random access protocol const uint8_t CSBKO_ALOHA = 0x19U; // ALOHA - Aloha PDUs for the random access protocol
const uint8_t CSBKO_RAND = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert const uint8_t CSBKO_RAND = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert
const uint8_t CSBKO_CALL_ALRT = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert
const uint8_t CSBKO_ACK_RSP = 0x20U; // ACK RSP - Acknowledge Response const uint8_t CSBKO_ACK_RSP = 0x20U; // ACK RSP - Acknowledge Response
const uint8_t CSBKO_EXT_FNCT = 0x24U; // (DMRA) EXT FNCT - Extended Function const uint8_t CSBKO_EXT_FNCT = 0x24U; // (DMRA) EXT FNCT - Extended Function
const uint8_t CSBKO_NACK_RSP = 0x26U; // NACK RSP - Negative Acknowledgement Response const uint8_t CSBKO_NACK_RSP = 0x26U; // NACK RSP - Negative Acknowledgement Response

@ -131,15 +131,15 @@ DataHeader& DataHeader::operator=(const DataHeader& header)
/// <summary> /// <summary>
/// Decodes a DMR data header. /// Decodes a DMR data header.
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
/// <returns>True, if DMR data header was decoded, otherwise false.</returns> /// <returns>True, if DMR data header was decoded, otherwise false.</returns>
bool DataHeader::decode(const uint8_t* bytes) bool DataHeader::decode(const uint8_t* data)
{ {
assert(bytes != NULL); assert(data != NULL);
// decode BPTC (196,96) FEC // decode BPTC (196,96) FEC
edac::BPTC19696 bptc; edac::BPTC19696 bptc;
bptc.decode(bytes, m_data); bptc.decode(data, m_data);
// make sure the CRC-CCITT 16 was actually included (the network tends to zero the CRC) // make sure the CRC-CCITT 16 was actually included (the network tends to zero the CRC)
if (m_data[10U] != 0x00U && m_data[11U] != 0x00U) { if (m_data[10U] != 0x00U && m_data[11U] != 0x00U) {
@ -250,10 +250,10 @@ bool DataHeader::decode(const uint8_t* bytes)
/// <summary> /// <summary>
/// Encodes a DMR data header. /// Encodes a DMR data header.
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
void DataHeader::encode(uint8_t* bytes) const void DataHeader::encode(uint8_t* data) const
{ {
assert(bytes != NULL); assert(data != NULL);
// perform no processing other then regenerating FEC // perform no processing other then regenerating FEC
if (m_DPF == DPF_PROPRIETARY) { if (m_DPF == DPF_PROPRIETARY) {
@ -271,7 +271,7 @@ void DataHeader::encode(uint8_t* bytes) const
// encode BPTC (196,96) FEC // encode BPTC (196,96) FEC
edac::BPTC19696 bptc; edac::BPTC19696 bptc;
bptc.encode(m_data, bytes); bptc.encode(m_data, data);
return; return;
} }
else { else {
@ -383,5 +383,5 @@ void DataHeader::encode(uint8_t* bytes) const
// encode BPTC (196,96) FEC // encode BPTC (196,96) FEC
edac::BPTC19696 bptc; edac::BPTC19696 bptc;
bptc.encode(m_data, bytes); bptc.encode(m_data, data);
} }

@ -53,9 +53,9 @@ namespace dmr
DataHeader& operator=(const DataHeader& header); DataHeader& operator=(const DataHeader& header);
/// <summary>Decodes a DMR data header.</summary> /// <summary>Decodes a DMR data header.</summary>
bool decode(const uint8_t* bytes); bool decode(const uint8_t* data);
/// <summary>Encodes a DMR data header.</summary> /// <summary>Encodes a DMR data header.</summary>
void encode(uint8_t* bytes) const; void encode(uint8_t* data) const;
public: public:
/// <summary>Flag indicating whether the CSBK is group or individual.</summary> /// <summary>Flag indicating whether the CSBK is group or individual.</summary>

@ -73,128 +73,125 @@ CSBK::CSBK(SiteData siteData, lookups::IdenTable entry, bool verbose) : CSBK(sit
/// </summary> /// </summary>
CSBK::~CSBK() CSBK::~CSBK()
{ {
delete[] m_data; /* stub */
} }
/// <summary> /// <summary>
/// Decodes a DMR CSBK. /// Decodes a DMR CSBK.
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
/// <returns>True, if DMR CSBK was decoded, otherwise false.</returns> /// <returns>True, if DMR CSBK was decoded, otherwise false.</returns>
bool CSBK::decode(const uint8_t* bytes) bool CSBK::decode(const uint8_t* data)
{ {
assert(bytes != NULL); assert(data != NULL);
uint8_t csbk[DMR_CSBK_LENGTH_BYTES];
// decode BPTC (196,96) FEC // decode BPTC (196,96) FEC
edac::BPTC19696 bptc; edac::BPTC19696 bptc;
bptc.decode(bytes, m_data); bptc.decode(data, csbk);
// validate the CRC-CCITT 16 // validate the CRC-CCITT 16
m_data[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
m_data[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
bool valid = edac::CRC::checkCCITT162(m_data, DMR_LC_HEADER_LENGTH_BYTES); bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES);
if (!valid) { if (!valid) {
LogError(LOG_DMR, "CSBK::decode(), failed CRC CCITT-162 check"); LogError(LOG_DMR, "CSBK::decode(), failed CRC CCITT-162 check");
return false; return false;
} }
// restore the checksum // restore the checksum
m_data[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
m_data[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
if (m_verbose) { if (m_verbose) {
Utils::dump(2U, "Decoded CSBK", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(2U, "Decoded CSBK", csbk, DMR_CSBK_LENGTH_BYTES);
} }
m_CSBKO = m_data[0U] & 0x3FU; // CSBKO m_CSBKO = csbk[0U] & 0x3FU; // CSBKO
m_lastBlock = (m_data[0U] & 0x80U) == 0x80U; // Last Block Marker m_lastBlock = (csbk[0U] & 0x80U) == 0x80U; // Last Block Marker
m_FID = m_data[1U]; // Feature ID m_FID = csbk[1U]; // Feature ID
m_dataContent = false;
m_CBF = 0U;
ulong64_t csbkValue = 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];
switch (m_CSBKO) { switch (m_CSBKO) {
case CSBKO_BSDWNACT: case CSBKO_BSDWNACT:
m_GI = false; m_bsId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Base Station Address
m_bsId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Base Station ID m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = false;
m_CBF = 0U;
break; break;
case CSBKO_UU_V_REQ: case CSBKO_UU_V_REQ:
m_GI = false; m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = false;
m_CBF = 0U;
break; break;
case CSBKO_UU_ANS_RSP: case CSBKO_UU_ANS_RSP:
m_GI = false; m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = false;
m_CBF = 0U;
break; break;
case CSBKO_PRECCSBK: case CSBKO_PRECCSBK:
m_GI = (m_data[2U] & 0x40U) == 0x40U; m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; //
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID m_CBF = (uint8_t)((csbkValue >> 48) & 0xFFU); // Blocks to Follow
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_CBF = m_data[3U]; m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
break; break;
case CSBKO_RAND: // CSBKO_CALL_ALRT when FID == FID_DMRA case CSBKO_RAND: // CSBKO_CALL_ALRT when FID == FID_DMRA
switch (m_FID) switch (m_FID)
{ {
case FID_DMRA: case FID_DMRA:
m_GI = (m_data[2U] & 0x40U) == 0x40U; // Group or Individual m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; //
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID m_CBF = (uint8_t)((csbkValue >> 48) & 0xFFU); // Blocks to Follow
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; // m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_CBF = m_data[3U]; // m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
break; break;
/* Tier III */
case FID_ETSI: case FID_ETSI:
default: default:
m_serviceOptions = m_data[2U]; // Service Options m_emergency = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
m_targetAddress = (m_data[3U] >> 6 & 0x03U); // Target Address m_privacy = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Privacy Flag
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID m_supplementData = (((csbkValue >> 56) & 0xFFU) & 0x20U) == 0x20U; // Supplementary Data Flag
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID m_broadcast = (((csbkValue >> 56) & 0xFFU) & 0x10U) == 0x10U; // Broadcast Flag
m_priority = (((csbkValue >> 56) & 0xFFU) & 0x03U); // Priority
m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
break; break;
} }
case CSBKO_ACK_RSP:
m_GI = (m_data[2U] & 0x40U) == 0x40U;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_response = m_data[3U]; // Response
m_dataContent = false;
break;
case CSBKO_EXT_FNCT: case CSBKO_EXT_FNCT:
m_GI = false; m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; //
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID m_CBF = (uint8_t)((csbkValue >> 48) & 0xFFU); // Blocks to Follow
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; // m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
m_CBF = m_data[3U]; //
break; break;
case CSBKO_NACK_RSP: case CSBKO_NACK_RSP:
m_GI = false; m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag
m_srcId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Source ID m_serviceType = (((csbkValue >> 56) & 0xFFU) & 0x3FU); // Service Type
m_dstId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Destination ID m_reason = (uint8_t)((csbkValue >> 48) & 0xFFU); // Reason Code
m_response = m_data[3U]; // Response m_srcId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Source Radio Address
m_dataContent = false; m_dstId = (uint32_t)(csbkValue & 0xFFFFFFU); // Target Radio Address
break;
/** Tier 3 */
case CSBKO_ACK_RSP:
m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag
m_reason = (uint8_t)((csbkValue >> 33) & 0xFFU); // Reason Code
m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address
m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address
break; break;
default: default:
m_GI = false;
m_srcId = 0U;
m_dstId = 0U;
m_dataContent = false;
m_CBF = 0U;
LogError(LOG_DMR, "CSBK::decode(), unknown CSBK type, csbko = $%02X", m_CSBKO); LogError(LOG_DMR, "CSBK::decode(), unknown CSBK type, csbko = $%02X", m_CSBKO);
return true; return true;
} }
@ -205,261 +202,182 @@ bool CSBK::decode(const uint8_t* bytes)
/// <summary> /// <summary>
/// Encodes a DMR CSBK. /// Encodes a DMR CSBK.
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
void CSBK::encode(uint8_t* bytes) void CSBK::encode(uint8_t* data)
{ {
assert(bytes != NULL); assert(data != NULL);
m_data[0U] = m_CSBKO; // CSBKO uint8_t csbk[DMR_CSBK_LENGTH_BYTES];
m_data[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES);
ulong64_t csbkValue = 0U;
csbk[0U] = m_CSBKO; // CSBKO
csbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
if (!m_Cdef) { if (!m_Cdef) {
m_data[1U] = m_FID; // Feature ID csbk[1U] = m_FID; // Feature ID
} }
else { else {
m_data[1U] = m_colorCode & 0x0FU; // Cdef uses Color Code csbk[1U] = m_colorCode & 0x0FU; // Cdef uses Color Code
} }
switch (m_CSBKO) { switch (m_CSBKO) {
case CSBKO_ACK_RSP:
m_data[2U] = (uint8_t)(m_serviceType & 0x3FU); // Service Type
m_data[2U] |= 0x80U; // Additional Information Field (always 1)
if (m_GI) {
m_data[2U] |= 0x40U; // Source Type
}
m_data[3U] = m_response; // Reason Code
m_data[4U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[5U] = (m_srcId >> 8) & 0xFFU;
m_data[6U] = (m_srcId >> 0) & 0xFFU;
m_data[7U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[8U] = (m_dstId >> 8) & 0xFFU;
m_data[9U] = (m_dstId >> 0) & 0xFFU;
break;
case CSBKO_EXT_FNCT: case CSBKO_EXT_FNCT:
if (m_GI) { csbkValue =
m_data[2U] |= 0x40U; // Group or Individual (m_GI ? 0x40U : 0x00U) + // Group or Invididual
} (m_dataContent ? 0x80U : 0x00U);
csbkValue = (csbkValue << 8) + m_CBF; // Blocks to Follow
if (m_dataContent) { csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
m_data[2U] |= 0x80U; // csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address
}
m_data[3U] = m_CBF; //
m_data[4U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[5U] = (m_srcId >> 8) & 0xFFU;
m_data[6U] = (m_srcId >> 0) & 0xFFU;
m_data[7U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[8U] = (m_dstId >> 8) & 0xFFU;
m_data[9U] = (m_dstId >> 0) & 0xFFU;
break; break;
case CSBKO_NACK_RSP: case CSBKO_NACK_RSP:
m_data[2U] = (uint8_t)(m_serviceType & 0x3FU); // Service Type csbkValue = 0x80U + // Additional Information Field (always 1)
m_data[2U] |= 0x80U; // Additional Information Field (always 1) (m_GI ? 0x40U : 0x00U) + // Source Type
if (m_GI) { (m_serviceType & 0x3FU); // Service Type
m_data[2U] |= 0x40U; // Source Type csbkValue = (csbkValue << 8) + m_reason; // Reason Code
} csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
m_data[3U] = m_response; // Reason Code csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address
m_data[4U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[5U] = (m_srcId >> 8) & 0xFFU;
m_data[6U] = (m_srcId >> 0) & 0xFFU;
m_data[7U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[8U] = (m_dstId >> 8) & 0xFFU;
m_data[9U] = (m_dstId >> 0) & 0xFFU;
break; break;
/* Tier III */ /* Tier III */
case CSBKO_ALOHA: case CSBKO_ACK_RSP:
{ if (m_reason == TS_ACK_RSN_REG) {
ulong64_t csbkValue = 0U; csbkValue = 0U;
csbkValue = (csbkValue << 2) + 0U; // Reserved } else {
csbkValue = (csbkValue << 1) + ((m_siteTSSync) ? 1U : 0U); // Site Time Slot Synchronization csbkValue = (m_GI ? 0x40U : 0x00U) + // Source Type
csbkValue = (csbkValue << 3) + DMR_ALOHA_VER_151; // DMR Spec. Version (1.5.1) (m_siteData.siteId() & 0x3FU); // Net + Site LSB
csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset
csbkValue = (csbkValue << 1) + ((m_siteData.netActive()) ? 1U : 0U); // Site Networked
csbkValue = (csbkValue << 5) + (m_alohaMask & 0x1FU); // MS Mask
csbkValue = (csbkValue << 2) + 0U; // Service Function
csbkValue = (csbkValue << 4) + 0U; //
csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration
csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number
csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity
csbkValue = (csbkValue << 24) + m_srcId; // Source ID
// split value into bytes
m_data[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
m_data[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
m_data[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
m_data[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
m_data[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
m_data[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
m_data[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
m_data[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
} }
csbkValue = (csbkValue << 7) + (m_reason & 0xFFU); // Reason Code
csbkValue = (csbkValue << 25) + m_dstId; // Target Radio Address
csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
break;
case CSBKO_ALOHA:
csbkValue = 0U;
csbkValue = (csbkValue << 2) + 0U; // Reserved
csbkValue = (csbkValue << 1) + ((m_siteTSSync) ? 1U : 0U); // Site Time Slot Synchronization
csbkValue = (csbkValue << 3) + DMR_ALOHA_VER_151; // DMR Spec. Version (1.5.1)
csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset
csbkValue = (csbkValue << 1) + ((m_siteData.netActive()) ? 1U : 0U); // Site Networked
csbkValue = (csbkValue << 5) + (m_alohaMask & 0x1FU); // MS Mask
csbkValue = (csbkValue << 2) + 0U; // Service Function
csbkValue = (csbkValue << 4) + 0U; //
csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration
csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number
csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity
csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
break; break;
case CSBKO_PV_GRANT: case CSBKO_PV_GRANT:
{ csbkValue = 0U;
ulong64_t csbkValue = 0U; csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number
csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number csbkValue = (csbkValue << 1) + 0U; // Reserved
csbkValue = (csbkValue << 1) + 0U; // Reserved csbkValue = (csbkValue << 1) + 0U; // Emergency
csbkValue = (csbkValue << 1) + 0U; // Emergency csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset
csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID
csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
csbkValue = (csbkValue << 24) + m_srcId; // Source ID
// split value into bytes
m_data[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
m_data[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
m_data[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
m_data[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
m_data[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
m_data[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
m_data[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
m_data[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
}
break; break;
case CSBKO_TV_GRANT: case CSBKO_TV_GRANT:
case CSBKO_BTV_GRANT: case CSBKO_BTV_GRANT:
{ csbkValue = 0U;
ulong64_t csbkValue = 0U; csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number
csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number csbkValue = (csbkValue << 1) + 0U; // Late Entry
csbkValue = (csbkValue << 1) + 0U; // Late Entry csbkValue = (csbkValue << 1) + 0U; // Emergency
csbkValue = (csbkValue << 1) + 0U; // Emergency csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset
csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID
csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
csbkValue = (csbkValue << 24) + m_srcId; // Source ID
// split value into bytes
m_data[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
m_data[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
m_data[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
m_data[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
m_data[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
m_data[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
m_data[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
m_data[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
}
break; break;
case CSBKO_BROADCAST: case CSBKO_BROADCAST:
{ {
ulong64_t csbkValue = 0U; csbkValue = 0U;
if (!m_Cdef) { if (!m_Cdef) {
csbkValue = m_anncType; // Announcement Type csbkValue = m_anncType; // Announcement Type
}
switch (m_anncType)
{
case BCAST_ANNC_ANN_WD_TSCC:
{
// Broadcast Parms 1
csbkValue = (csbkValue << 4) + 0U; // Reserved
csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 1
csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 2
csbkValue = (csbkValue << 1) + ((m_annWdCh1) ? 1U : 0U); // Announce/Withdraw Channel 1
csbkValue = (csbkValue << 1) + ((m_annWdCh2) ? 1U : 0U); // Announce/Withdraw Channel 2
csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration
csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number
csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity
// Broadcast Parms 2
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel 1
csbkValue = (csbkValue << 12) + (m_logicalCh2 & 0xFFFU); // Logical Channel 2
}
break;
case BCAST_ANNC_CHAN_FREQ:
{
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
const uint32_t multiple = 100000;
// calculate Rx frequency
uint32_t rxFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1)) + calcTxOffset);
// generate frequency in mhz
uint32_t rxFreqMhz = rxFrequency + multiple / 2;
rxFreqMhz -= rxFreqMhz % multiple;
rxFreqMhz /= multiple * 10;
// generate khz offset
uint32_t rxFreqKhz = rxFrequency - (rxFreqMhz * 1000000);
// calculate Tx Frequency
uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1)));
// generate frequency in mhz
uint32_t txFreqMhz = txFrequency + multiple / 2;
txFreqMhz -= txFreqMhz % multiple;
txFreqMhz /= multiple * 10;
// generate khz offset
uint32_t txFreqKhz = txFrequency - (txFreqMhz * 1000000);
csbkValue = 0U; // Cdef Type (always 0 for ANN_WD_TSCC)
csbkValue = (csbkValue << 2) + 0U; // Reserved
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel
csbkValue = (csbkValue << 10) + (txFreqMhz & 0x7FFU); // Transmit Freq Mhz
csbkValue = (csbkValue << 13) + (txFreqKhz & 0x3FFFU); // Transmit Freq Offset Khz
csbkValue = (csbkValue << 10) + (rxFreqMhz & 0x7FFU); // Receive Freq Mhz
csbkValue = (csbkValue << 13) + (rxFreqKhz & 0x3FFFU); // Receive Freq Khz
}
break;
case BCAST_ANNC_SITE_PARMS:
{
// Broadcast Parms 1
csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Parms 1)
csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration
csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number
csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity
// Broadcast Parms 2
csbkValue = (csbkValue << 1) + 0U; // Roaming TG Subscription/Attach
csbkValue = (csbkValue << 1) + ((m_hibernating) ? 1U : 0U); // TSCC Hibernating
csbkValue = (csbkValue << 22) + 0U; // Broadcast Parms 2 (Reserved)
}
}
// split value into bytes
m_data[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
m_data[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
m_data[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
m_data[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
m_data[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
m_data[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
m_data[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
m_data[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
} }
break;
default: switch (m_anncType)
if (m_GI) { {
m_data[2U] |= 0x40U; // Group or Individual case BCAST_ANNC_ANN_WD_TSCC:
// Broadcast Parms 1
csbkValue = (csbkValue << 4) + 0U; // Reserved
csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 1
csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 2
csbkValue = (csbkValue << 1) + ((m_annWdCh1) ? 1U : 0U); // Announce/Withdraw Channel 1
csbkValue = (csbkValue << 1) + ((m_annWdCh2) ? 1U : 0U); // Announce/Withdraw Channel 2
csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration
csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number
csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity
// Broadcast Parms 2
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel 1
csbkValue = (csbkValue << 12) + (m_logicalCh2 & 0xFFFU); // Logical Channel 2
break;
case BCAST_ANNC_CHAN_FREQ:
{
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
const uint32_t multiple = 100000;
// calculate Rx frequency
uint32_t rxFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1)) + calcTxOffset);
// generate frequency in mhz
uint32_t rxFreqMhz = rxFrequency + multiple / 2;
rxFreqMhz -= rxFreqMhz % multiple;
rxFreqMhz /= multiple * 10;
// generate khz offset
uint32_t rxFreqKhz = rxFrequency - (rxFreqMhz * 1000000);
// calculate Tx Frequency
uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1)));
// generate frequency in mhz
uint32_t txFreqMhz = txFrequency + multiple / 2;
txFreqMhz -= txFreqMhz % multiple;
txFreqMhz /= multiple * 10;
// generate khz offset
uint32_t txFreqKhz = txFrequency - (txFreqMhz * 1000000);
csbkValue = 0U; // Cdef Type (always 0 for ANN_WD_TSCC)
csbkValue = (csbkValue << 2) + 0U; // Reserved
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel
csbkValue = (csbkValue << 10) + (txFreqMhz & 0x7FFU); // Transmit Freq Mhz
csbkValue = (csbkValue << 13) + (txFreqKhz & 0x3FFFU); // Transmit Freq Offset Khz
csbkValue = (csbkValue << 10) + (rxFreqMhz & 0x7FFU); // Receive Freq Mhz
csbkValue = (csbkValue << 13) + (rxFreqKhz & 0x3FFFU); // Receive Freq Khz
} }
break;
if (m_dataContent) { case BCAST_ANNC_SITE_PARMS:
m_data[2U] |= 0x80U; // // Broadcast Parms 1
csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Parms 1)
csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration
csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number
csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity
// Broadcast Parms 2
csbkValue = (csbkValue << 1) + 0U; // Roaming TG Subscription/Attach
csbkValue = (csbkValue << 1) + ((m_hibernating) ? 1U : 0U); // TSCC Hibernating
csbkValue = (csbkValue << 22) + 0U; // Broadcast Parms 2 (Reserved)
break;
} }
}
break;
m_data[3U] = m_CBF; // default:
csbkValue =
m_data[4U] = (m_dstId >> 16) & 0xFFU; // Destination ID (m_GI ? 0x40U : 0x00U) + // Group or Invididual
m_data[5U] = (m_dstId >> 8) & 0xFFU; (m_dataContent ? 0x80U : 0x00U);
m_data[6U] = (m_dstId >> 0) & 0xFFU; csbkValue = (csbkValue << 8) + m_CBF; // Blocks to Follow
csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address
m_data[7U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[8U] = (m_srcId >> 8) & 0xFFU;
m_data[9U] = (m_srcId >> 0) & 0xFFU;
if ((m_FID == FID_ETSI) || (m_FID == FID_DMRA)) { if ((m_FID == FID_ETSI) || (m_FID == FID_DMRA)) {
LogError(LOG_DMR, "CSBK::encode(), unknown CSBK type, csbko = $%02X", m_CSBKO); LogError(LOG_DMR, "CSBK::encode(), unknown CSBK type, csbko = $%02X", m_CSBKO);
} }
@ -470,65 +388,52 @@ void CSBK::encode(uint8_t* bytes)
if (m_FID == FID_DVM) { if (m_FID == FID_DVM) {
switch (m_CSBKO) { switch (m_CSBKO) {
case CSBKO_DVM_GIT_HASH: case CSBKO_DVM_GIT_HASH:
{ csbkValue = 0U;
ulong64_t csbkValue = 0U; csbkValue = g_gitHashBytes[0]; // ...
csbkValue = g_gitHashBytes[0]; // ... csbkValue = (csbkValue << 8) + (g_gitHashBytes[1U]); // ...
csbkValue = (csbkValue << 8) + (g_gitHashBytes[1U]); // ... csbkValue = (csbkValue << 8) + (g_gitHashBytes[2U]); // ...
csbkValue = (csbkValue << 8) + (g_gitHashBytes[2U]); // ... csbkValue = (csbkValue << 8) + (g_gitHashBytes[3U]); // ...
csbkValue = (csbkValue << 8) + (g_gitHashBytes[3U]); // ... csbkValue = (csbkValue << 16) + 0U;
csbkValue = (csbkValue << 16) + 0U; csbkValue = (csbkValue << 4) + m_siteIdenEntry.channelId(); // Channel ID
csbkValue = (csbkValue << 4) + m_siteIdenEntry.channelId(); // Channel ID csbkValue = (csbkValue << 12) + m_logicalCh1; // Channel Number
csbkValue = (csbkValue << 12) + m_logicalCh1; // Channel Number
// split value into bytes
m_data[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
m_data[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
m_data[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
m_data[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
m_data[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
m_data[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
m_data[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
m_data[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
}
break; break;
default: default:
if (m_GI) { csbkValue =
m_data[2U] |= 0x40U; // Group or Individual (m_GI ? 0x40U : 0x00U) + // Group or Invididual
} (m_dataContent ? 0x80U : 0x00U);
csbkValue = (csbkValue << 8) + m_CBF; // Blocks to Follow
if (m_dataContent) { csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address
m_data[2U] |= 0x80U; // csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address
}
m_data[3U] = m_CBF; //
m_data[4U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[5U] = (m_dstId >> 8) & 0xFFU;
m_data[6U] = (m_dstId >> 0) & 0xFFU;
m_data[7U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[8U] = (m_srcId >> 8) & 0xFFU;
m_data[9U] = (m_srcId >> 0) & 0xFFU;
LogError(LOG_DMR, "CSBK::encode(), unknown CSBK type, csbko = $%02X", m_CSBKO); LogError(LOG_DMR, "CSBK::encode(), unknown CSBK type, csbko = $%02X", m_CSBKO);
break; break;
} }
} }
m_data[10U] ^= CSBK_CRC_MASK[0U]; // split ulong64_t (8 byte) value into bytes
m_data[11U] ^= CSBK_CRC_MASK[1U]; 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);
csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U];
edac::CRC::addCCITT162(m_data, 12U); edac::CRC::addCCITT162(csbk, 12U);
m_data[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
m_data[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
if (m_verbose) { if (m_verbose) {
Utils::dump(2U, "Encoded CSBK", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(2U, "Encoded CSBK", csbk, DMR_CSBK_LENGTH_BYTES);
} }
// encode BPTC (196,96) FEC // encode BPTC (196,96) FEC
edac::BPTC19696 bptc; edac::BPTC19696 bptc;
bptc.encode(m_data, bytes); bptc.encode(csbk, data);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -541,22 +446,27 @@ void CSBK::encode(uint8_t* bytes)
/// <param name="siteData"></param> /// <param name="siteData"></param>
CSBK::CSBK(SiteData siteData) : CSBK::CSBK(SiteData siteData) :
m_verbose(false), m_verbose(false),
m_colorCode(0U),
m_lastBlock(true),
m_Cdef(false),
m_CSBKO(CSBKO_NONE), m_CSBKO(CSBKO_NONE),
m_FID(0x00U), m_FID(0x00U),
m_lastBlock(true),
m_bsId(0U),
m_GI(false), m_GI(false),
m_Cdef(false), m_bsId(0U),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_dataContent(false), m_dataContent(false),
m_CBF(0U), m_CBF(0U),
m_colorCode(0U), m_emergency(false),
m_privacy(false),
m_supplementData(false),
m_priority(0U),
m_broadcast(false),
m_backoffNo(1U), m_backoffNo(1U),
m_serviceType(0U), m_serviceType(0U),
m_serviceOptions(0U),
m_targetAddress(TGT_ADRS_TGID), m_targetAddress(TGT_ADRS_TGID),
m_response(0U), m_response(0U),
m_reason(0U),
m_anncType(BCAST_ANNC_SITE_PARMS), m_anncType(BCAST_ANNC_SITE_PARMS),
m_hibernating(false), m_hibernating(false),
m_annWdCh1(false), m_annWdCh1(false),
@ -568,8 +478,7 @@ CSBK::CSBK(SiteData siteData) :
m_siteOffsetTiming(false), m_siteOffsetTiming(false),
m_alohaMask(0U), m_alohaMask(0U),
m_siteData(siteData), m_siteData(siteData),
m_siteIdenEntry(lookups::IdenTable()), m_siteIdenEntry(lookups::IdenTable())
m_data(NULL)
{ {
m_data = new uint8_t[12U]; /* stub */
} }

@ -55,34 +55,33 @@ namespace dmr
~CSBK(); ~CSBK();
/// <summary>Decodes a DMR CSBK.</summary> /// <summary>Decodes a DMR CSBK.</summary>
bool decode(const uint8_t* bytes); bool decode(const uint8_t* data);
/// <summary>Encodes a DMR CSBK.</summary> /// <summary>Encodes a DMR CSBK.</summary>
void encode(uint8_t* bytes); void encode(uint8_t* data);
public: public:
/// <summary>Flag indicating verbose log output.</summary> /// <summary>Flag indicating verbose log output.</summary>
__PROPERTY(bool, verbose, Verbose); __PROPERTY(bool, verbose, Verbose);
// Generic fields /// <summary>DMR access color code.</summary>
/// <summary>CSBK opcode.</summary> __PROPERTY(uint8_t, colorCode, ColorCode);
__PROPERTY(uint8_t, CSBKO, CSBKO);
/// <summary>CSBK feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID);
/** Common Data */
/// <summary>Flag indicating this is the last TSBK in a sequence of TSBKs.</summary> /// <summary>Flag indicating this is the last TSBK in a sequence of TSBKs.</summary>
__PROPERTY(bool, lastBlock, LastBlock); __PROPERTY(bool, lastBlock, LastBlock);
/// <summary>Flag indicating whether the CSBK is a Cdef block.</summary>
__PROPERTY(bool, Cdef, Cdef);
// For BS Dwn Act /// <summary>CSBK opcode.</summary>
__READONLY_PROPERTY(uint32_t, bsId, BSId); __PROPERTY(uint8_t, CSBKO, CSBKO);
/// <summary>CSBK feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID);
// For Pre
/// <summary>Flag indicating whether the CSBK is group or individual.</summary> /// <summary>Flag indicating whether the CSBK is group or individual.</summary>
__PROPERTY(bool, GI, GI); __PROPERTY(bool, GI, GI);
// For Cdef blocks /// <summary>Base Station ID.</summary>
/// <summary>Flag indicating whether the CSBK is a Cdef block.</summary> __READONLY_PROPERTY(uint32_t, bsId, BSId);
__PROPERTY(bool, Cdef, Cdef);
/// <summary>Source ID.</summary> /// <summary>Source ID.</summary>
__PROPERTY(uint32_t, srcId, SrcId); __PROPERTY(uint32_t, srcId, SrcId);
/// <summary>Destination ID.</summary> /// <summary>Destination ID.</summary>
@ -91,25 +90,35 @@ namespace dmr
/// <summary></summary> /// <summary></summary>
__READONLY_PROPERTY(bool, dataContent, DataContent); __READONLY_PROPERTY(bool, dataContent, DataContent);
/// <summary>Sets the number of blocks to follow.</summary> /// <summary>Number of blocks to follow.</summary>
__PROPERTY(uint8_t, CBF, CBF); __PROPERTY(uint8_t, CBF, CBF);
/// <summary>DMR access color code.</summary> /** Service Options */
__PROPERTY(uint8_t, colorCode, ColorCode); /// <summary>Flag indicating the emergency bits are set.</summary>
__PROPERTY(bool, emergency, Emergency);
// Tier III /// <summary>Flag indicating that privacy is enabled.</summary>
__PROPERTY(bool, privacy, Privacy);
/// <summary>Flag indicating that supplementary data is required.</summary>
__PROPERTY(bool, supplementData, SupplementData);
/// <summary>Priority level for the traffic.</summary>
__PROPERTY(uint8_t, priority, Priority);
/// <summary>Flag indicating a broadcast service.</summary>
__PROPERTY(bool, broadcast, Broadcast);
/** Tier III */
/// <summary>Backoff Number.</summary> /// <summary>Backoff Number.</summary>
__PROPERTY(uint8_t, backoffNo, BackoffNo); __PROPERTY(uint8_t, backoffNo, BackoffNo);
/// <summary>Service Type.</summary> /// <summary>Service Type.</summary>
__PROPERTY(uint8_t, serviceType, serviceType); __PROPERTY(uint8_t, serviceType, serviceType);
/// <summary>Service type.</summary>
__PROPERTY(uint8_t, serviceOptions, ServiceOptions);
/// <summary>Destination/Target address type.</summary> /// <summary>Destination/Target address type.</summary>
__PROPERTY(uint8_t, targetAddress, TargetAddress); __PROPERTY(uint8_t, targetAddress, TargetAddress);
/// <summary>Response type.</summary> /// <summary>Response information.</summary>
__PROPERTY(uint8_t, response, Response); __PROPERTY(uint8_t, response, Response);
/// <summary>Reason type.</summary>
__PROPERTY(uint8_t, reason, reason);
/// <summary>Broadcast Announcment Type.</summary> /// <summary>Broadcast Announcment Type.</summary>
__PROPERTY(uint8_t, anncType, AnncType); __PROPERTY(uint8_t, anncType, AnncType);
@ -144,8 +153,6 @@ namespace dmr
private: private:
/// <summary>Initializes a new instance of the CSBK class.</summary> /// <summary>Initializes a new instance of the CSBK class.</summary>
CSBK(SiteData siteData); CSBK(SiteData siteData);
uint8_t* m_data;
}; };
} // namespace lc } // namespace lc
} // namespace dmr } // namespace dmr

@ -66,8 +66,8 @@ LC::LC(uint8_t flco, uint32_t srcId, uint32_t dstId) :
/// <summary> /// <summary>
/// Initializes a new instance of the LC class. /// Initializes a new instance of the LC class.
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
LC::LC(const uint8_t* bytes) : LC::LC(const uint8_t* data) :
m_PF(false), m_PF(false),
m_FLCO(FLCO_GROUP), m_FLCO(FLCO_GROUP),
m_FID(FID_ETSI), m_FID(FID_ETSI),
@ -80,23 +80,23 @@ LC::LC(const uint8_t* bytes) :
m_priority(CALL_PRIORITY_2), m_priority(CALL_PRIORITY_2),
m_R(false) m_R(false)
{ {
assert(bytes != NULL); assert(data != NULL);
m_PF = (bytes[0U] & 0x80U) == 0x80U; m_PF = (data[0U] & 0x80U) == 0x80U;
m_R = (bytes[0U] & 0x40U) == 0x40U; m_R = (data[0U] & 0x40U) == 0x40U;
m_FLCO = bytes[0U] & 0x3FU; m_FLCO = data[0U] & 0x3FU;
m_FID = bytes[1U]; m_FID = data[1U];
m_emergency = (bytes[2U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[2U] & 0x80U) == 0x80U; // Emergency Flag
m_encrypted = (bytes[2U] & 0x40U) == 0x40U; // Encryption Flag m_encrypted = (data[2U] & 0x40U) == 0x40U; // Encryption Flag
m_broadcast = (bytes[2U] & 0x08U) == 0x08U; // Broadcast Flag m_broadcast = (data[2U] & 0x08U) == 0x08U; // Broadcast Flag
m_ovcm = (bytes[2U] & 0x04U) == 0x04U; // OVCM Flag m_ovcm = (data[2U] & 0x04U) == 0x04U; // OVCM Flag
m_priority = (bytes[2U] & 0x03U); // Priority m_priority = (data[2U] & 0x03U); // Priority
m_dstId = bytes[3U] << 16 | bytes[4U] << 8 | bytes[5U]; // Destination Address m_dstId = data[3U] << 16 | data[4U] << 8 | data[5U]; // Destination Address
m_srcId = bytes[6U] << 16 | bytes[7U] << 8 | bytes[8U]; // Source Address m_srcId = data[6U] << 16 | data[7U] << 8 | data[8U]; // Source Address
} }
/// <summary> /// <summary>
/// Initializes a new instance of the LC class. /// Initializes a new instance of the LC class.
@ -178,34 +178,34 @@ LC::~LC()
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
void LC::getData(uint8_t* bytes) const void LC::getData(uint8_t* data) const
{ {
assert(bytes != NULL); assert(data != NULL);
bytes[0U] = (uint8_t)m_FLCO; data[0U] = (uint8_t)m_FLCO;
if (m_PF) if (m_PF)
bytes[0U] |= 0x80U; data[0U] |= 0x80U;
if (m_R) if (m_R)
bytes[0U] |= 0x40U; data[0U] |= 0x40U;
bytes[1U] = m_FID; data[1U] = m_FID;
bytes[2U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag data[2U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
(m_broadcast ? 0x08U : 0x00U) + // Broadcast Flag (m_broadcast ? 0x08U : 0x00U) + // Broadcast Flag
(m_ovcm ? 0x04U : 0x00U) + // OVCM Flag (m_ovcm ? 0x04U : 0x00U) + // OVCM Flag
(m_priority & 0x03U); // Priority (m_priority & 0x03U); // Priority
bytes[3U] = m_dstId >> 16; // Destination Address data[3U] = m_dstId >> 16; // Destination Address
bytes[4U] = m_dstId >> 8; // .. data[4U] = m_dstId >> 8; // ..
bytes[5U] = m_dstId >> 0; // .. data[5U] = m_dstId >> 0; // ..
bytes[6U] = m_srcId >> 16; // Source Address data[6U] = m_srcId >> 16; // Source Address
bytes[7U] = m_srcId >> 8; // .. data[7U] = m_srcId >> 8; // ..
bytes[8U] = m_srcId >> 0; // .. data[8U] = m_srcId >> 0; // ..
} }
/// <summary> /// <summary>

@ -48,7 +48,7 @@ namespace dmr
/// <summary>Initializes a new instance of the LC class.</summary> /// <summary>Initializes a new instance of the LC class.</summary>
LC(uint8_t flco, uint32_t srcId, uint32_t dstId); LC(uint8_t flco, uint32_t srcId, uint32_t dstId);
/// <summary>Initializes a new instance of the LC class.</summary> /// <summary>Initializes a new instance of the LC class.</summary>
LC(const uint8_t* bytes); LC(const uint8_t* data);
/// <summary>Initializes a new instance of the LC class.</summary> /// <summary>Initializes a new instance of the LC class.</summary>
LC(const bool* bits); LC(const bool* bits);
/// <summary>Initializes a new instance of the LC class.</summary> /// <summary>Initializes a new instance of the LC class.</summary>
@ -57,7 +57,7 @@ namespace dmr
~LC(); ~LC();
/// <summary>Gets LC data as bytes.</summary> /// <summary>Gets LC data as bytes.</summary>
void getData(uint8_t* bytes) const; void getData(uint8_t* data) const;
/// <summary>Gets LC data as bits.</summary> /// <summary>Gets LC data as bits.</summary>
void getData(bool* bits) const; void getData(bool* bits) const;

@ -41,8 +41,8 @@ using namespace dmr;
/// <summary> /// <summary>
/// Initializes a new instance of the PrivacyLC class. /// Initializes a new instance of the PrivacyLC class.
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
PrivacyLC::PrivacyLC(const uint8_t* bytes) : PrivacyLC::PrivacyLC(const uint8_t* data) :
m_FID(FID_ETSI), m_FID(FID_ETSI),
m_dstId(0U), m_dstId(0U),
m_group(false), m_group(false),
@ -50,22 +50,22 @@ PrivacyLC::PrivacyLC(const uint8_t* bytes) :
m_kId(0U), m_kId(0U),
m_mi(NULL) m_mi(NULL)
{ {
assert(bytes != NULL); assert(data != NULL);
m_mi = new uint8_t[DMR_MI_LENGTH_BYTES]; m_mi = new uint8_t[DMR_MI_LENGTH_BYTES];
m_group = (bytes[0U] & 0x20U) == 0x20U; m_group = (data[0U] & 0x20U) == 0x20U;
m_algId = bytes[0U] & 7; // Algorithm ID m_algId = data[0U] & 7; // Algorithm ID
m_FID = bytes[1U]; m_FID = data[1U];
m_kId = bytes[2U]; m_kId = data[2U];
m_mi[0U] = bytes[3U]; m_mi[0U] = data[3U];
m_mi[1U] = bytes[4U]; m_mi[1U] = data[4U];
m_mi[2U] = bytes[5U]; m_mi[2U] = data[5U];
m_mi[3U] = bytes[6U]; m_mi[3U] = data[6U];
m_dstId = bytes[7U] << 16 | bytes[8U] << 8 | bytes[9U]; // Destination Address m_dstId = data[7U] << 16 | data[8U] << 8 | data[9U]; // Destination Address
} }
/// <summary> /// <summary>
/// Initializes a new instance of the PrivacyLC class. /// Initializes a new instance of the PrivacyLC class.
@ -138,25 +138,25 @@ PrivacyLC::~PrivacyLC()
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="data"></param>
void PrivacyLC::getData(uint8_t* bytes) const void PrivacyLC::getData(uint8_t* data) const
{ {
assert(bytes != NULL); assert(data != NULL);
bytes[0U] = (m_group ? 0x20U : 0x00U) + data[0U] = (m_group ? 0x20U : 0x00U) +
(m_algId & 0x07U); // Algorithm ID (m_algId & 0x07U); // Algorithm ID
bytes[1U] = m_FID; data[1U] = m_FID;
bytes[2U] = m_kId; data[2U] = m_kId;
bytes[3U] = m_mi[0U]; data[3U] = m_mi[0U];
bytes[4U] = m_mi[1U]; data[4U] = m_mi[1U];
bytes[5U] = m_mi[2U]; data[5U] = m_mi[2U];
bytes[6U] = m_mi[3U]; data[6U] = m_mi[3U];
bytes[7U] = m_dstId >> 16; // Destination Address data[7U] = m_dstId >> 16; // Destination Address
bytes[8U] = m_dstId >> 8; // .. data[8U] = m_dstId >> 8; // ..
bytes[9U] = m_dstId >> 0; // .. data[9U] = m_dstId >> 0; // ..
} }
/// <summary> /// <summary>

@ -42,7 +42,7 @@ namespace dmr
class HOST_SW_API PrivacyLC { class HOST_SW_API PrivacyLC {
public: public:
/// <summary>Initializes a new instance of the PrivacyLC class.</summary> /// <summary>Initializes a new instance of the PrivacyLC class.</summary>
PrivacyLC(const uint8_t* bytes); PrivacyLC(const uint8_t* data);
/// <summary>Initializes a new instance of the PrivacyLC class.</summary> /// <summary>Initializes a new instance of the PrivacyLC class.</summary>
PrivacyLC(const bool* bits); PrivacyLC(const bool* bits);
/// <summary>Initializes a new instance of the PrivacyLC class.</summary> /// <summary>Initializes a new instance of the PrivacyLC class.</summary>
@ -51,7 +51,7 @@ namespace dmr
~PrivacyLC(); ~PrivacyLC();
/// <summary>Gets LC data as bytes.</summary> /// <summary>Gets LC data as bytes.</summary>
void getData(uint8_t* bytes) const; void getData(uint8_t* data) const;
/// <summary>Gets LC data as bits.</summary> /// <summary>Gets LC data as bits.</summary>
void getData(bool* bits) const; void getData(bool* bits) const;

@ -162,13 +162,15 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len)
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
} }
break; break;
case CSBKO_CALL_ALRT: case CSBKO_RAND:
if (m_verbose) { if (csbk.getFID() == FID_DMRA) {
LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u", if (m_verbose) {
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u",
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
}
::ActivityLog("DMR", true, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
} }
::ActivityLog("DMR", true, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
break; break;
case CSBKO_ACK_RSP: case CSBKO_ACK_RSP:
if (m_verbose) { if (m_verbose) {
@ -312,13 +314,15 @@ void ControlSignaling::processNetwork(const data::Data & dmrData)
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
} }
break; break;
case CSBKO_CALL_ALRT: case CSBKO_RAND:
if (m_verbose) { if (csbk.getFID() == FID_DMRA) {
LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u", if (m_verbose) {
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u",
m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId);
}
::ActivityLog("DMR", false, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
} }
::ActivityLog("DMR", false, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId);
break; break;
case CSBKO_ACK_RSP: case CSBKO_ACK_RSP:
if (m_verbose) { if (m_verbose) {
@ -454,7 +458,7 @@ void ControlSignaling::writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId)
lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData);
csbk.setVerbose(m_dumpCSBKData); csbk.setVerbose(m_dumpCSBKData);
csbk.setCSBKO(CSBKO_CALL_ALRT); csbk.setCSBKO(CSBKO_RAND);
csbk.setFID(FID_DMRA); csbk.setFID(FID_DMRA);
csbk.setGI(false); csbk.setGI(false);

@ -185,7 +185,7 @@ bool LC::decodeHDU(const uint8_t* data)
ulong64_t rsValue = 0U; ulong64_t rsValue = 0U;
// combine bytes into rs value // combine bytes into ulong64_t (8 byte) value
rsValue = rs[12U]; rsValue = rs[12U];
rsValue = (rsValue << 8) + rs[13U]; rsValue = (rsValue << 8) + rs[13U];
rsValue = (rsValue << 8) + rs[14U]; rsValue = (rsValue << 8) + rs[14U];
@ -562,7 +562,7 @@ bool LC::decodeLC(const uint8_t * rs)
{ {
ulong64_t rsValue = 0U; ulong64_t rsValue = 0U;
// combine bytes into rs value // combine bytes into ulong64_t (8 byte) value
rsValue = rs[1U]; rsValue = rs[1U];
rsValue = (rsValue << 8) + rs[2U]; rsValue = (rsValue << 8) + rs[2U];
rsValue = (rsValue << 8) + rs[3U]; rsValue = (rsValue << 8) + rs[3U];
@ -685,7 +685,7 @@ void LC::encodeLC(uint8_t * rs)
break; break;
} }
// split rs value into bytes // split ulong64_t (8 byte) value into bytes
rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU); rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU);
rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU); rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU);
rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU); rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU);

@ -290,7 +290,7 @@ bool TDULC::decodeLC(const uint8_t* rs)
{ {
ulong64_t rsValue = 0U; ulong64_t rsValue = 0U;
// combine bytes into rs value // combine bytes into ulong64_t (8 byte) value
rsValue = rs[1U]; rsValue = rs[1U];
rsValue = (rsValue << 8) + rs[2U]; rsValue = (rsValue << 8) + rs[2U];
rsValue = (rsValue << 8) + rs[3U]; rsValue = (rsValue << 8) + rs[3U];
@ -508,7 +508,7 @@ void TDULC::encodeLC(uint8_t* rs)
break; break;
} }
// split rs value into bytes // split ulong64_t (8 byte) value into bytes
rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU); rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU);
rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU); rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU);
rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU); rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU);

@ -193,7 +193,7 @@ bool TSBK::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* b
ulong64_t tsbkValue = 0U; ulong64_t tsbkValue = 0U;
// combine bytes into rs value // combine bytes into ulong64_t (8 byte) value
tsbkValue = dataHeader.getAMBTField8(); tsbkValue = dataHeader.getAMBTField8();
tsbkValue = (tsbkValue << 8) + dataHeader.getAMBTField9(); tsbkValue = (tsbkValue << 8) + dataHeader.getAMBTField9();
tsbkValue = (tsbkValue << 8) + pduUserData[0U]; tsbkValue = (tsbkValue << 8) + pduUserData[0U];
@ -544,7 +544,7 @@ bool TSBK::decode(const uint8_t* data, bool rawTSBK)
ulong64_t tsbkValue = 0U; ulong64_t tsbkValue = 0U;
// combine bytes into rs value // combine bytes into ulong64_t (8 byte) value
tsbkValue = tsbk[2U]; tsbkValue = tsbk[2U];
tsbkValue = (tsbkValue << 8) + tsbk[3U]; tsbkValue = (tsbkValue << 8) + tsbk[3U];
tsbkValue = (tsbkValue << 8) + tsbk[4U]; tsbkValue = (tsbkValue << 8) + tsbk[4U];
@ -1324,7 +1324,7 @@ void TSBK::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
} }
} }
// split rs value into bytes // split ulong64_t (8 byte) value into bytes
tsbk[2U] = (uint8_t)((tsbkValue >> 56) & 0xFFU); tsbk[2U] = (uint8_t)((tsbkValue >> 56) & 0xFFU);
tsbk[3U] = (uint8_t)((tsbkValue >> 48) & 0xFFU); tsbk[3U] = (uint8_t)((tsbkValue >> 48) & 0xFFU);
tsbk[4U] = (uint8_t)((tsbkValue >> 40) & 0xFFU); tsbk[4U] = (uint8_t)((tsbkValue >> 40) & 0xFFU);

Loading…
Cancel
Save

Powered by TurnKey Linux.