correct bad LICH handling for RCCH type packets; correct some bad PacketInformation handling;

r05a06_dev
Bryan Biedenkapp 4 days ago
parent 9662385249
commit e4bc909972

@ -160,11 +160,8 @@ void LICH::copy(const LICH& data)
bool LICH::getParity() const
{
switch (m_lich & 0xF0U) {
case 0x80U:
case 0xB0U:
return true;
default:
return false;
}
// TS 1-A section 4.5.3 defines even parity over the four most
// significant LICH information bits (RFCT and FCT).
const uint8_t parityBits = (m_lich >> 4U) & 0x0FU;
return ((parityBits >> 3U) ^ (parityBits >> 2U) ^ (parityBits >> 1U) ^ parityBits) & 0x01U;
}

@ -112,8 +112,8 @@ void PacketInformation::encode(const uint8_t messageType, uint8_t* data)
break;
case MessageType::RTCH_DCALL_ACK:
{
data[0U] = (m_rspClass & 0x03U << 4) + // Response Class
(m_rspType & 0x07U << 1); // Response Type
data[0U] = ((m_rspClass & 0x03U) << 4) | // Response Class
((m_rspType & 0x07U) << 1); // Response Type
bool highFragCount = (m_fragmentCount & 0x100U) == 0x100U;
data[0U] += (highFragCount ? 0x01U : 0x00U); // Fragment Count - bit 8

@ -225,3 +225,30 @@ TEST_CASE("LICH rejects invalid parity", "[nxdn][lich]") {
LICH decoded;
REQUIRE_FALSE(decoded.decode(data));
}
TEST_CASE("LICH uses even parity over every RFCT and FCT combination", "[nxdn][lich][golden]") {
for (uint8_t rfct = 0U; rfct < 4U; rfct++) {
for (uint8_t fct = 0U; fct < 4U; fct++) {
uint8_t data[NXDN_FRAME_LENGTH_BYTES + 2U] = {};
LICH lich;
lich.setRFCT(static_cast<RFChannelType::E>(rfct));
lich.setFCT(static_cast<FuncChannelType::E>(fct));
lich.setOption(ChOption::DATA_NORMAL);
lich.setOutbound(false);
lich.encode(data);
uint8_t encodedLICH[1U] = {};
for (uint32_t bit = 0U; bit < 8U; bit++) {
const uint32_t offset = NXDN_FSW_LENGTH_BITS + bit * 2U;
WRITE_BIT(encodedLICH, bit, READ_BIT(data, offset));
REQUIRE(READ_BIT(data, offset + 1U));
}
const uint8_t highNibble = static_cast<uint8_t>((rfct << 2U) | fct);
const bool expectedParity = ((highNibble >> 3U) ^ (highNibble >> 2U) ^
(highNibble >> 1U) ^ highNibble) & 0x01U;
REQUIRE((encodedLICH[0U] & 0x01U) == (expectedParity ? 0x01U : 0x00U));
}
}
}

@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - Test Suite
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2026 Bryan Biedenkapp, N2PLL
*/
#include <catch2/catch_test_macros.hpp>
#include "common/nxdn/NXDNDefines.h"
#include "common/nxdn/lc/PacketInformation.h"
using namespace nxdn::defines;
using namespace nxdn::lc;
TEST_CASE("PacketInformation encodes DCALL_ACK response fields", "[nxdn][packet-information][golden]")
{
PacketInformation packet;
uint8_t data[2U] = {};
SECTION("ACK receive success") {
packet.setResponseClass(PDUResponseClass::ACK);
packet.setResponseType(0x01U);
packet.setFragmentCount(0x000U);
packet.encode(MessageType::RTCH_DCALL_ACK, data);
REQUIRE(data[0U] == 0x02U);
REQUIRE(data[1U] == 0x00U);
}
SECTION("NACK abort with maximum fragment count") {
packet.setResponseClass(PDUResponseClass::NACK);
packet.setResponseType(0x03U);
packet.setFragmentCount(0x1FFU);
packet.encode(MessageType::RTCH_DCALL_ACK, data);
REQUIRE(data[0U] == 0x37U);
REQUIRE(data[1U] == 0xFFU);
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.