From 936481f76b39e437ee694f93042bc6e694203cce Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Fri, 12 Aug 2022 19:46:24 -0400 Subject: [PATCH] fix latent issue with symbol dump dumping 1 extra byte; correct bitwise CRC-16 incorrectly calculating the CRC-16-CCITT; add extra debugging logic to NXDN code; rework how various array sizes are handled for NXDN; continue work on NXDN RCCH CAC implementation; refactor NXDN LICH slightly (we don't need a 1 byte 'array' for this); --- Utils.cpp | 2 +- edac/CRC.cpp | 11 ++-- host/Host.cpp | 3 +- nxdn/Control.cpp | 14 ++-- nxdn/NXDNDefines.h | 74 ++++++++++------------ nxdn/channel/CAC.cpp | 137 ++++++++++++++++++++++++++-------------- nxdn/channel/CAC.h | 2 + nxdn/channel/FACCH1.cpp | 44 +++++++------ nxdn/channel/LICH.cpp | 74 ++++++++++++---------- nxdn/channel/LICH.h | 6 +- nxdn/channel/SACCH.cpp | 54 +++++++++------- nxdn/channel/UDCH.cpp | 36 ++++++----- nxdn/lc/RCCH.cpp | 18 +++--- nxdn/lc/RTCH.cpp | 8 ++- nxdn/packet/Data.cpp | 14 ++-- nxdn/packet/Trunk.cpp | 23 ++++--- nxdn/packet/Voice.cpp | 20 +++--- 17 files changed, 313 insertions(+), 227 deletions(-) diff --git a/Utils.cpp b/Utils.cpp index 281209fa..249bd564 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -212,7 +212,7 @@ void Utils::symbols(const std::string& title, const uint8_t* data, uint32_t leng } for (unsigned i = 0U; i < 9U; i++) { - if (symOffset + i > length) { + if (symOffset + i >= length) { break; } diff --git a/edac/CRC.cpp b/edac/CRC.cpp index f16c4084..9a9e22de 100644 --- a/edac/CRC.cpp +++ b/edac/CRC.cpp @@ -660,7 +660,7 @@ bool CRC::checkCRC16(const uint8_t* in, uint32_t bitLength) { assert(in != NULL); - uint16_t crc = createCRC15(in, bitLength); + uint16_t crc = createCRC16(in, bitLength); uint8_t temp1[2U]; temp1[0U] = (crc >> 8) & 0xFFU; temp1[1U] = (crc >> 0) & 0xFFU; @@ -669,7 +669,7 @@ bool CRC::checkCRC16(const uint8_t* in, uint32_t bitLength) temp2[0U] = 0x00U; temp2[1U] = 0x00U; uint32_t j = bitLength; - for (uint32_t i = 1U; i < 16U; i++, j++) { + for (uint32_t i = 0U; i < 16U; i++, j++) { bool b = READ_BIT(in, j); WRITE_BIT(temp2, i, b); } @@ -692,14 +692,14 @@ void CRC::addCRC16(uint8_t* in, uint32_t bitLength) { assert(in != NULL); - uint16_t crc = createCRC15(in, bitLength); + uint16_t crc = createCRC16(in, bitLength); uint8_t temp[2U]; temp[0U] = (crc >> 8) & 0xFFU; temp[1U] = (crc >> 0) & 0xFFU; uint32_t n = bitLength; - for (uint32_t i = 1U; i < 16U; i++, n++) { + for (uint32_t i = 0U; i < 16U; i++, n++) { bool b = READ_BIT(temp, i); WRITE_BIT(in, n, b); } @@ -790,7 +790,7 @@ uint16_t CRC::createCRC15(const uint8_t* in, uint32_t bitLength) /// uint16_t CRC::createCRC16(const uint8_t* in, uint32_t bitLength) { - uint16_t crc = 0xFFFFU; + uint16_t crc = 0x0000U; for (uint32_t i = 0U; i < bitLength; i++) { bool bit1 = READ_BIT(in, i) != 0x00U; @@ -802,5 +802,6 @@ uint16_t CRC::createCRC16(const uint8_t* in, uint32_t bitLength) crc ^= 0x1021U; } + crc = ~crc; return crc & 0xFFFFU; } diff --git a/host/Host.cpp b/host/Host.cpp index 11f68488..ee087c52 100644 --- a/host/Host.cpp +++ b/host/Host.cpp @@ -2138,7 +2138,8 @@ bool Host::createModem() LogInfo(" UDP Address: %s", g_remoteAddress.c_str()); LogInfo(" UDP Port: %u", g_remotePort); } - else { + + if (!m_modemRemote) { LogInfo(" RX Invert: %s", rxInvert ? "yes" : "no"); LogInfo(" TX Invert: %s", txInvert ? "yes" : "no"); LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no"); diff --git a/nxdn/Control.cpp b/nxdn/Control.cpp index e8b1bae0..412e250f 100644 --- a/nxdn/Control.cpp +++ b/nxdn/Control.cpp @@ -117,7 +117,7 @@ Control::Control(uint32_t ran, uint32_t callHang, uint32_t queueSize, uint32_t t m_rfTGHang(1000U, tgHang), m_netTimeout(1000U, timeout), m_networkWatchdog(1000U, 0U, 1500U), - m_ccPacketInterval(1000U, 0U, 25U), + m_ccPacketInterval(1000U, 0U, 10U), m_ccFrameCnt(0U), m_ccSeq(0U), m_siteData(), @@ -709,14 +709,14 @@ void Control::writeRF_Message_Tx_Rel(bool noNetwork) lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_UDCH); lich.setOption(NXDN_LICH_USC_UDCH); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(true); lich.encode(data + 2U); - uint8_t buffer[NXDN_UDCH_LENGTH_BYTES]; - ::memset(buffer, 0x00U, NXDN_UDCH_LENGTH_BYTES); + uint8_t buffer[NXDN_RTCH_LC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_RTCH_LC_LENGTH_BYTES); m_rfLC.setMessageType(RTCH_MESSAGE_TYPE_TX_REL); - m_rfLC.encode(buffer, NXDH_UDCH_CRC_BITS); + m_rfLC.encode(buffer, NXDN_UDCH_LENGTH_BITS); channel::UDCH udch; udch.setRAN(m_ran); @@ -778,6 +778,10 @@ void Control::scrambler(uint8_t* data) const { assert(data != NULL); + if (m_debug) { + Utils::symbols("!!! *Tx NXDN (Unscrambled)", data, NXDN_FRAME_LENGTH_BYTES); + } + for (uint32_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) data[i] ^= SCRAMBLER[i]; } diff --git a/nxdn/NXDNDefines.h b/nxdn/NXDNDefines.h index 487c9fd4..5eab24f1 100644 --- a/nxdn/NXDNDefines.h +++ b/nxdn/NXDNDefines.h @@ -84,59 +84,51 @@ namespace nxdn const uint32_t NXDN_SACCH_FEC_LENGTH_BYTES = (NXDN_SACCH_FEC_LENGTH_BITS / 8U) + 1U; const uint32_t NXDN_SACCH_FEC_CONV_LENGTH_BITS = 72U; // Convolution Length const uint32_t NXDN_SACCH_FEC_CONV_LENGTH_BYTES = NXDN_SACCH_FEC_CONV_LENGTH_BITS / 8U; - const uint32_t NXDN_SACCH_LENGTH_BITS = 36U; // Data + CRC-6 + 4-bit NULL - const uint32_t NXDN_SACCH_LENGTH_BYTES = (NXDN_SACCH_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_SACCH_CRC_BITS = 26U; // Data + const uint32_t NXDN_SACCH_CRC_LENGTH_BITS = 36U; // Data + CRC-6 + 4-bit NULL + const uint32_t NXDN_SACCH_CRC_LENGTH_BYTES = (NXDN_SACCH_CRC_LENGTH_BITS / 8U) + 1U; + const uint32_t NXDN_SACCH_LENGTH_BITS = 26U; const uint32_t NXDN_FACCH1_FEC_LENGTH_BITS = 144U; // Puncture and Interleave Length const uint32_t NXDN_FACCH1_FEC_LENGTH_BYTES = NXDN_FACCH1_FEC_LENGTH_BITS / 8U; const uint32_t NXDN_FACCH1_FEC_CONV_LENGTH_BITS = 192U; // Convolution Length const uint32_t NXDN_FACCH1_FEC_CONV_LENGTH_BYTES = NXDN_FACCH1_FEC_CONV_LENGTH_BITS / 8U; - const uint32_t NXDN_FACCH1_LENGTH_BITS = 96U; // Data + CRC-12 + 4-bit NULL - const uint32_t NXDN_FACCH1_LENGTH_BYTES = NXDN_FACCH1_LENGTH_BITS / 8U; - const uint32_t NXDN_FACCH1_CRC_BITS = 80U; // Data + const uint32_t NXDN_FACCH1_CRC_LENGTH_BITS = 96U; // Data + CRC-12 + 4-bit NULL + const uint32_t NXDN_FACCH1_CRC_LENGTH_BYTES = NXDN_FACCH1_CRC_LENGTH_BITS / 8U; + const uint32_t NXDN_FACCH1_LENGTH_BITS = 80U; const uint32_t NXDN_UDCH_FEC_LENGTH_BITS = 348U; // Puncture and Interleave Length const uint32_t NXDN_UDCH_FEC_LENGTH_BYTES = (NXDN_UDCH_FEC_LENGTH_BITS / 8U) + 1U; const uint32_t NXDN_UDCH_FEC_CONV_LENGTH_BITS = 406U; // Convolution Length const uint32_t NXDN_UDCH_FEC_CONV_LENGTH_BYTES = (NXDN_UDCH_FEC_CONV_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_UDCH_LENGTH_BITS = 203U; // Data + CRC-15 + 4-bit NULL - const uint32_t NXDN_UDCH_LENGTH_BYTES = (NXDN_UDCH_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDH_UDCH_CRC_BITS = 184U; // Data - const uint32_t NXDH_UDCH_CRC_BYTES = NXDH_UDCH_CRC_BITS / 8U; - - const uint32_t NXDN_CAC_LENGTH_BITS = 384U; - const uint32_t NXDN_CAC_LENGTH_BYTES = (NXDN_CAC_LENGTH_BITS / 8U); - - const uint32_t NXDN_CAC_OUT_FEC_LENGTH_BITS = 300U; // Puncture and Interleave Length - const uint32_t NXDN_CAC_OUT_FEC_LENGTH_BYTES = (NXDN_CAC_OUT_FEC_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_CAC_OUT_FEC_CONV_LENGTH_BITS = 350U; // Convolution Length - const uint32_t NXDN_CAC_OUT_FEC_CONV_LENGTH_BYTES = (NXDN_CAC_OUT_FEC_CONV_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_CAC_OUT_LENGTH_BITS = 175U; // Data + CRC-16 + 4-bit NULL - const uint32_t NXDN_CAC_OUT_LENGTH_BYTES = (NXDN_CAC_OUT_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_CAC_OUT_CRC_BITS = 155U; // Data + const uint32_t NXDN_UDCH_CRC_LENGTH_BITS = 203U; // Data + CRC-15 + 4-bit NULL + const uint32_t NXDN_UDCH_CRC_LENGTH_BYTES = (NXDN_UDCH_CRC_LENGTH_BITS / 8U) + 1U; + const uint32_t NXDN_UDCH_LENGTH_BITS = 184U; + + const uint32_t NXDN_CAC_FRAME_LENGTH_BITS = 348U; + const uint32_t NXDN_CAC_FRAME_LENGTH_BYTES = (NXDN_CAC_FRAME_LENGTH_BITS / 8U) + 1U; + const uint32_t NXDN_CAC_FEC_LENGTH_BITS = 300U; // Puncture and Interleave Length + const uint32_t NXDN_CAC_FEC_LENGTH_BYTES = (NXDN_CAC_FEC_LENGTH_BITS / 8U) + 1U; + const uint32_t NXDN_CAC_FEC_CONV_LENGTH_BITS = 350U; // Convolution Length + const uint32_t NXDN_CAC_FEC_CONV_LENGTH_BYTES = (NXDN_CAC_FEC_CONV_LENGTH_BITS / 8U) + 1U; + const uint32_t NXDN_CAC_CRC_LENGTH_BITS = 175U; // Data + CRC-16 + 4-bit NULL + const uint32_t NXDN_CAC_LENGTH_BITS = 155U; + const uint32_t NXDN_CAC_E_POST_FIELD_BITS = 24U; const uint32_t NXDN_CAC_IN_FEC_LENGTH_BITS = 252U; // Puncture and Interleave Length const uint32_t NXDN_CAC_IN_FEC_LENGTH_BYTES = (NXDN_CAC_IN_FEC_LENGTH_BITS / 8U) + 1U; + const uint32_t NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS = 312U; // Convolution Length + const uint32_t NXDN_CAC_LONG_FEC_CONV_LENGTH_BYTES = NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS / 8U; + const uint32_t NXDN_CAC_LONG_CRC_LENGTH_BITS = 156U; // Data + CRC-16 + 4-bit NULL + const uint32_t NXDN_CAC_LONG_LENGTH_BITS = 136U; + const uint32_t NXDN_CAC_SHORT_CRC_LENGTH_BITS = 126U; // Data + CRC-16 + 4-bit NULL + const uint32_t NXDN_CAC_SHORT_LENGTH_BITS = 106U; - const uint32_t NXDN_CAC_LONG_IN_FEC_CONV_LENGTH_BITS = 312U; // Convolution Length - const uint32_t NXDN_CAC_LONG_IN_FEC_CONV_LENGTH_BYTES = NXDN_CAC_LONG_IN_FEC_CONV_LENGTH_BITS / 8U; - const uint32_t NXDN_CAC_LONG_IN_LENGTH_BITS = 156U; // Data + CRC-16 + 4-bit NULL - const uint32_t NXDN_CAC_LONG_IN_LENGTH_BYTES = (NXDN_CAC_LONG_IN_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_CAC_LONG_IN_CRC_BITS = 136U; // Data - const uint32_t NXDN_CAC_LONG_IN_CRC_BYTES = NXDN_CAC_LONG_IN_CRC_BITS / 8U; + const uint32_t NXDN_RTCH_LC_LENGTH_BYTES = 22U; // this is really the UDCH size... - const uint32_t NXDN_CAC_SHORT_IN_FEC_LENGTH_BITS = 252U; // Interleave Length - const uint32_t NXDN_CAC_SHORT_IN_FEC_LENGTH_BYTES = (NXDN_CAC_SHORT_IN_FEC_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_CAC_SHORT_IN_LENGTH_BITS = 126U; // Data + CRC-16 + 4-bit NULL - const uint32_t NXDN_CAC_SHORT_IN_LENGTH_BYTES = (NXDN_CAC_SHORT_IN_LENGTH_BITS / 8U) + 1U; - const uint32_t NXDN_CAC_SHORT_IN_CRC_BITS = 106U; // Data - const uint32_t NXDN_CAC_SHORT_IN_CRC_BYTES = (NXDN_CAC_SHORT_IN_CRC_BITS / 8U) + 1U; - - const uint32_t NXDN_RTCH_LC_LENGTH_BYTES = 22U; - const uint32_t NXDN_RCCH_LC_LENGTH_BYTES = 22U; - - const uint32_t NXDN_E_POST_FIELD_BITS = 24U; + const uint32_t NXDN_RCCH_LC_LENGTH_BITS = 144U; + const uint32_t NXDN_RCCH_LC_LENGTH_BYTES = (NXDN_RCCH_LC_LENGTH_BITS / 8U); + const uint32_t NXDN_RCCH_CAC_LC_LONG_LENGTH_BITS = 128U; + const uint32_t NXDN_RCCH_CAC_LC_SHORT_LENGTH_BITS = 96U; const uint8_t POST_FIELD[] = { 0x57U, 0x75U, 0xFDU }; @@ -166,8 +158,10 @@ namespace nxdn const uint8_t NXDN_LICH_STEAL_FACCH1_1 = 1U; const uint8_t NXDN_LICH_STEAL_FACCH = 0U; - const uint8_t NXDN_LICH_DIRECTION_INBOUND = 0U; - const uint8_t NXDN_LICH_DIRECTION_OUTBOUND = 1U; + const uint8_t NXDN_SR_RCCH_SINGLE = 0x00U; + const uint8_t NXDN_SR_RCCH_DUAL = 0x01U; + const uint8_t NXDN_SR_RCCH_HEAD_SINGLE = 0x02U; + const uint8_t NXDN_SR_RCCH_HEAD_DUAL = 0x03U; const uint8_t NXDN_SR_SINGLE = 0U; const uint8_t NXDN_SR_4_4 = 0U; diff --git a/nxdn/channel/CAC.cpp b/nxdn/channel/CAC.cpp index 2e32af77..3b1e1e2b 100644 --- a/nxdn/channel/CAC.cpp +++ b/nxdn/channel/CAC.cpp @@ -120,10 +120,16 @@ const uint32_t PUNCTURE_LIST_OUT[] = { /// CAC::CAC() : m_verbose(false), - m_ran(0U), - m_data(NULL) + m_ran(1U), + m_structure(NXDN_SR_RCCH_SINGLE), + m_idleBusy(true), + m_txContinuous(false), + m_receive(true), + m_data(NULL), + m_rxCRC(0U) { - m_data = new uint8_t[NXDN_CAC_OUT_LENGTH_BYTES]; + m_data = new uint8_t[NXDN_CAC_FRAME_LENGTH_BYTES]; + ::memset(m_data, 0x00U, NXDN_CAC_FRAME_LENGTH_BYTES); } /// @@ -132,8 +138,13 @@ CAC::CAC() : /// CAC::CAC(const CAC& data) : m_verbose(false), - m_ran(0U), - m_data(NULL) + m_ran(1U), + m_structure(NXDN_SR_RCCH_SINGLE), + m_idleBusy(true), + m_txContinuous(false), + m_receive(true), + m_data(NULL), + m_rxCRC(0U) { copy(data); } @@ -154,11 +165,18 @@ CAC::~CAC() CAC& CAC::operator=(const CAC& data) { if (&data != this) { - ::memcpy(m_data, data.m_data, NXDN_CAC_OUT_LENGTH_BYTES); + ::memcpy(m_data, data.m_data, NXDN_CAC_FRAME_LENGTH_BYTES); m_verbose = data.m_verbose; m_ran = m_data[0U] & 0x3FU; + m_structure = (m_data[0U] >> 6) & 0x03U; + + m_idleBusy = data.m_idleBusy; + m_txContinuous = data.m_txContinuous; + m_receive = data.m_receive; + + m_rxCRC = data.m_rxCRC; } return *this; @@ -173,7 +191,8 @@ bool CAC::decode(const uint8_t* data) { assert(data != NULL); - uint8_t buffer[NXDN_CAC_IN_FEC_LENGTH_BYTES + 1U]; + uint8_t buffer[NXDN_CAC_IN_FEC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_CAC_IN_FEC_LENGTH_BYTES); // deinterleave for (uint32_t i = 0U; i < NXDN_CAC_IN_FEC_LENGTH_BITS; i++) { @@ -193,21 +212,21 @@ bool CAC::decode(const uint8_t* data) conv.start(); uint32_t n = 0U; - for (uint32_t i = 0U; i < (NXDN_CAC_SHORT_IN_LENGTH_BITS + 4U); i++) { + for (uint32_t i = 0U; i < (NXDN_CAC_SHORT_CRC_LENGTH_BITS + 4U); i++) { uint8_t s0 = buffer[n++]; uint8_t s1 = buffer[n++]; conv.decode(s0, s1); } - conv.chainback(m_data, NXDN_CAC_SHORT_IN_LENGTH_BITS); + conv.chainback(m_data, NXDN_CAC_SHORT_CRC_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Decoded CAC", m_data, NXDN_CAC_SHORT_IN_LENGTH_BYTES); + Utils::dump(2U, "Decoded CAC", m_data, (NXDN_CAC_SHORT_CRC_LENGTH_BITS / 8U) + 1U); } // check CRC-16 - bool ret = CRC::checkCRC16(m_data, NXDN_CAC_SHORT_IN_CRC_BITS); + bool ret = CRC::checkCRC16(m_data, NXDN_CAC_SHORT_LENGTH_BITS); if (!ret) { LogError(LOG_NXDN, "SACCH::decode(), failed CRC-6 check"); return false; @@ -217,16 +236,22 @@ bool CAC::decode(const uint8_t* data) uint8_t crc[2U]; ::memset(crc, 0x00U, 2U); - uint32_t j = NXDN_CAC_SHORT_IN_CRC_BITS; - for (uint32_t i = 1U; i < 16U; i++, j++) { - bool b = READ_BIT(m_data, j); + m_ran = m_data[0U] & 0x3FU; + m_structure = (m_data[0U] >> 6) & 0x03U; + + uint32_t offset = NXDN_CAC_SHORT_CRC_LENGTH_BITS - 20U; + for (uint32_t i = 0U; i < 16U; i++, offset++) { + bool b = READ_BIT(m_data, offset); WRITE_BIT(crc, i, b); } m_rxCRC = (crc[0U] << 8) | (crc[1U] << 0); - m_ran = m_data[0U] & 0x3FU; - +#if DEBUG_NXDN_CAC + if (m_verbose) { + Utils::dump(2U, "Raw CAC Buffer", m_data, NXDN_CAC_FEC_LENGTH_BYTES); + } +#endif return true; } @@ -238,36 +263,43 @@ void CAC::encode(uint8_t* data) const { assert(data != NULL); - m_data[0U] &= 0xC0U; - m_data[0U] |= m_ran; + m_data[0U] &= 0xC0U; + m_data[0U] |= m_ran; - uint8_t buffer[NXDN_CAC_OUT_LENGTH_BYTES]; - ::memset(buffer, 0x00U, NXDN_CAC_OUT_LENGTH_BYTES); + m_data[0U] &= 0x3FU; + m_data[0U] |= (m_structure << 6) & 0xC0U; - for (uint32_t i = 0U; i < NXDN_CAC_OUT_CRC_BITS; i++) { + uint8_t buffer[NXDN_CAC_FEC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_CAC_FEC_LENGTH_BYTES); + + for (uint32_t i = 0U; i < NXDN_CAC_LENGTH_BITS; i++) { bool b = READ_BIT(m_data, i); WRITE_BIT(buffer, i, b); } - CRC::addCRC16(buffer, NXDN_CAC_OUT_CRC_BITS); + CRC::addCRC16(buffer, NXDN_CAC_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Encoded CAC", buffer, NXDN_CAC_OUT_LENGTH_BYTES); + Utils::dump(2U, "Encoded CAC", buffer, NXDN_CAC_FEC_LENGTH_BYTES); } // encode convolution - uint8_t convolution[NXDN_CAC_OUT_FEC_CONV_LENGTH_BYTES]; + uint8_t convolution[NXDN_CAC_FEC_CONV_LENGTH_BYTES]; + ::memset(convolution, 0x00U, NXDN_CAC_FEC_CONV_LENGTH_BYTES); + Convolution conv; - conv.encode(buffer, convolution, NXDN_CAC_OUT_LENGTH_BITS); + conv.encode(buffer, convolution, NXDN_CAC_CRC_LENGTH_BITS); #if DEBUG_NXDN_CAC - Utils::dump(2U, "CAC::encode(), CAC Convolution", convolution, NXDN_CAC_OUT_FEC_CONV_LENGTH_BYTES); + Utils::dump(2U, "CAC::encode(), CAC Convolution", convolution, NXDN_CAC_FEC_CONV_LENGTH_BYTES); #endif // puncture - uint8_t puncture[NXDN_CAC_OUT_FEC_LENGTH_BYTES]; + uint8_t puncture[NXDN_CAC_FEC_LENGTH_BYTES]; + ::memset(puncture, 0x00U, NXDN_CAC_FEC_LENGTH_BYTES); + uint32_t n = 0U, index = 0U; - for (uint32_t i = 0U; i < NXDN_CAC_OUT_FEC_CONV_LENGTH_BITS; i++) { + for (uint32_t i = 0U; i < NXDN_CAC_FEC_CONV_LENGTH_BITS; i++) { if (i != PUNCTURE_LIST_OUT[index]) { bool b = READ_BIT(convolution, i); WRITE_BIT(puncture, n, b); @@ -278,41 +310,45 @@ void CAC::encode(uint8_t* data) const } // interleave - for (uint32_t i = 0U; i < NXDN_CAC_OUT_FEC_LENGTH_BITS; i++) { + for (uint32_t i = 0U; i < NXDN_CAC_FEC_LENGTH_BITS; i++) { uint32_t n = INTERLEAVE_TABLE_OUT[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS; bool b = READ_BIT(puncture, i); WRITE_BIT(data, n, b); } #if DEBUG_NXDN_CAC - Utils::dump(2U, "CAC::encode(), CAC Puncture and Interleave", data, NXDN_CAC_OUT_FEC_LENGTH_BYTES); + Utils::dump(2U, "CAC::encode(), CAC Puncture and Interleave", data, NXDN_CAC_FRAME_LENGTH_BYTES); #endif // apply control field uint8_t control[3U]; ::memset(control, 0x00U, 3U); - uint8_t parity = 0x01U; + uint8_t parity = 0x03U; if (m_idleBusy && m_txContinuous) - parity = 0x03U; + parity = 0x01U; - control[0U] = ((m_idleBusy ? 0x03U : 0x01U) << 22) + ((m_txContinuous ? 0x03U : 0x01U) << 20) + - (parity << 18) + ((m_receive ? 0x03U : 0x01U) << 16); - control[1U] = (m_rxCRC >> 8U); - control[2U] = (m_rxCRC >> 0U); + control[0U] = ((m_idleBusy ? 0x03U : 0x01U) << 6) + ((m_txContinuous ? 0x03U : 0x01U) << 4) + + (parity << 2) + ((m_receive ? 0x03U : 0x01U)); + control[1U] = (m_rxCRC >> 8U) & 0xFFU; + control[2U] = (m_rxCRC >> 0U) & 0xFFU; - uint32_t offset = NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_CAC_OUT_FEC_LENGTH_BITS; - for (uint32_t i = 0U; i < NXDN_E_POST_FIELD_BITS; i++, offset++) { + for (uint32_t i = 0U; i < NXDN_CAC_E_POST_FIELD_BITS; i++) { + uint32_t n = i + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_CAC_FEC_LENGTH_BITS; bool b = READ_BIT(control, i); - WRITE_BIT(data, offset, b); + WRITE_BIT(data, n, b); } // post field - offset = NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_CAC_OUT_FEC_LENGTH_BITS + NXDN_E_POST_FIELD_BITS; - for (uint32_t i = 0U; i < NXDN_E_POST_FIELD_BITS; i++, offset++) { + for (uint32_t i = 0U; i < NXDN_CAC_E_POST_FIELD_BITS; i++) { + uint32_t n = i + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_CAC_FEC_LENGTH_BITS + NXDN_CAC_E_POST_FIELD_BITS; bool b = READ_BIT(POST_FIELD, i); - WRITE_BIT(data, offset, b); + WRITE_BIT(data, n, b); } + +#if DEBUG_NXDN_CAC + Utils::dump(2U, "CAC::encode(), CAC + E + Post", data, NXDN_FRAME_LENGTH_BYTES); +#endif } /// @@ -324,7 +360,7 @@ void CAC::getData(uint8_t* data) const assert(data != NULL); uint32_t offset = 8U; - for (uint32_t i = 0U; i < (NXDN_CAC_SHORT_IN_CRC_BITS - 8); i++, offset++) { + for (uint32_t i = 0U; i < (NXDN_CAC_SHORT_LENGTH_BITS - 10); i++, offset++) { bool b = READ_BIT(m_data, offset); WRITE_BIT(data, i, b); } @@ -338,8 +374,10 @@ void CAC::setData(const uint8_t* data) { assert(data != NULL); + ::memset(m_data, 0x00U, NXDN_CAC_FRAME_LENGTH_BYTES); + uint32_t offset = 8U; - for (uint32_t i = 0U; i < (NXDN_CAC_OUT_CRC_BITS - 8); i++, offset++) { + for (uint32_t i = 0U; i < (NXDN_CAC_CRC_LENGTH_BITS - 31); i++, offset++) { bool b = READ_BIT(data, i); WRITE_BIT(m_data, offset, b); } @@ -355,8 +393,15 @@ void CAC::setData(const uint8_t* data) /// void CAC::copy(const CAC& data) { - m_data = new uint8_t[NXDN_CAC_OUT_LENGTH_BYTES]; - ::memcpy(m_data, data.m_data, NXDN_CAC_OUT_LENGTH_BYTES); + m_data = new uint8_t[NXDN_CAC_FRAME_LENGTH_BYTES]; + ::memcpy(m_data, data.m_data, NXDN_CAC_FRAME_LENGTH_BYTES); m_ran = m_data[0U] & 0x3FU; + m_structure = (m_data[0U] >> 6) & 0x03U; + + m_idleBusy = data.m_idleBusy; + m_txContinuous = data.m_txContinuous; + m_receive = data.m_receive; + + m_rxCRC = data.m_rxCRC; } diff --git a/nxdn/channel/CAC.h b/nxdn/channel/CAC.h index 3b771052..1f9a1be1 100644 --- a/nxdn/channel/CAC.h +++ b/nxdn/channel/CAC.h @@ -70,6 +70,8 @@ namespace nxdn /** Common Data */ /// Radio Access Number __PROPERTY(uint8_t, ran, RAN); + /// + __PROPERTY(uint8_t, structure, Structure); /** Collision Control Field */ /// Idle/Busy. diff --git a/nxdn/channel/FACCH1.cpp b/nxdn/channel/FACCH1.cpp index fae4d773..e40fa49a 100644 --- a/nxdn/channel/FACCH1.cpp +++ b/nxdn/channel/FACCH1.cpp @@ -75,7 +75,8 @@ FACCH1::FACCH1() : m_verbose(false), m_data(NULL) { - m_data = new uint8_t[NXDN_FACCH1_LENGTH_BYTES]; + m_data = new uint8_t[NXDN_FACCH1_CRC_LENGTH_BYTES]; + ::memset(m_data, 0x00U, NXDN_FACCH1_CRC_LENGTH_BYTES); } /// @@ -105,7 +106,7 @@ FACCH1::~FACCH1() FACCH1& FACCH1::operator=(const FACCH1& data) { if (&data != this) { - ::memcpy(m_data, data.m_data, NXDN_FACCH1_LENGTH_BYTES); + ::memcpy(m_data, data.m_data, NXDN_FACCH1_CRC_LENGTH_BYTES); m_verbose = data.m_verbose; } @@ -123,6 +124,7 @@ bool FACCH1::decode(const uint8_t* data, uint32_t offset) assert(data != NULL); uint8_t buffer[NXDN_FACCH1_FEC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_FACCH1_FEC_LENGTH_BYTES); // deinterleave for (uint32_t i = 0U; i < NXDN_FACCH1_FEC_LENGTH_BITS; i++) { @@ -157,21 +159,21 @@ bool FACCH1::decode(const uint8_t* data, uint32_t offset) conv.start(); n = 0U; - for (uint32_t i = 0U; i < (NXDN_FACCH1_LENGTH_BITS + 4U); i++) { + for (uint32_t i = 0U; i < (NXDN_FACCH1_CRC_LENGTH_BITS + 4U); i++) { uint8_t s0 = puncture[n++]; uint8_t s1 = puncture[n++]; conv.decode(s0, s1); } - conv.chainback(m_data, NXDN_FACCH1_LENGTH_BITS); + conv.chainback(m_data, NXDN_FACCH1_CRC_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Decoded FACCH1", m_data, NXDN_FACCH1_LENGTH_BYTES); + Utils::dump(2U, "Decoded FACCH1", m_data, NXDN_FACCH1_CRC_LENGTH_BYTES); } // check CRC-12 - bool ret = CRC::checkCRC12(m_data, NXDN_FACCH1_CRC_BITS); + bool ret = CRC::checkCRC12(m_data, NXDN_FACCH1_LENGTH_BITS); if (!ret) { LogError(LOG_NXDN, "FACCH1::decode(), failed CRC-12 check"); return false; @@ -189,32 +191,36 @@ void FACCH1::encode(uint8_t* data, uint32_t offset) const { assert(data != NULL); - uint8_t buffer[NXDN_FACCH1_LENGTH_BYTES]; - ::memset(buffer, 0x00U, NXDN_FACCH1_LENGTH_BYTES); - ::memcpy(buffer, m_data, NXDN_FACCH1_LENGTH_BYTES - 2U); + uint8_t buffer[NXDN_FACCH1_CRC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_FACCH1_CRC_LENGTH_BYTES); + ::memcpy(buffer, m_data, NXDN_FACCH1_CRC_LENGTH_BYTES - 2U); - CRC::addCRC12(buffer, NXDN_FACCH1_CRC_BITS); + CRC::addCRC12(buffer, NXDN_FACCH1_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Encoded FACCH1", buffer, NXDN_FACCH1_LENGTH_BYTES); + Utils::dump(2U, "Encoded FACCH1", buffer, NXDN_FACCH1_CRC_LENGTH_BYTES); } // encode convolution uint8_t convolution[NXDN_FACCH1_FEC_CONV_LENGTH_BYTES]; + ::memset(convolution, 0x00U, NXDN_FACCH1_FEC_CONV_LENGTH_BYTES); + Convolution conv; - conv.encode(buffer, convolution, NXDN_FACCH1_LENGTH_BITS); + conv.encode(buffer, convolution, NXDN_FACCH1_CRC_LENGTH_BITS); #if DEBUG_NXDN_FACCH1 Utils::dump(2U, "FACCH1::encode(), FACCH1 Convolution", convolution, NXDN_FACCH1_FEC_CONV_LENGTH_BYTES); #endif // puncture - uint8_t raw[NXDN_FACCH1_FEC_LENGTH_BYTES]; + uint8_t puncture[NXDN_FACCH1_FEC_LENGTH_BYTES]; + ::memset(puncture, 0x00U, NXDN_FACCH1_FEC_LENGTH_BYTES); + uint32_t n = 0U, index = 0U; for (uint32_t i = 0U; i < NXDN_FACCH1_FEC_CONV_LENGTH_BITS; i++) { if (i != PUNCTURE_LIST[index]) { bool b = READ_BIT(convolution, i); - WRITE_BIT(raw, n, b); + WRITE_BIT(puncture, n, b); n++; } else { index++; @@ -224,7 +230,7 @@ void FACCH1::encode(uint8_t* data, uint32_t offset) const // interleave for (uint32_t i = 0U; i < NXDN_FACCH1_FEC_LENGTH_BITS; i++) { uint32_t n = INTERLEAVE_TABLE[i] + offset; - bool b = READ_BIT(raw, i); + bool b = READ_BIT(puncture, i); WRITE_BIT(data, n, b); } @@ -241,7 +247,7 @@ void FACCH1::getData(uint8_t* data) const { assert(data != NULL); - ::memcpy(data, m_data, NXDN_FACCH1_LENGTH_BYTES - 2U); + ::memcpy(data, m_data, NXDN_FACCH1_CRC_LENGTH_BYTES - 2U); } /// @@ -252,7 +258,7 @@ void FACCH1::setData(const uint8_t* data) { assert(data != NULL); - ::memcpy(m_data, data, NXDN_FACCH1_LENGTH_BYTES - 2U); + ::memcpy(m_data, data, NXDN_FACCH1_CRC_LENGTH_BYTES - 2U); } // --------------------------------------------------------------------------- @@ -265,8 +271,8 @@ void FACCH1::setData(const uint8_t* data) /// void FACCH1::copy(const FACCH1& data) { - m_data = new uint8_t[NXDN_FACCH1_LENGTH_BYTES]; - ::memcpy(m_data, data.m_data, NXDN_FACCH1_LENGTH_BYTES); + m_data = new uint8_t[NXDN_FACCH1_CRC_LENGTH_BYTES]; + ::memcpy(m_data, data.m_data, NXDN_FACCH1_CRC_LENGTH_BYTES); m_verbose = data.m_verbose; } diff --git a/nxdn/channel/LICH.cpp b/nxdn/channel/LICH.cpp index 7be5b6e0..f59565b3 100644 --- a/nxdn/channel/LICH.cpp +++ b/nxdn/channel/LICH.cpp @@ -30,6 +30,7 @@ */ #include "nxdn/NXDNDefines.h" #include "nxdn/channel/LICH.h" +#include "Log.h" using namespace nxdn; using namespace nxdn::channel; @@ -49,10 +50,10 @@ LICH::LICH() : m_rfct(NXDN_LICH_RFCT_RCCH), m_fct(NXDN_LICH_USC_SACCH_NS), m_option(0U), - m_direction(NXDN_LICH_DIRECTION_OUTBOUND), - m_data(NULL) + m_outbound(true), + m_lich(0U) { - m_data = new uint8_t[1U]; + /* stub */ } /// @@ -63,8 +64,8 @@ LICH::LICH(const LICH& data) : m_rfct(NXDN_LICH_RFCT_RCCH), m_fct(NXDN_LICH_USC_SACCH_NS), m_option(0U), - m_direction(NXDN_LICH_DIRECTION_OUTBOUND), - m_data(NULL) + m_outbound(true), + m_lich(0U) { copy(data); } @@ -74,7 +75,7 @@ LICH::LICH(const LICH& data) : /// LICH::~LICH() { - delete[] m_data; + /* stub */ } /// @@ -85,12 +86,12 @@ LICH::~LICH() LICH& LICH::operator=(const LICH& data) { if (&data != this) { - m_data[0U] = data.m_data[0U]; + m_lich = data.m_lich; m_rfct = data.m_rfct; m_fct = data.m_fct; m_option = data.m_option; - m_direction = data.m_direction; + m_outbound = data.m_outbound; } return *this; @@ -108,16 +109,20 @@ bool LICH::decode(const uint8_t* data) uint32_t offset = NXDN_FSW_LENGTH_BITS; for (uint32_t i = 0U; i < (NXDN_LICH_LENGTH_BITS / 2U); i++, offset += 2U) { bool b = READ_BIT(data, offset); - WRITE_BIT(m_data, i, b); + m_lich = (b) ? (m_lich | BIT_MASK_TABLE[(i) & 7]) : (m_lich & ~BIT_MASK_TABLE[(i) & 7]); } +#if DEBUG_NXDN_LICH + LogDebug(LOG_NXDN, "LICH::decode(), m_lich = %02X", m_lich); +#endif + bool newParity = getParity(); - bool origParity = (m_data[0U] & 0x01U) == 0x01U; + bool origParity = (m_lich & 0x01U) == 0x01U; - m_rfct = (m_data[0U] >> 6) & 0x03U; - m_fct = (m_data[0U] >> 4) & 0x03U; - m_option = (m_data[0U] >> 2) & 0x03U; - m_direction = (m_data[0U] >> 1) & 0x01U; + m_rfct = (m_lich >> 6) & 0x03U; + m_fct = (m_lich >> 4) & 0x03U; + m_option = (m_lich >> 2) & 0x03U; + m_outbound = ((m_lich >> 1) & 0x01U) == 0x01U; return origParity == newParity; } @@ -130,27 +135,33 @@ void LICH::encode(uint8_t* data) { assert(data != NULL); - m_data[0U] &= 0x3FU; - m_data[0U] |= (m_rfct << 6) & 0xC0U; + m_lich = 0U; + + m_lich &= 0x3FU; + m_lich |= (m_rfct & 0x03U) << 6; + + m_lich &= 0xCFU; + m_lich |= (m_fct & 0x03U) << 4; - m_data[0U] &= 0xCFU; - m_data[0U] |= (m_fct << 4) & 0x30U; + m_lich &= 0xF3U; + m_lich |= (m_option & 0x03U) << 2; - m_data[0U] &= 0xF3U; - m_data[0U] |= (m_option << 2) & 0x0CU; + m_lich &= 0xFDU; + m_lich |= (m_outbound ? 0x01U : 0x00U) << 1; - m_data[0U] &= 0xFDU; - m_data[0U] |= (m_direction << 1) & 0x02U; +#if DEBUG_NXDN_LICH + LogDebug(LOG_NXDN, "LICH::encode(), m_lich = %02X", m_lich); +#endif bool parity = getParity(); if (parity) - m_data[0U] |= 0x01U; + m_lich |= 0x01U; else - m_data[0U] &= 0xFEU; + m_lich &= 0xFEU; uint32_t offset = NXDN_FSW_LENGTH_BITS; for (uint32_t i = 0U; i < (NXDN_LICH_LENGTH_BITS / 2U); i++) { - bool b = READ_BIT(m_data, i); + bool b = (m_lich & BIT_MASK_TABLE[(i) & 7]); WRITE_BIT(data, offset, b); offset++; WRITE_BIT(data, offset, true); @@ -168,13 +179,12 @@ void LICH::encode(uint8_t* data) /// void LICH::copy(const LICH& data) { - m_data = new uint8_t[1U]; - m_data[0U] = data.m_data[0U]; + m_lich = data.m_lich; - m_rfct = (m_data[0U] >> 6) & 0x03U; - m_fct = (m_data[0U] >> 4) & 0x03U; - m_option = (m_data[0U] >> 2) & 0x03U; - m_direction = (m_data[0U] >> 1) & 0x01U; + m_rfct = (m_lich >> 6) & 0x03U; + m_fct = (m_lich >> 4) & 0x03U; + m_option = (m_lich >> 2) & 0x03U; + m_outbound = ((m_lich >> 1) & 0x01U) == 0x01U; } /// @@ -183,7 +193,7 @@ void LICH::copy(const LICH& data) /// bool LICH::getParity() const { - switch (m_data[0U] & 0xF0U) { + switch (m_lich & 0xF0U) { case 0x80U: case 0xB0U: return true; diff --git a/nxdn/channel/LICH.h b/nxdn/channel/LICH.h index 72b877c5..08a9d0db 100644 --- a/nxdn/channel/LICH.h +++ b/nxdn/channel/LICH.h @@ -67,11 +67,11 @@ namespace nxdn __PROPERTY(uint8_t, fct, FCT); /// Channel Options __PROPERTY(uint8_t, option, Option); - /// Channel Direction - __PROPERTY(uint8_t, direction, Direction); + /// Flag indicating outbound traffic direction + __PROPERTY(bool, outbound, Outbound); private: - uint8_t* m_data; + uint8_t m_lich; /// Internal helper to copy the class. void copy(const LICH& data); diff --git a/nxdn/channel/SACCH.cpp b/nxdn/channel/SACCH.cpp index 5484417e..42e2427e 100644 --- a/nxdn/channel/SACCH.cpp +++ b/nxdn/channel/SACCH.cpp @@ -66,11 +66,12 @@ const uint32_t PUNCTURE_LIST[] = { 5U, 11U, 17U, 23U, 29U, 35U, 41U, 47U, 53U, 5 /// SACCH::SACCH() : m_verbose(false), - m_ran(0U), - m_structure(0U), + m_ran(1U), + m_structure(NXDN_SR_SINGLE), m_data(NULL) { - m_data = new uint8_t[NXDN_SACCH_LENGTH_BYTES]; + m_data = new uint8_t[NXDN_SACCH_CRC_LENGTH_BYTES]; + ::memset(m_data, 0x00U, NXDN_SACCH_CRC_LENGTH_BYTES); } /// @@ -79,8 +80,8 @@ SACCH::SACCH() : /// SACCH::SACCH(const SACCH& data) : m_verbose(false), - m_ran(0U), - m_structure(0U), + m_ran(1U), + m_structure(NXDN_SR_SINGLE), m_data(NULL) { copy(data); @@ -102,7 +103,7 @@ SACCH::~SACCH() SACCH& SACCH::operator=(const SACCH& data) { if (&data != this) { - ::memcpy(m_data, data.m_data, NXDN_SACCH_LENGTH_BYTES); + ::memcpy(m_data, data.m_data, NXDN_SACCH_CRC_LENGTH_BYTES); m_verbose = data.m_verbose; @@ -123,6 +124,7 @@ bool SACCH::decode(const uint8_t* data) assert(data != NULL); uint8_t buffer[NXDN_SACCH_FEC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_SACCH_FEC_LENGTH_BYTES); // deinterleave for (uint32_t i = 0U; i < NXDN_SACCH_FEC_LENGTH_BITS; i++) { @@ -157,21 +159,21 @@ bool SACCH::decode(const uint8_t* data) conv.start(); n = 0U; - for (uint32_t i = 0U; i < (NXDN_SACCH_LENGTH_BITS + 4U); i++) { + for (uint32_t i = 0U; i < (NXDN_SACCH_CRC_LENGTH_BITS + 4U); i++) { uint8_t s0 = puncture[n++]; uint8_t s1 = puncture[n++]; conv.decode(s0, s1); } - conv.chainback(m_data, NXDN_SACCH_LENGTH_BITS); + conv.chainback(m_data, NXDN_SACCH_CRC_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Decoded SACCH", m_data, NXDN_SACCH_LENGTH_BYTES); + Utils::dump(2U, "Decoded SACCH", m_data, NXDN_SACCH_CRC_LENGTH_BYTES); } // check CRC-6 - bool ret = CRC::checkCRC6(m_data, NXDN_SACCH_CRC_BITS); + bool ret = CRC::checkCRC6(m_data, NXDN_SACCH_LENGTH_BITS); if (!ret) { LogError(LOG_NXDN, "SACCH::decode(), failed CRC-6 check"); return false; @@ -191,30 +193,32 @@ void SACCH::encode(uint8_t* data) const { assert(data != NULL); - m_data[0U] &= 0xC0U; - m_data[0U] |= m_ran; + m_data[0U] &= 0xC0U; + m_data[0U] |= m_ran; - m_data[0U] &= 0x3FU; - m_data[0U] |= (m_structure << 6) & 0xC0U; + m_data[0U] &= 0x3FU; + m_data[0U] |= (m_structure << 6) & 0xC0U; - uint8_t buffer[NXDN_SACCH_LENGTH_BYTES]; - ::memset(buffer, 0x00U, NXDN_SACCH_LENGTH_BYTES); + uint8_t buffer[NXDN_SACCH_CRC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_SACCH_CRC_LENGTH_BYTES); - for (uint32_t i = 0U; i < NXDN_SACCH_CRC_BITS; i++) { + for (uint32_t i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) { bool b = READ_BIT(m_data, i); WRITE_BIT(buffer, i, b); } - CRC::addCRC6(buffer, NXDN_SACCH_CRC_BITS); + CRC::addCRC6(buffer, NXDN_SACCH_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Encoded SACCH", buffer, NXDN_SACCH_LENGTH_BYTES); + Utils::dump(2U, "Encoded SACCH", buffer, NXDN_SACCH_CRC_LENGTH_BYTES); } // encode convolution uint8_t convolution[NXDN_SACCH_FEC_CONV_LENGTH_BYTES]; + ::memset(convolution, 0x00U, NXDN_SACCH_FEC_CONV_LENGTH_BYTES); + Convolution conv; - conv.encode(buffer, convolution, NXDN_SACCH_LENGTH_BITS); + conv.encode(buffer, convolution, NXDN_SACCH_CRC_LENGTH_BITS); #if DEBUG_NXDN_SACCH Utils::dump(2U, "SACCH::encode(), SACCH Convolution", convolution, NXDN_SACCH_FEC_CONV_LENGTH_BYTES); @@ -222,6 +226,8 @@ void SACCH::encode(uint8_t* data) const // puncture uint8_t puncture[NXDN_SACCH_FEC_LENGTH_BYTES]; + ::memset(puncture, 0x00U, NXDN_SACCH_FEC_LENGTH_BYTES); + uint32_t n = 0U, index = 0U; for (uint32_t i = 0U; i < NXDN_SACCH_FEC_CONV_LENGTH_BITS; i++) { if (i != PUNCTURE_LIST[index]) { @@ -254,7 +260,7 @@ void SACCH::getData(uint8_t* data) const assert(data != NULL); uint32_t offset = 8U; - for (uint32_t i = 0U; i < (NXDN_SACCH_CRC_BITS - 8); i++, offset++) { + for (uint32_t i = 0U; i < (NXDN_SACCH_LENGTH_BITS - 8); i++, offset++) { bool b = READ_BIT(m_data, offset); WRITE_BIT(data, i, b); } @@ -269,7 +275,7 @@ void SACCH::setData(const uint8_t* data) assert(data != NULL); uint32_t offset = 8U; - for (uint32_t i = 0U; i < (NXDN_SACCH_CRC_BITS - 8); i++, offset++) { + for (uint32_t i = 0U; i < (NXDN_SACCH_LENGTH_BITS - 8); i++, offset++) { bool b = READ_BIT(data, i); WRITE_BIT(m_data, offset, b); } @@ -285,8 +291,8 @@ void SACCH::setData(const uint8_t* data) /// void SACCH::copy(const SACCH& data) { - m_data = new uint8_t[NXDN_SACCH_LENGTH_BYTES]; - ::memcpy(m_data, data.m_data, NXDN_SACCH_LENGTH_BYTES); + m_data = new uint8_t[NXDN_SACCH_CRC_LENGTH_BYTES]; + ::memcpy(m_data, data.m_data, NXDN_SACCH_CRC_LENGTH_BYTES); m_ran = m_data[0U] & 0x3FU; m_structure = (m_data[0U] >> 6) & 0x03U; diff --git a/nxdn/channel/UDCH.cpp b/nxdn/channel/UDCH.cpp index 0f470a1f..61bd769e 100644 --- a/nxdn/channel/UDCH.cpp +++ b/nxdn/channel/UDCH.cpp @@ -98,7 +98,8 @@ UDCH::UDCH() : m_ran(0U), m_data(NULL) { - m_data = new uint8_t[NXDN_UDCH_LENGTH_BYTES]; + m_data = new uint8_t[NXDN_UDCH_CRC_LENGTH_BYTES]; + ::memset(m_data, 0x00U, NXDN_UDCH_CRC_LENGTH_BYTES); } /// @@ -129,7 +130,7 @@ UDCH::~UDCH() UDCH& UDCH::operator=(const UDCH& data) { if (&data != this) { - ::memcpy(m_data, data.m_data, NXDN_UDCH_LENGTH_BYTES); + ::memcpy(m_data, data.m_data, NXDN_UDCH_CRC_LENGTH_BYTES); m_verbose = data.m_verbose; @@ -149,6 +150,7 @@ bool UDCH::decode(const uint8_t* data) assert(data != NULL); uint8_t buffer[NXDN_UDCH_FEC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_UDCH_FEC_LENGTH_BYTES); // deinterleave for (uint32_t i = 0U; i < NXDN_UDCH_FEC_LENGTH_BITS; i++) { @@ -183,21 +185,21 @@ bool UDCH::decode(const uint8_t* data) conv.start(); n = 0U; - for (uint32_t i = 0U; i < (NXDN_UDCH_LENGTH_BITS + 4U); i++) { + for (uint32_t i = 0U; i < (NXDN_UDCH_CRC_LENGTH_BITS + 4U); i++) { uint8_t s0 = puncture[n++]; uint8_t s1 = puncture[n++]; conv.decode(s0, s1); } - conv.chainback(m_data, NXDN_UDCH_LENGTH_BITS); + conv.chainback(m_data, NXDN_UDCH_CRC_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Decoded UDCH", m_data, NXDN_UDCH_LENGTH_BYTES); + Utils::dump(2U, "Decoded UDCH", m_data, NXDN_UDCH_CRC_LENGTH_BYTES); } // check CRC-15 - bool ret = CRC::checkCRC15(m_data, NXDH_UDCH_CRC_BITS); + bool ret = CRC::checkCRC15(m_data, NXDN_UDCH_LENGTH_BITS); if (!ret) { LogError(LOG_NXDN, "UDCH::decode(), failed CRC-15 check"); return false; @@ -218,20 +220,22 @@ void UDCH::encode(uint8_t* data) const m_data[0U] = m_ran; - uint8_t buffer[NXDN_UDCH_LENGTH_BYTES]; - ::memset(buffer, 0x00U, NXDN_UDCH_LENGTH_BYTES); + uint8_t buffer[NXDN_UDCH_CRC_LENGTH_BYTES]; + ::memset(buffer, 0x00U, NXDN_UDCH_CRC_LENGTH_BYTES); ::memcpy(buffer, m_data, 23U); - CRC::addCRC15(buffer, NXDH_UDCH_CRC_BITS); + CRC::addCRC15(buffer, NXDN_UDCH_LENGTH_BITS); if (m_verbose) { - Utils::dump(2U, "Encoded UDCH", m_data, NXDN_UDCH_LENGTH_BYTES); + Utils::dump(2U, "Encoded UDCH", m_data, NXDN_UDCH_CRC_LENGTH_BYTES); } // encode convolution uint8_t convolution[NXDN_UDCH_FEC_CONV_LENGTH_BYTES]; + ::memset(convolution, 0x00U, NXDN_UDCH_FEC_CONV_LENGTH_BYTES); + Convolution conv; - conv.encode(buffer, convolution, NXDN_UDCH_LENGTH_BITS); + conv.encode(buffer, convolution, NXDN_UDCH_CRC_LENGTH_BITS); #if DEBUG_NXDN_UDCH Utils::dump(2U, "UDCH::encode(), UDCH Convolution", convolution, NXDN_UDCH_FEC_CONV_LENGTH_BYTES); @@ -239,6 +243,8 @@ void UDCH::encode(uint8_t* data) const // puncture uint8_t puncture[NXDN_UDCH_FEC_LENGTH_BYTES]; + ::memset(puncture, 0x00U, NXDN_UDCH_FEC_LENGTH_BYTES); + uint32_t n = 0U, index = 0U; for (uint32_t i = 0U; i < NXDN_UDCH_FEC_CONV_LENGTH_BITS; i++) { if (i != PUNCTURE_LIST[index]) { @@ -270,7 +276,7 @@ void UDCH::getData(uint8_t* data) const { assert(data != NULL); - ::memcpy(data, m_data + 1U, 22U); + ::memcpy(data, m_data + 1U, NXDN_RTCH_LC_LENGTH_BYTES); } /// @@ -281,7 +287,7 @@ void UDCH::setData(const uint8_t* data) { assert(data != NULL); - ::memcpy(m_data + 1U, data, 22U); + ::memcpy(m_data + 1U, data, NXDN_RTCH_LC_LENGTH_BYTES); } // --------------------------------------------------------------------------- @@ -294,8 +300,8 @@ void UDCH::setData(const uint8_t* data) /// void UDCH::copy(const UDCH& data) { - m_data = new uint8_t[26U]; - ::memcpy(m_data, data.m_data, 26U); + m_data = new uint8_t[NXDN_UDCH_CRC_LENGTH_BYTES]; + ::memcpy(m_data, data.m_data, NXDN_UDCH_CRC_LENGTH_BYTES); m_ran = m_data[0U] & 0x3FU; } diff --git a/nxdn/lc/RCCH.cpp b/nxdn/lc/RCCH.cpp index 399fb828..5ffd2e6a 100644 --- a/nxdn/lc/RCCH.cpp +++ b/nxdn/lc/RCCH.cpp @@ -91,7 +91,13 @@ RCCH& RCCH::operator=(const RCCH& data) { if (&data != this) { ::memcpy(m_data, data.m_data, NXDN_RCCH_LC_LENGTH_BYTES); - decodeLC(m_data); + + m_verbose = data.m_verbose; + if (m_data != NULL) { + if ((m_data[0] & 0x3FU) != 0U) { + decodeLC(m_data); + } + } } return *this; @@ -101,6 +107,8 @@ RCCH& RCCH::operator=(const RCCH& data) /// Decode call link control data. /// /// +/// +/// /// True, if RCCH was decoded, otherwise false. void RCCH::decode(const uint8_t* data, uint32_t length, uint32_t offset) { @@ -111,10 +119,6 @@ void RCCH::decode(const uint8_t* data, uint32_t length, uint32_t offset) WRITE_BIT(m_data, offset, b); } - if (m_verbose) { - Utils::dump(2U, "Decoded RCCH Data", m_data, NXDN_RCCH_LC_LENGTH_BYTES); - } - decodeLC(m_data); } @@ -134,10 +138,6 @@ void RCCH::encode(uint8_t* data, uint32_t length, uint32_t offset) bool b = READ_BIT(m_data, offset); WRITE_BIT(data, i, b); } - - if (m_verbose) { - Utils::dump(2U, "Encoded RCCH Data", data, length); - } } /// diff --git a/nxdn/lc/RTCH.cpp b/nxdn/lc/RTCH.cpp index 248e58bf..62f7ad3e 100644 --- a/nxdn/lc/RTCH.cpp +++ b/nxdn/lc/RTCH.cpp @@ -123,7 +123,13 @@ RTCH& RTCH::operator=(const RTCH& data) { if (&data != this) { ::memcpy(m_data, data.m_data, NXDN_RTCH_LC_LENGTH_BYTES); - decodeLC(m_data); + + m_verbose = data.m_verbose; + if (m_data != NULL) { + if ((m_data[0] & 0x3FU) != 0U) { + decodeLC(m_data); + } + } } return *this; diff --git a/nxdn/packet/Data.cpp b/nxdn/packet/Data.cpp index a4ef32cb..d252400e 100644 --- a/nxdn/packet/Data.cpp +++ b/nxdn/packet/Data.cpp @@ -193,11 +193,11 @@ bool Data::process(uint8_t option, uint8_t* data, uint32_t len) } // the layer 3 LC data will only be correct if valid is true - uint8_t buffer[NXDN_UDCH_LENGTH_BYTES]; + uint8_t buffer[NXDN_RTCH_LC_LENGTH_BYTES]; udch.getData(buffer); lc::RTCH lc; - lc.decode(buffer, NXDH_UDCH_CRC_BITS); + lc.decode(buffer, NXDN_UDCH_LENGTH_BITS); uint16_t dstId = lc.getDstId(); uint16_t srcId = lc.getSrcId(); bool group = lc.getGroup(); @@ -237,10 +237,10 @@ bool Data::process(uint8_t option, uint8_t* data, uint32_t len) lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_UDCH); lich.setOption(option); - lich.setDirection(!m_nxdn->m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(!m_nxdn->m_duplex ? false : true); lich.encode(data + 2U); - lich.setDirection(NXDN_LICH_DIRECTION_INBOUND); + lich.setOutbound(false); uint8_t type = RTCH_MESSAGE_TYPE_DCALL_DATA; if (validUDCH) { @@ -301,11 +301,11 @@ bool Data::processNetwork(uint8_t option, lc::RTCH& netLC, uint8_t* data, uint32 return false; // The layer3 data will only be correct if valid is true - uint8_t buffer[NXDN_UDCH_LENGTH_BYTES]; + uint8_t buffer[NXDN_RTCH_LC_LENGTH_BYTES]; udch.getData(buffer); lc::RTCH lc; - lc.decode(buffer, NXDH_UDCH_CRC_BITS); + lc.decode(buffer, NXDN_UDCH_LENGTH_BITS); uint16_t dstId = lc.getDstId(); uint16_t srcId = lc.getSrcId(); bool group = lc.getGroup(); @@ -345,7 +345,7 @@ bool Data::processNetwork(uint8_t option, lc::RTCH& netLC, uint8_t* data, uint32 lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_UDCH); lich.setOption(option); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(true); lich.encode(data + 2U); uint8_t type = RTCH_MESSAGE_TYPE_DCALL_DATA; diff --git a/nxdn/packet/Trunk.cpp b/nxdn/packet/Trunk.cpp index 040ed55c..b9f0db0f 100644 --- a/nxdn/packet/Trunk.cpp +++ b/nxdn/packet/Trunk.cpp @@ -163,10 +163,10 @@ bool Trunk::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) m_nxdn->m_queue.clear(); // the layer3 data will only be correct if valid is true - uint8_t buffer[NXDN_CAC_LENGTH_BYTES]; + uint8_t buffer[NXDN_CAC_FRAME_LENGTH_BYTES]; cac.getData(buffer); - m_rfLC.decode(buffer, NXDN_CAC_SHORT_IN_CRC_BITS); + m_rfLC.decode(buffer, NXDN_RCCH_CAC_LC_SHORT_LENGTH_BITS); uint16_t srcId = m_rfLC.getSrcId(); uint16_t dstId = m_rfLC.getDstId(); @@ -388,15 +388,16 @@ void Trunk::writeRF_Message(bool noNetwork, bool clearBeforeWrite) lich.setRFCT(NXDN_LICH_RFCT_RCCH); lich.setFCT(NXDN_LICH_CAC_OUTBOUND); lich.setOption(NXDN_LICH_DATA_NORMAL); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(true); lich.encode(data + 2U); uint8_t buffer[NXDN_RCCH_LC_LENGTH_BYTES]; ::memset(buffer, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES); - m_rfLC.encode(buffer, NXDN_CAC_OUT_CRC_BITS); + m_rfLC.encode(buffer, NXDN_RCCH_LC_LENGTH_BITS); channel::CAC cac; + cac.setVerbose(m_dumpRCCH); cac.setRAN(m_nxdn->m_ran); cac.setData(buffer); cac.encode(data + 2U); @@ -687,18 +688,20 @@ void Trunk::writeRF_CC_Message_Site_Info() channel::LICH lich; lich.setRFCT(NXDN_LICH_RFCT_RCCH); lich.setFCT(NXDN_LICH_CAC_OUTBOUND); - lich.setOption(NXDN_LICH_DATA_NORMAL); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOption(NXDN_LICH_DATA_COMMON); + lich.setOutbound(true); lich.encode(data + 2U); uint8_t buffer[NXDN_RCCH_LC_LENGTH_BYTES]; ::memset(buffer, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES); m_rfLC.setMessageType(RCCH_MESSAGE_TYPE_SITE_INFO); - m_rfLC.encode(buffer, NXDN_CAC_OUT_CRC_BITS); + m_rfLC.encode(buffer, NXDN_RCCH_LC_LENGTH_BITS); channel::CAC cac; + cac.setVerbose(m_dumpRCCH); cac.setRAN(m_nxdn->m_ran); + cac.setStructure(NXDN_SR_RCCH_HEAD_SINGLE); cac.setData(buffer); cac.encode(data + 2U); @@ -730,17 +733,19 @@ void Trunk::writeRF_CC_Message_Service_Info() lich.setRFCT(NXDN_LICH_RFCT_RCCH); lich.setFCT(NXDN_LICH_CAC_OUTBOUND); lich.setOption(NXDN_LICH_DATA_NORMAL); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(true); lich.encode(data + 2U); uint8_t buffer[NXDN_RCCH_LC_LENGTH_BYTES]; ::memset(buffer, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES); m_rfLC.setMessageType(MESSAGE_TYPE_SRV_INFO); - m_rfLC.encode(buffer, NXDN_CAC_OUT_CRC_BITS); + m_rfLC.encode(buffer, NXDN_RCCH_LC_LENGTH_BITS); channel::CAC cac; + cac.setVerbose(m_dumpRCCH); cac.setRAN(m_nxdn->m_ran); + cac.setStructure(NXDN_SR_RCCH_SINGLE); cac.setData(buffer); cac.encode(data + 2U); diff --git a/nxdn/packet/Voice.cpp b/nxdn/packet/Voice.cpp index 8565a66c..76e44a55 100644 --- a/nxdn/packet/Voice.cpp +++ b/nxdn/packet/Voice.cpp @@ -247,7 +247,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_SACCH_NS); lich.setOption(NXDN_LICH_STEAL_FACCH); - lich.setDirection(!m_nxdn->m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(!m_nxdn->m_duplex ? false : true); lich.encode(data + 2U); // generate the SACCH @@ -424,10 +424,10 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_SACCH_NS); lich.setOption(NXDN_LICH_STEAL_FACCH); - lich.setDirection(!m_nxdn->m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(!m_nxdn->m_duplex ? false : true); lich.encode(start + 2U); - lich.setDirection(NXDN_LICH_DIRECTION_INBOUND); + lich.setOutbound(false); // generate the SACCH channel::SACCH sacch; @@ -436,7 +436,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) sacch.setStructure(NXDN_SR_SINGLE); sacch.encode(start + 2U); - uint8_t message[22U]; + uint8_t message[NXDN_RTCH_LC_LENGTH_BYTES]; m_nxdn->m_rfLC.getData(message); facch.setData(message); @@ -465,10 +465,10 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_SACCH_SS); lich.setOption(option); - lich.setDirection(!m_nxdn->m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(!m_nxdn->m_duplex ? false : true); lich.encode(data + 2U); - lich.setDirection(NXDN_LICH_DIRECTION_INBOUND); + lich.setOutbound(false); // regenerate SACCH if it's valid channel::SACCH sacch; @@ -672,7 +672,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_SACCH_NS); lich.setOption(NXDN_LICH_STEAL_FACCH); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(true); lich.encode(data + 2U); // generate the SACCH @@ -827,7 +827,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_SACCH_NS); lich.setOption(NXDN_LICH_STEAL_FACCH); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(true); lich.encode(start + 2U); // generate the SACCH @@ -837,7 +837,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t sacch.setStructure(NXDN_SR_SINGLE); sacch.encode(start + 2U); - uint8_t message[22U]; + uint8_t message[NXDN_RTCH_LC_LENGTH_BYTES]; m_nxdn->m_rfLC.getData(message); facch.setData(message); @@ -864,7 +864,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t lich.setRFCT(NXDN_LICH_RFCT_RDCH); lich.setFCT(NXDN_LICH_USC_SACCH_SS); lich.setOption(option); - lich.setDirection(NXDN_LICH_DIRECTION_OUTBOUND); + lich.setOutbound(true); lich.encode(data + 2U); // regenerate SACCH if it's valid