From a78199c6a2d76396632f5c7bff06675c88b03983 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Mon, 3 Oct 2022 16:12:05 -0400 Subject: [PATCH] add logic to check the NXDN FSW sync word; change NXDN convolution decoder to report boolean status for decode fail instead of code assert; use a buffer for LICH instead of attempting to direct write a byte (slightly more code at the expense of less inaccuracy); handle failed convolutional decode; set verbosity flag in appropriate places; fix data offsets when encoding/decoding FACCH; --- nxdn/Control.cpp | 37 ++++++++++++-- nxdn/Convolution.cpp | 11 ++++- nxdn/Convolution.h | 3 +- nxdn/channel/CAC.cpp | 7 ++- nxdn/channel/FACCH1.cpp | 5 +- nxdn/channel/LICH.cpp | 14 +++++- nxdn/channel/SACCH.cpp | 11 ++++- nxdn/channel/UDCH.cpp | 5 +- nxdn/packet/Data.cpp | 4 ++ nxdn/packet/Voice.cpp | 104 ++++++++++++++++++++++++---------------- 10 files changed, 147 insertions(+), 54 deletions(-) diff --git a/nxdn/Control.cpp b/nxdn/Control.cpp index 13ccd0df..362ca595 100644 --- a/nxdn/Control.cpp +++ b/nxdn/Control.cpp @@ -53,6 +53,8 @@ using namespace nxdn::packet; // Constants // --------------------------------------------------------------------------- +const uint8_t MAX_SYNC_BYTES_ERRS = 0U; + const uint8_t SCRAMBLER[] = { 0x00U, 0x00U, 0x00U, 0x82U, 0xA0U, 0x88U, 0x8AU, 0x00U, 0xA2U, 0xA8U, 0x82U, 0x8AU, 0x82U, 0x02U, 0x20U, 0x08U, 0x8AU, 0x20U, 0xAAU, 0xA2U, 0x82U, 0x08U, 0x22U, 0x8AU, 0xAAU, 0x08U, 0x28U, 0x88U, @@ -290,6 +292,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len) assert(data != NULL); uint8_t type = data[0U]; + bool sync = data[1U] == 0x01U; if (type == modem::TAG_LOST && m_rfState == RS_RF_AUDIO) { if (m_rssi != 0U) { @@ -348,6 +351,32 @@ bool Control::processFrame(uint8_t* data, uint32_t len) m_rssiCount++; } + if (!sync && m_rfState == RS_RF_LISTENING) { + uint8_t syncBytes[NXDN_FSW_BYTES_LENGTH]; + ::memcpy(syncBytes, data + 2U, NXDN_FSW_BYTES_LENGTH); + + uint8_t errs = 0U; + for (uint8_t i = 0U; i < NXDN_FSW_BYTES_LENGTH; i++) + errs += Utils::countBits8(syncBytes[i] ^ NXDN_FSW_BYTES[i]); + + if (errs >= MAX_SYNC_BYTES_ERRS) { + LogWarning(LOG_RF, "NXDN, possible sync word rejected, errs = %u, sync word = %02X %02X %02X", errs, + syncBytes[0U], syncBytes[1U], syncBytes[2U]); + + return false; + } + else { + LogWarning(LOG_RF, "NXDN, possible sync word, errs = %u, sync word = %02X %02X %02X", errs, + syncBytes[0U], syncBytes[1U], syncBytes[2U]); + + sync = true; // we found a completly valid sync with no errors... + } + } + + if (sync && m_debug) { + Utils::symbols("!!! *Rx NXDN", data + 2U, len - 2U); + } + scrambler(data + 2U); channel::LICH lich; @@ -799,10 +828,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]; + + if (m_debug) { + Utils::symbols("!!! *NXDN (Scrambled)", data, NXDN_FRAME_LENGTH_BYTES); + } } diff --git a/nxdn/Convolution.cpp b/nxdn/Convolution.cpp index 536f5fd9..e26d0b98 100644 --- a/nxdn/Convolution.cpp +++ b/nxdn/Convolution.cpp @@ -12,6 +12,7 @@ // /* * Copyright (C) 2009-2016,2018,2021 by Jonathan Naylor G4KLX +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +29,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "nxdn/Convolution.h" +#include "Log.h" +#include "Utils.h" using namespace nxdn; @@ -127,7 +130,7 @@ uint32_t Convolution::chainback(uint8_t* out, uint32_t nBits) /// /// /// -void Convolution::decode(uint8_t s0, uint8_t s1) +bool Convolution::decode(uint8_t s0, uint8_t s1) { *m_dp = 0U; @@ -151,11 +154,15 @@ void Convolution::decode(uint8_t s0, uint8_t s1) ++m_dp; - assert((m_dp - m_decisions) <= 300); + if ((m_dp - m_decisions) > 300) { + return false; + } uint16_t* tmp = m_oldMetrics; m_oldMetrics = m_newMetrics; m_newMetrics = tmp; + + return true; } /// diff --git a/nxdn/Convolution.h b/nxdn/Convolution.h index 42431cc2..b85243a7 100644 --- a/nxdn/Convolution.h +++ b/nxdn/Convolution.h @@ -12,6 +12,7 @@ // /* * Copyright (C) 2015,2016,2018,2021 by Jonathan Naylor G4KLX +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,7 +55,7 @@ namespace nxdn uint32_t chainback(uint8_t* out, uint32_t nBits); /// - void decode(uint8_t s0, uint8_t s1); + bool decode(uint8_t s0, uint8_t s1); /// void encode(const uint8_t* in, uint8_t* out, uint32_t nBits) const; diff --git a/nxdn/channel/CAC.cpp b/nxdn/channel/CAC.cpp index a7e3467c..d6b0cd96 100644 --- a/nxdn/channel/CAC.cpp +++ b/nxdn/channel/CAC.cpp @@ -216,7 +216,10 @@ bool CAC::decode(const uint8_t* data) uint8_t s0 = buffer[n++]; uint8_t s1 = buffer[n++]; - conv.decode(s0, s1); + if (!conv.decode(s0, s1)) { + LogError(LOG_NXDN, "CAC::decode(), failed to decode convolution"); + return false; + } } conv.chainback(m_data, NXDN_CAC_SHORT_CRC_LENGTH_BITS); @@ -228,7 +231,7 @@ bool CAC::decode(const uint8_t* data) // check CRC-16 bool ret = CRC::checkCRC16(m_data, NXDN_CAC_SHORT_LENGTH_BITS); if (!ret) { - LogError(LOG_NXDN, "SACCH::decode(), failed CRC-6 check"); + LogError(LOG_NXDN, "CAC::decode(), failed CRC-6 check"); return false; } diff --git a/nxdn/channel/FACCH1.cpp b/nxdn/channel/FACCH1.cpp index e40fa49a..68fd1152 100644 --- a/nxdn/channel/FACCH1.cpp +++ b/nxdn/channel/FACCH1.cpp @@ -163,7 +163,10 @@ bool FACCH1::decode(const uint8_t* data, uint32_t offset) uint8_t s0 = puncture[n++]; uint8_t s1 = puncture[n++]; - conv.decode(s0, s1); + if (!conv.decode(s0, s1)) { + LogError(LOG_NXDN, "FACCH1::decode(), failed to decode convolution"); + return false; + } } conv.chainback(m_data, NXDN_FACCH1_CRC_LENGTH_BITS); diff --git a/nxdn/channel/LICH.cpp b/nxdn/channel/LICH.cpp index f59565b3..c8dff28d 100644 --- a/nxdn/channel/LICH.cpp +++ b/nxdn/channel/LICH.cpp @@ -106,12 +106,17 @@ bool LICH::decode(const uint8_t* data) { assert(data != NULL); + uint8_t lich[1U]; + ::memset(lich, 0x00U, 1U); + 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); - m_lich = (b) ? (m_lich | BIT_MASK_TABLE[(i) & 7]) : (m_lich & ~BIT_MASK_TABLE[(i) & 7]); + WRITE_BIT(lich, i, b); } + m_lich = lich[0U]; + #if DEBUG_NXDN_LICH LogDebug(LOG_NXDN, "LICH::decode(), m_lich = %02X", m_lich); #endif @@ -159,9 +164,14 @@ void LICH::encode(uint8_t* data) else m_lich &= 0xFEU; + uint8_t lich[1U]; + ::memset(lich, 0x00U, 1U); + + lich[0U] = m_lich; + uint32_t offset = NXDN_FSW_LENGTH_BITS; for (uint32_t i = 0U; i < (NXDN_LICH_LENGTH_BITS / 2U); i++) { - bool b = (m_lich & BIT_MASK_TABLE[(i) & 7]); + bool b = READ_BIT(lich, i); WRITE_BIT(data, offset, b); offset++; WRITE_BIT(data, offset, true); diff --git a/nxdn/channel/SACCH.cpp b/nxdn/channel/SACCH.cpp index 42e2427e..e1af5d2a 100644 --- a/nxdn/channel/SACCH.cpp +++ b/nxdn/channel/SACCH.cpp @@ -139,6 +139,8 @@ bool SACCH::decode(const uint8_t* data) // depuncture uint8_t puncture[90U]; + ::memset(puncture, 0x00U, 90U); + uint32_t n = 0U, index = 0U; for (uint32_t i = 0U; i < NXDN_SACCH_FEC_LENGTH_BITS; i++) { if (n == PUNCTURE_LIST[index]) { @@ -154,6 +156,10 @@ bool SACCH::decode(const uint8_t* data) puncture[n++] = 0U; } +#if DEBUG_NXDN_SACCH + Utils::dump(2U, "SACCH::decode(), SACCH Puncture List", puncture, 90U); +#endif + // decode convolution Convolution conv; conv.start(); @@ -163,7 +169,10 @@ bool SACCH::decode(const uint8_t* data) uint8_t s0 = puncture[n++]; uint8_t s1 = puncture[n++]; - conv.decode(s0, s1); + if (!conv.decode(s0, s1)) { + LogError(LOG_NXDN, "SACCH::decode(), failed to decode convolution"); + return false; + } } conv.chainback(m_data, NXDN_SACCH_CRC_LENGTH_BITS); diff --git a/nxdn/channel/UDCH.cpp b/nxdn/channel/UDCH.cpp index 61bd769e..87442a59 100644 --- a/nxdn/channel/UDCH.cpp +++ b/nxdn/channel/UDCH.cpp @@ -189,7 +189,10 @@ bool UDCH::decode(const uint8_t* data) uint8_t s0 = puncture[n++]; uint8_t s1 = puncture[n++]; - conv.decode(s0, s1); + if (!conv.decode(s0, s1)) { + LogError(LOG_NXDN, "UDCH::decode(), failed to decode convolution"); + return false; + } } conv.chainback(m_data, NXDN_UDCH_CRC_LENGTH_BITS); diff --git a/nxdn/packet/Data.cpp b/nxdn/packet/Data.cpp index d252400e..36974283 100644 --- a/nxdn/packet/Data.cpp +++ b/nxdn/packet/Data.cpp @@ -182,6 +182,7 @@ bool Data::process(uint8_t option, uint8_t* data, uint32_t len) assert(data != NULL); channel::UDCH udch; + udch.setVerbose(m_verbose); bool validUDCH = udch.decode(data + 2U); if (m_nxdn->m_rfState == RS_RF_LISTENING && !validUDCH) return false; @@ -197,6 +198,7 @@ bool Data::process(uint8_t option, uint8_t* data, uint32_t len) udch.getData(buffer); lc::RTCH lc; + lc.setVerbose(m_verbose); lc.decode(buffer, NXDN_UDCH_LENGTH_BITS); uint16_t dstId = lc.getDstId(); uint16_t srcId = lc.getSrcId(); @@ -296,6 +298,7 @@ bool Data::processNetwork(uint8_t option, lc::RTCH& netLC, uint8_t* data, uint32 } channel::UDCH udch; + udch.setVerbose(m_verbose); bool validUDCH = udch.decode(data + 2U); if (m_nxdn->m_netState == RS_NET_IDLE && !validUDCH) return false; @@ -305,6 +308,7 @@ bool Data::processNetwork(uint8_t option, lc::RTCH& netLC, uint8_t* data, uint32 udch.getData(buffer); lc::RTCH lc; + lc.setVerbose(m_verbose); lc.decode(buffer, NXDN_UDCH_LENGTH_BITS); uint16_t dstId = lc.getDstId(); uint16_t srcId = lc.getSrcId(); diff --git a/nxdn/packet/Voice.cpp b/nxdn/packet/Voice.cpp index 9881b62e..0b272c7c 100644 --- a/nxdn/packet/Voice.cpp +++ b/nxdn/packet/Voice.cpp @@ -189,6 +189,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) assert(data != NULL); channel::SACCH sacch; + sacch.setVerbose(m_verbose); bool valid = sacch.decode(data + 2U); if (valid) { uint8_t ran = sacch.getRAN(); @@ -201,9 +202,10 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) if (fct == NXDN_LICH_USC_SACCH_NS) { // the SACCH on a non-superblock frame is usually an idle and not interesting apart from the RAN. channel::FACCH1 facch; - bool valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch.setVerbose(m_verbose); + bool valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (!valid) - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); if (!valid) return false; @@ -211,7 +213,8 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) facch.getData(buffer); lc::RTCH lc; - lc.decode(buffer, NXDN_FACCH1_LENGTH_BITS); + lc.setVerbose(m_verbose); + lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS); uint16_t dstId = lc.getDstId(); uint16_t srcId = lc.getSrcId(); bool group = lc.getGroup(); @@ -252,13 +255,14 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) // generate the SACCH channel::SACCH sacch; + sacch.setVerbose(m_verbose); sacch.setData(SACCH_IDLE); sacch.setRAN(m_nxdn->m_ran); sacch.setStructure(NXDN_SR_SINGLE); sacch.encode(data + 2U); - facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); - facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); m_nxdn->scrambler(data + 2U); @@ -311,18 +315,19 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) } else { if (m_nxdn->m_rfState == RS_RF_LISTENING) { channel::FACCH1 facch; + facch.setVerbose(m_verbose); bool valid = false; switch (option) { case NXDN_LICH_STEAL_FACCH: - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (!valid) - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); break; case NXDN_LICH_STEAL_FACCH1_1: - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); break; case NXDN_LICH_STEAL_FACCH1_2: - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); break; default: break; @@ -334,7 +339,8 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) facch.getData(buffer); lc::RTCH lc; - lc.decode(buffer, NXDN_FACCH1_LENGTH_BITS); + lc.setVerbose(m_verbose); + lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS); hasInfo = lc.getMessageType() == RTCH_MESSAGE_TYPE_VCALL; if (!hasInfo) @@ -431,6 +437,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) // generate the SACCH channel::SACCH sacch; + sacch.setVerbose(m_verbose); sacch.setData(SACCH_IDLE); sacch.setRAN(m_nxdn->m_ran); sacch.setStructure(NXDN_SR_SINGLE); @@ -440,8 +447,8 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) m_nxdn->m_rfLC.encode(buffer, NXDN_RTCH_LC_LENGTH_BITS); facch.setData(buffer); - facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); - facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); + facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); m_nxdn->scrambler(start + 2U); @@ -472,6 +479,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) // regenerate SACCH if it's valid channel::SACCH sacch; + sacch.setVerbose(m_verbose); bool validSACCH = sacch.decode(data + 2U); if (validSACCH) { sacch.setRAN(m_nxdn->m_ran); @@ -510,9 +518,10 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) } } else if (option == NXDN_LICH_STEAL_FACCH1_1) { channel::FACCH1 facch1; - bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch1.setVerbose(m_verbose); + bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (valid) - facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); edac::AMBEFEC ambe; @@ -565,19 +574,22 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) } channel::FACCH1 facch1; - bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch1.setVerbose(m_verbose); + bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); if (valid) - facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); } else { channel::FACCH1 facch11; - bool valid1 = facch11.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch11.setVerbose(m_verbose); + bool valid1 = facch11.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (valid1) - facch11.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch11.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); channel::FACCH1 facch12; - bool valid2 = facch12.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch12.setVerbose(m_verbose); + bool valid2 = facch12.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); if (valid2) - facch12.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch12.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); } data[0U] = modem::TAG_DATA; @@ -621,14 +633,16 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t } channel::SACCH sacch; + sacch.setVerbose(m_verbose); sacch.decode(data + 2U); if (fct == NXDN_LICH_USC_SACCH_NS) { // the SACCH on a non-superblock frame is usually an idle and not interesting apart from the RAN. channel::FACCH1 facch; - bool valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch.setVerbose(m_verbose); + bool valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (!valid) - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); if (!valid) return false; @@ -636,7 +650,8 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t facch.getData(buffer); lc::RTCH lc; - lc.decode(buffer, NXDN_FACCH1_LENGTH_BITS); + lc.setVerbose(m_verbose); + lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS); uint16_t dstId = lc.getDstId(); uint16_t srcId = lc.getSrcId(); bool group = lc.getGroup(); @@ -677,13 +692,14 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t // generate the SACCH channel::SACCH sacch; + sacch.setVerbose(m_verbose); sacch.setData(SACCH_IDLE); sacch.setRAN(m_nxdn->m_ran); sacch.setStructure(NXDN_SR_SINGLE); sacch.encode(data + 2U); - facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); - facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); m_nxdn->scrambler(data + 2U); @@ -719,18 +735,19 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t } else { if (m_nxdn->m_netState == RS_NET_IDLE) { channel::FACCH1 facch; + facch.setVerbose(m_verbose); bool valid = false; switch (option) { case NXDN_LICH_STEAL_FACCH: - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (!valid) - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); break; case NXDN_LICH_STEAL_FACCH1_1: - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); break; case NXDN_LICH_STEAL_FACCH1_2: - valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); break; default: break; @@ -742,7 +759,8 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t facch.getData(buffer); lc::RTCH lc; - lc.decode(buffer, NXDN_FACCH1_LENGTH_BITS); + lc.setVerbose(m_verbose); + lc.decode(buffer, NXDN_FACCH1_FEC_LENGTH_BITS); hasInfo = lc.getMessageType() == RTCH_MESSAGE_TYPE_VCALL; if (!hasInfo) @@ -832,6 +850,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t // generate the SACCH channel::SACCH sacch; + sacch.setVerbose(m_verbose); sacch.setData(SACCH_IDLE); sacch.setRAN(m_nxdn->m_ran); sacch.setStructure(NXDN_SR_SINGLE); @@ -841,8 +860,8 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t m_nxdn->m_rfLC.encode(buffer, NXDN_RTCH_LC_LENGTH_BITS); facch.setData(buffer); - facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); - facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); + facch.encode(start + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); m_nxdn->scrambler(start + 2U); @@ -869,6 +888,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t // regenerate SACCH if it's valid channel::SACCH sacch; + sacch.setVerbose(m_verbose); bool validSACCH = sacch.decode(data + 2U); if (validSACCH) { sacch.setRAN(m_nxdn->m_ran); @@ -894,9 +914,10 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t } } else if (option == NXDN_LICH_STEAL_FACCH1_1) { channel::FACCH1 facch1; - bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch1.setVerbose(m_verbose); + bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (valid) - facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); edac::AMBEFEC ambe; @@ -926,19 +947,22 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t LogMessage(LOG_NET, "NXDN, " NXDN_RTCH_MSG_TYPE_VCALL ", audio, errs = %u/94 (%.1f%%)", errors, float(errors) / 0.94F); } channel::FACCH1 facch1; - bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch1.setVerbose(m_verbose); + bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); if (valid) - facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); } else { channel::FACCH1 facch11; - bool valid1 = facch11.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch11.setVerbose(m_verbose); + bool valid1 = facch11.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); if (valid1) - facch11.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch11.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS); channel::FACCH1 facch12; - bool valid2 = facch12.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch12.setVerbose(m_verbose); + bool valid2 = facch12.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); if (valid2) - facch12.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + facch12.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS + NXDN_FACCH1_FEC_LENGTH_BITS); } data[0U] = modem::TAG_DATA;