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;

2.0-maint
Bryan Biedenkapp 3 years ago
parent 82be3e643b
commit a78199c6a2

@ -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);
}
}

@ -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)
/// </summary>
/// <param name="s0"></param>
/// <param name="s1"></param>
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;
}
/// <summary>

@ -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);
/// <summary></summary>
void decode(uint8_t s0, uint8_t s1);
bool decode(uint8_t s0, uint8_t s1);
/// <summary></summary>
void encode(const uint8_t* in, uint8_t* out, uint32_t nBits) const;

@ -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;
}

@ -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);

@ -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);

@ -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);

@ -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);

@ -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();

@ -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;

Loading…
Cancel
Save

Powered by TurnKey Linux.