From 24082b9652547805c38efcc78d9a0393ee424446 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Fri, 12 Apr 2024 23:19:28 -0400 Subject: [PATCH] P25 data (#52) NOTE: this does not indicate full P25 data support as working yet; this commit refactors a lot of the baseline PDU handling code, and better handles both confirmed and unconfirmed PDU data blocks, there is still some more work to do, I just didn't want p25_data to start getting overly out of sync with master. * rework modem protocol to support variable length frames up to 64k; refactor P25 PDU handling to support TIA-102 minimum 512 byte frames; * fix PDU length its 512 bytes not 500; ignore instead of report invalid modem frames; add double length checking to HostSetup; * add support to send P25 long frames to the modem; * adjust FIFO size to 522 (fits a single PDU frame); remove extra debug displays; match fixed FIFO sizes between modem and host; * correct weird inverted CRC-9 that sometimes happen; * ensure netPDU is reset at the beginning of a network data call; fix lengh used by data block dumping; * fix some buffer lengths; --- configs/config.example.yml | 2 +- src/common/edac/CRC.cpp | 76 +++++-------- src/common/edac/CRC.h | 9 +- src/common/p25/P25Defines.h | 7 +- src/common/p25/data/DataBlock.cpp | 34 +++++- src/fw/hotspot | 2 +- src/fw/modem | 2 +- src/host/Host.Config.cpp | 16 +++ src/host/Host.P25.cpp | 2 +- src/host/modem/Modem.cpp | 132 +++++++++++++---------- src/host/modem/Modem.h | 11 +- src/host/modem/port/ModemNullPort.cpp | 10 +- src/host/p25/packet/ControlSignaling.cpp | 14 +-- src/host/p25/packet/Data.cpp | 89 +++++++-------- src/host/setup/HostSetup.cpp | 79 +++++++++++--- 15 files changed, 281 insertions(+), 204 deletions(-) diff --git a/configs/config.example.yml b/configs/config.example.yml index 6484d1ef..a933b111 100644 --- a/configs/config.example.yml +++ b/configs/config.example.yml @@ -473,7 +473,7 @@ system: # Size (in bytes) of the DMR transmit FIFO buffer. dmrFifoLength: 505 # Size (in bytes) of the P25 transmit FIFO buffer. - p25FifoLength: 442 + p25FifoLength: 522 # Size (in bytes) of the NXDN transmit FIFO buffer. nxdnFifoLength: 538 diff --git a/src/common/edac/CRC.cpp b/src/common/edac/CRC.cpp index a72de316..760f6582 100644 --- a/src/common/edac/CRC.cpp +++ b/src/common/edac/CRC.cpp @@ -9,7 +9,7 @@ * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX -* Copyright (C) 2018,2022 Bryan Biedenkapp, N2PLL +* Copyright (C) 2018,2022,2024 Bryan Biedenkapp, N2PLL * */ #include "Defines.h" @@ -49,22 +49,6 @@ const uint8_t CRC8_TABLE[] = { 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3, 0x01 }; -const uint16_t CRC9_TABLE[] = { - 0x1E7U, 0x1F3U, 0x1F9U, 0x1FCU, 0x0D2U, 0x045U, 0x122U, 0x0BDU, 0x15EU, 0x083, - 0x141U, 0x1A0U, 0x0FCU, 0x052U, 0x005U, 0x102U, 0x0ADU, 0x156U, 0x087U, 0x143, - 0x1A1U, 0x1D0U, 0x0C4U, 0x04EU, 0x00BU, 0x105U, 0x182U, 0x0EDU, 0x176U, 0x097, - 0x14BU, 0x1A5U, 0x1D2U, 0x0C5U, 0x162U, 0x09DU, 0x14EU, 0x08BU, 0x145U, 0x1A2, - 0x0FDU, 0x17EU, 0x093U, 0x149U, 0x1A4U, 0x0FEU, 0x053U, 0x129U, 0x194U, 0x0E6, - 0x05FU, 0x12FU, 0x197U, 0x1CBU, 0x1E5U, 0x1F2U, 0x0D5U, 0x16AU, 0x099U, 0x14C, - 0x08AU, 0x069U, 0x134U, 0x0B6U, 0x077U, 0x13BU, 0x19DU, 0x1CEU, 0x0CBU, 0x165, - 0x1B2U, 0x0F5U, 0x17AU, 0x091U, 0x148U, 0x088U, 0x068U, 0x018U, 0x020U, 0x03C, - 0x032U, 0x035U, 0x11AU, 0x0A1U, 0x150U, 0x084U, 0x06EU, 0x01BU, 0x10DU, 0x186, - 0x0EFU, 0x177U, 0x1BBU, 0x1DDU, 0x1EEU, 0x0DBU, 0x16DU, 0x1B6U, 0x0F7U, 0x17B, - 0x1BDU, 0x1DEU, 0x0C3U, 0x161U, 0x1B0U, 0x0F4U, 0x056U, 0x007U, 0x103U, 0x181, - 0x1C0U, 0x0CCU, 0x04AU, 0x009U, 0x104U, 0x0AEU, 0x07BU, 0x13DU, 0x19EU, 0x0E3, - 0x171U, 0x1B8U, 0x0F0U, 0x054U, 0x006U, 0x02FU, 0x117U, 0x18BU, 0x1C5U, 0x1E2, - 0x0DDU, 0x16EU, 0x09BU, 0x14DU, 0x1A6U }; - const uint16_t CCITT16_TABLE1[] = { 0x0000U, 0x1189U, 0x2312U, 0x329BU, 0x4624U, 0x57ADU, 0x6536U, 0x74BFU, 0x8C48U, 0x9DC1U, 0xAF5AU, 0xBED3U, 0xCA6CU, 0xDBE5U, 0xE97EU, 0xF8F7U, @@ -427,38 +411,6 @@ uint8_t CRC::crc8(const uint8_t *in, uint32_t length) return crc; } -/// -/// Generate 9-bit CRC. -/// -/// Input byte array. -/// Length of byte array in bits. -/// Calculated 9-bit CRC value. -uint16_t CRC::crc9(const uint8_t* in, uint32_t bitLength) -{ - assert(in != nullptr); - - uint16_t crc = 0x00U; - - for (uint32_t i = 0; i < bitLength; i++) { - bool b = READ_BIT(in, i); - if (b) { - if (i < 7U) { - crc ^= CRC9_TABLE[i]; - } else if (i > 15) { - crc ^= CRC9_TABLE[i - 9]; - } - } - } - - crc &= 0x1FFU; - -#if DEBUG_CRC_CHECK - LogDebug(LOG_HOST, "CRC::crc9(), crc = $%03X, bitlen = %u", crc, bitLength); -#endif - - return crc; -} - /// /// Check 6-bit CRC. /// @@ -694,7 +646,31 @@ uint16_t CRC::addCRC16(uint8_t* in, uint32_t bitLength) } /// -/// +/// Generate 9-bit CRC. +/// +/// Input byte array. +/// Length of byte array in bits. +/// +uint16_t CRC::createCRC9(const uint8_t* in, uint32_t bitLength) +{ + uint16_t crc = 0U; + + for (uint32_t i = 0U; i < bitLength; i++) { + bool bit1 = READ_BIT(in, i) != 0x00U; + bool bit2 = (crc & 0x100U) == 0x100U; + + crc <<= 1; + + if (bit1 ^ bit2) + crc ^= 0x59U; + } + + crc = ~crc; + return crc & 0x1FFU; +} + +/// +/// Generate 16-bit CRC. /// /// Input byte array. /// Length of byte array in bits. diff --git a/src/common/edac/CRC.h b/src/common/edac/CRC.h index 8a8cc223..541c6f51 100644 --- a/src/common/edac/CRC.h +++ b/src/common/edac/CRC.h @@ -9,7 +9,7 @@ * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX -* Copyright (C) 2018,2022 Bryan Biedenkapp, N2PLL +* Copyright (C) 2018,2022,2024 Bryan Biedenkapp, N2PLL * */ #if !defined(__CRC_H__) @@ -49,9 +49,6 @@ namespace edac /// Generate 8-bit CRC. static uint8_t crc8(const uint8_t* in, uint32_t length); - /// Generate 9-bit CRC. - static uint16_t crc9(const uint8_t* in, uint32_t bitLength); - /// Check 6-bit CRC. static bool checkCRC6(const uint8_t* in, uint32_t bitLength); /// Encode 6-bit CRC. @@ -72,7 +69,9 @@ namespace edac /// Encode 16-bit CRC CCITT-162 w/ initial generator of 1. static uint16_t addCRC16(uint8_t* in, uint32_t bitLength); - /// + /// Generate 9-bit CRC. + static uint16_t createCRC9(const uint8_t* in, uint32_t bitLength); + /// Generate 16-bit CRC. static uint16_t createCRC16(const uint8_t* in, uint32_t bitLength); private: diff --git a/src/common/p25/P25Defines.h b/src/common/p25/P25Defines.h index 4157685d..43a0dcc0 100644 --- a/src/common/p25/P25Defines.h +++ b/src/common/p25/P25Defines.h @@ -41,6 +41,9 @@ namespace p25 const uint32_t P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES = 90U; const uint32_t P25_TSDU_TRIPLE_FRAME_LENGTH_BITS = P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES * 8U; + const uint32_t P25_PDU_FRAME_LENGTH_BYTES = 512U; + const uint32_t P25_PDU_FRAME_LENGTH_BITS = P25_PDU_FRAME_LENGTH_BYTES * 8U; + const uint32_t P25_TDULC_FRAME_LENGTH_BYTES = 54U; const uint32_t P25_TDULC_FRAME_LENGTH_BITS = P25_TDULC_FRAME_LENGTH_BYTES * 8U; @@ -68,8 +71,8 @@ namespace p25 const uint32_t P25_TSBK_FEC_LENGTH_BITS = P25_TSBK_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits const uint32_t P25_TSBK_LENGTH_BYTES = 12U; - const uint32_t P25_MAX_PDU_COUNT = 32U; - const uint32_t P25_MAX_PDU_LENGTH = 512U; + const uint32_t P25_MAX_PDU_BLOCKS = 42U; + const uint32_t P25_PDU_HEADER_LENGTH_BYTES = 12U; const uint32_t P25_PDU_CONFIRMED_LENGTH_BYTES = 18U; const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U; diff --git a/src/common/p25/data/DataBlock.cpp b/src/common/p25/data/DataBlock.cpp index 2a367412..7da5d75e 100644 --- a/src/common/p25/data/DataBlock.cpp +++ b/src/common/p25/data/DataBlock.cpp @@ -100,11 +100,24 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header) } else { ::memcpy(m_data, buffer + 2U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); // Payload Data - } + } + + uint8_t crcBuffer[18U]; + ::memset(crcBuffer, 0x00U, 18U); + + // generate CRC buffer + for (uint32_t i = 0; i < 144U; i++) { + bool b = READ_BIT(buffer, i); + if (i < 7U) { + WRITE_BIT(crcBuffer, i, b); + } else if (i > 15U) { + WRITE_BIT(crcBuffer, i - 9U, b); + } + } // compute CRC-9 for the packet - uint16_t calculated = edac::CRC::crc9(buffer, 144U); - if (((crc ^ calculated) != 0) && ((crc ^ calculated) != 0x1FFU)) { + uint16_t calculated = edac::CRC::createCRC9(crcBuffer, 135U); + if ((crc ^ calculated) != 0) { LogWarning(LOG_P25, "P25_DUID_PDU, fmt = $%02X, invalid crc = $%04X != $%04X (computed)", m_fmt, crc, calculated); } @@ -176,7 +189,20 @@ void DataBlock::encode(uint8_t* data) ::memcpy(buffer + 2U, m_data, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); } - uint16_t crc = edac::CRC::crc9(buffer, 144U); + uint8_t crcBuffer[18U]; + ::memset(crcBuffer, 0x00U, 18U); + + // generate CRC buffer + for (uint32_t i = 0; i < 144U; i++) { + bool b = READ_BIT(buffer, i); + if (i < 7U) { + WRITE_BIT(crcBuffer, i, b); + } else if (i > 15U) { + WRITE_BIT(crcBuffer, i - 9U, b); + } + } + + uint16_t crc = edac::CRC::createCRC9(crcBuffer, 135U); buffer[0U] = buffer[0U] + ((crc >> 8) & 0x01U); // CRC-9 Check Sum (b8) buffer[1U] = (crc & 0xFFU); // CRC-9 Check Sum (b0 - b7) diff --git a/src/fw/hotspot b/src/fw/hotspot index 07ec4612..88224479 160000 --- a/src/fw/hotspot +++ b/src/fw/hotspot @@ -1 +1 @@ -Subproject commit 07ec4612fc6e7c018b77a880c59154bd88e80492 +Subproject commit 882244795b9bec1f2c86d596d4ab4ecd4346c8b9 diff --git a/src/fw/modem b/src/fw/modem index 93a59264..98d3bb1c 160000 --- a/src/fw/modem +++ b/src/fw/modem @@ -1 +1 @@ -Subproject commit 93a59264ff2e8515d11aa259577ee106287fd51d +Subproject commit 98d3bb1cd9bd1bdfa8d723c15f8847841739e9ca diff --git a/src/host/Host.Config.cpp b/src/host/Host.Config.cpp index 20fca540..b0755227 100644 --- a/src/host/Host.Config.cpp +++ b/src/host/Host.Config.cpp @@ -454,6 +454,22 @@ bool Host::createModem() uint16_t p25FifoLength = (uint16_t)modemConf["p25FifoLength"].as(P25_TX_BUFFER_LEN); uint16_t nxdnFifoLength = (uint16_t)modemConf["nxdnFifoLength"].as(NXDN_TX_BUFFER_LEN); + // clamp fifo sizes + if (dmrFifoLength < DMR_TX_BUFFER_LEN) { + LogWarning(LOG_HOST, "DMR FIFO size must be greater then %u bytes, defaulting to %u bytes!", DMR_TX_BUFFER_LEN, DMR_TX_BUFFER_LEN); + dmrFifoLength = DMR_TX_BUFFER_LEN; + } + + if (p25FifoLength < 442U/*P25_TX_BUFFER_LEN*/) { + LogWarning(LOG_HOST, "P25 FIFO size must be greater then %u bytes, defaulting to %u bytes!", 442U/*P25_TX_BUFFER_LEN*/, 442U/*P25_TX_BUFFER_LEN*/); + p25FifoLength = 442U/*P25_TX_BUFFER_LEN*/; + } + + if (nxdnFifoLength < NXDN_TX_BUFFER_LEN) { + LogWarning(LOG_HOST, "NXDN FIFO size must be greater then %u frames, defaulting to %u frames!", NXDN_TX_BUFFER_LEN, NXDN_TX_BUFFER_LEN); + nxdnFifoLength = NXDN_TX_BUFFER_LEN; + } + float rxLevel = modemConf["rxLevel"].as(50.0F); float cwIdTXLevel = modemConf["cwIdTxLevel"].as(50.0F); float dmrTXLevel = modemConf["dmrTxLevel"].as(50.0F); diff --git a/src/host/Host.P25.cpp b/src/host/Host.P25.cpp index 96a55dd0..9a1e9c32 100644 --- a/src/host/Host.P25.cpp +++ b/src/host/Host.P25.cpp @@ -43,7 +43,7 @@ void Host::interruptP25Control(p25::Control* control) /// void Host::readFramesP25(p25::Control* control, std::function&& afterReadCallback) { - uint8_t data[p25::P25_LDU_FRAME_LENGTH_BYTES * 2U]; + uint8_t data[p25::P25_PDU_FRAME_LENGTH_BYTES * 2U]; // read P25 frames from modem, and if there are frames // write those frames to the P25 controller diff --git a/src/host/modem/Modem.cpp b/src/host/modem/Modem.cpp index 810463fe..4a163674 100644 --- a/src/host/modem/Modem.cpp +++ b/src/host/modem/Modem.cpp @@ -9,7 +9,7 @@ * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * * Copyright (C) 2011-2021 Jonathan Naylor, G4KLX -* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL +* Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL * Copyright (C) 2021 Nat Moore * */ @@ -377,7 +377,7 @@ void Modem::setRXLevel(float rxLevel) uint8_t buffer[4U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 4U; buffer[2U] = CMD_SET_RXLEVEL; @@ -437,7 +437,7 @@ void Modem::setFifoLength(uint16_t dmrLength, uint16_t p25Length, uint16_t nxdnL uint8_t buffer[9U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 9U; buffer[2U] = CMD_SET_BUFFERS; @@ -628,7 +628,12 @@ void Modem::clock(uint32_t ms) } else { // type == RTM_OK - switch (m_buffer[2U]) { + uint8_t cmdOffset = 2U; + if (m_rspDoubleLength) { + cmdOffset = 3U; + } + + switch (m_buffer[cmdOffset]) { /** Digital Mobile Radio */ case CMD_DMR_DATA1: { @@ -727,18 +732,15 @@ void Modem::clock(uint32_t ms) //if (m_trace) // Utils::dump(1U, "RX P25 Data", m_buffer, m_length); - if (m_rspDoubleLength) { - LogError(LOG_MODEM, "CMD_P25_DATA double length?; len = %u", m_length); - break; - } + uint8_t length[2U]; + length[0U] = ((m_length - cmdOffset) >> 8U) & 0xFFU; + length[1U] = (m_length - cmdOffset) & 0xFFU; + m_rxP25Queue.addData(length, 2U); - uint8_t data = m_length - 2U; + uint8_t data = TAG_DATA; m_rxP25Queue.addData(&data, 1U); - data = TAG_DATA; - m_rxP25Queue.addData(&data, 1U); - - m_rxP25Queue.addData(m_buffer + 3U, m_length - 3U); + m_rxP25Queue.addData(m_buffer + (cmdOffset + 1U), m_length - (cmdOffset + 1U)); } } break; @@ -1036,10 +1038,14 @@ uint32_t Modem::readP25Frame(uint8_t* data) if (m_rxP25Queue.isEmpty()) return 0U; - uint8_t len = 0U; - m_rxP25Queue.peek(&len, 1U); + uint8_t length[2U]; + ::memset(length, 0x00U, 2U); + m_rxP25Queue.peek(length, 2U); + + uint16_t len = 0U; + len = (length[0U] << 8) + length[1U]; if (m_rxP25Queue.dataSize() >= len) { - m_rxP25Queue.get(&len, 1U); // ensure we pop the length off + m_rxP25Queue.get(length, 2U); // ensure we pop the length off m_rxP25Queue.get(data, len); return len; @@ -1161,7 +1167,7 @@ void Modem::clearDMRFrame1() { uint8_t buffer[3U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_DMR_CLEAR1; #if DEBUG_MODEM @@ -1178,7 +1184,7 @@ void Modem::clearDMRFrame2() { uint8_t buffer[3U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_DMR_CLEAR2; #if DEBUG_MODEM @@ -1195,7 +1201,7 @@ void Modem::clearP25Frame() { uint8_t buffer[3U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_P25_CLEAR; #if DEBUG_MODEM @@ -1212,7 +1218,7 @@ void Modem::clearNXDNFrame() { uint8_t buffer[3U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_NXDN_CLEAR; #if DEBUG_MODEM @@ -1350,7 +1356,7 @@ bool Modem::writeDMRFrame1(const uint8_t* data, uint32_t length) uint8_t buffer[MAX_LENGTH]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = length + 2U; buffer[2U] = CMD_DMR_DATA1; @@ -1408,7 +1414,7 @@ bool Modem::writeDMRFrame2(const uint8_t* data, uint32_t length) uint8_t buffer[MAX_LENGTH]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = length + 2U; buffer[2U] = CMD_DMR_DATA2; @@ -1454,7 +1460,7 @@ bool Modem::writeP25Frame(const uint8_t* data, uint32_t length) assert(length > 0U); if (m_p25Enabled) { - const uint8_t MAX_LENGTH = 250U; + const uint16_t MAX_LENGTH = 520U; if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) return false; @@ -1466,11 +1472,19 @@ bool Modem::writeP25Frame(const uint8_t* data, uint32_t length) uint8_t buffer[MAX_LENGTH]; - buffer[0U] = DVM_FRAME_START; - buffer[1U] = length + 2U; - buffer[2U] = CMD_P25_DATA; - - ::memcpy(buffer + 3U, data + 1U, length - 1U); + if (length < 252U) { + buffer[0U] = DVM_SHORT_FRAME_START; + buffer[1U] = length + 2U; + buffer[2U] = CMD_P25_DATA; + ::memcpy(buffer + 3U, data + 1U, length - 1U); + } else { + length += 3U; + buffer[0U] = DVM_LONG_FRAME_START; + buffer[1U] = (length >> 8U) & 0xFFU; + buffer[2U] = (length & 0xFFU); + buffer[3U] = CMD_P25_DATA; + ::memcpy(buffer + 4U, data + 1U, length - 1U); + } uint8_t len = length + 2U; @@ -1524,7 +1538,7 @@ bool Modem::writeNXDNFrame(const uint8_t* data, uint32_t length) uint8_t buffer[MAX_LENGTH]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = length + 2U; buffer[2U] = CMD_NXDN_DATA; @@ -1573,7 +1587,7 @@ bool Modem::writeDMRStart(bool tx) uint8_t buffer[4U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 4U; buffer[2U] = CMD_DMR_START; buffer[3U] = tx ? 0x01U : 0x00U; @@ -1599,7 +1613,7 @@ bool Modem::writeDMRShortLC(const uint8_t* lc) if (m_dmrEnabled) { uint8_t buffer[12U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 12U; buffer[2U] = CMD_DMR_SHORTLC; buffer[3U] = lc[0U]; @@ -1631,7 +1645,7 @@ bool Modem::writeDMRAbort(uint32_t slotNo) if (m_dmrEnabled) { uint8_t buffer[4U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 4U; buffer[2U] = CMD_DMR_ABORT; buffer[3U] = slotNo; @@ -1655,7 +1669,7 @@ bool Modem::setDMRIgnoreCACH_AT(uint8_t slotNo) if (m_dmrEnabled) { uint8_t buffer[4U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 4U; buffer[2U] = CMD_DMR_CACH_AT_CTRL; buffer[3U] = slotNo; @@ -1705,7 +1719,7 @@ bool Modem::setState(DVM_STATE state) { uint8_t buffer[4U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 4U; buffer[2U] = CMD_SET_MODE; buffer[3U] = state; @@ -1730,7 +1744,7 @@ bool Modem::sendCWId(const std::string& callsign) uint8_t buffer[205U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = length + 3U; buffer[2U] = CMD_SEND_CWID; @@ -1790,7 +1804,7 @@ bool Modem::getFirmwareVersion() for (uint32_t i = 0U; i < 6U; i++) { uint8_t buffer[3U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_GET_VERSION; @@ -1800,7 +1814,7 @@ bool Modem::getFirmwareVersion() for (uint32_t count = 0U; count < MAX_RESPONSES; count++) { Thread::sleep(10U); - RESP_TYPE_DVM resp = getResponse(true); + RESP_TYPE_DVM resp = getResponse(); if (resp == RTM_ERROR) continue; @@ -1858,7 +1872,7 @@ bool Modem::getStatus() { uint8_t buffer[3U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_GET_STATUS; @@ -1877,7 +1891,7 @@ bool Modem::writeConfig() ::memset(buffer, 0x00U, 25U); uint8_t lengthToWrite = 17U; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[2U] = CMD_SET_CONFIG; buffer[3U] = 0x00U; @@ -1993,7 +2007,7 @@ bool Modem::writeSymbolAdjust() ::memset(buffer, 0x00U, 20U); uint8_t lengthToWrite = 7U; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[2U] = CMD_SET_SYMLVLADJ; buffer[3U] = (uint8_t)(m_dmrSymLevel3Adj + 128); @@ -2049,7 +2063,7 @@ bool Modem::writeRFParams() ::memset(buffer, 0x00U, 22U); uint8_t lengthToWrite = 18U; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[2U] = CMD_SET_RFPARAMS; buffer[3U] = 0x00U; @@ -2130,7 +2144,7 @@ bool Modem::readFlash() for (uint32_t i = 0U; i < 6U; i++) { uint8_t buffer[3U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_FLSH_READ; @@ -2140,7 +2154,7 @@ bool Modem::readFlash() for (uint32_t count = 0U; count < MAX_RESPONSES; count++) { Thread::sleep(10U); - RESP_TYPE_DVM resp = getResponse(true); + RESP_TYPE_DVM resp = getResponse(); if (resp == RTM_ERROR) continue; @@ -2368,9 +2382,8 @@ void Modem::printDebug(const uint8_t* buffer, uint16_t len) /// /// Helper to get the raw response packet from modem. /// -/// Ignores invalid frame start and does not report as error. /// Response type from modem. -RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid) +RESP_TYPE_DVM Modem::getResponse() { m_rspDoubleLength = false; @@ -2390,22 +2403,23 @@ RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid) return RTM_TIMEOUT; } - if (m_buffer[0U] != DVM_FRAME_START) { - if (!noReportInvalid) { - LogError(LOG_MODEM, "Modem::getResponse(), illegal response, first byte not a frame start; byte = %02X", m_buffer[0U]); - Utils::dump(1U, "Modem Invalid Frame", m_buffer, 250U); - } - + if (m_buffer[0U] != DVM_SHORT_FRAME_START && + m_buffer[0U] != DVM_LONG_FRAME_START) { + //LogError(LOG_MODEM, "Modem::getResponse(), illegal response, first byte not a frame start; byte = %02X", m_buffer[0U]); ::memset(m_buffer, 0x00U, BUFFER_LENGTH); return RTM_ERROR; } + if (m_buffer[0U] == DVM_LONG_FRAME_START) { + m_rspDoubleLength = true; + } + //LogDebug(LOG_MODEM, "getResponse(), RESP_START"); m_rspState = RESP_LENGTH1; } - //LogDebug(LOG_MODEM, "getResponse(), getting frame length 1/2"); + //LogDebug(LOG_MODEM, "getResponse(), getting frame length 1/2, rspDoubleLength = %u", m_rspDoubleLength); // get the length of the frame, 1/2 if (m_rspState == RESP_LENGTH1) { int ret = m_port->read(m_buffer + 1U, 1U); @@ -2418,21 +2432,21 @@ RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid) if (ret == 0) return RTM_TIMEOUT; - if (m_buffer[1U] >= 250U) { + if (m_buffer[1U] >= 250U && !m_rspDoubleLength) { LogError(LOG_MODEM, "Invalid length received from the modem, len = %u", m_buffer[1U]); return RTM_ERROR; } - m_length = m_buffer[1U]; - - if (m_length == 0U) + if (m_rspDoubleLength) { m_rspState = RESP_LENGTH2; - else + m_length = ((m_buffer[1U] & 0xFFU) << 8); + } else { m_rspState = RESP_TYPE; + m_length = m_buffer[1U]; + } //LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH1, len = %u", m_length); - m_rspDoubleLength = false; m_rspOffset = 2U; } @@ -2449,7 +2463,7 @@ RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid) if (ret == 0) return RTM_TIMEOUT; - m_length = m_buffer[2U] + 255U; + m_length = (m_length + (m_buffer[2U] & 0xFFU)); m_rspState = RESP_TYPE; //LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH2, len = %u", m_length); diff --git a/src/host/modem/Modem.h b/src/host/modem/Modem.h index 9680259a..8521d4e2 100644 --- a/src/host/modem/Modem.h +++ b/src/host/modem/Modem.h @@ -9,7 +9,7 @@ * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * * Copyright (C) 2011-2021 Jonathan Naylor, G4KLX -* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL +* Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL * Copyright (C) 2021 Nat Moore * */ @@ -35,8 +35,8 @@ // 505 = DMR_FRAME_LENGTH_BYTES * 15 + 10 (BUFFER_LEN = DMR_FRAME_LENGTH_BYTES * NO_OF_FRAMES + 10) #define DMR_TX_BUFFER_LEN 505U // 15 frames + pad -// 442 = P25_LDU_FRAME_LENGTH_BYTES * 2 + 10 (BUFFER_LEN = P25_LDU_FRAME_LENGTH_BYTES * NO_OF_FRAMES + 10) -#define P25_TX_BUFFER_LEN 442U // 2 frames + pad +// 522 = P25_PDU_FRAME_LENGTH_BYTES + 10 (BUFFER_LEN = P25_PDU_FRAME_LENGTH_BYTES + 10) +#define P25_TX_BUFFER_LEN 522U // 1 PDU frame + pad // 538 = NXDN_FRAME_LENGTH_BYTES * 11 + 10 (BUFFER_LEN = NXDN_FRAME_LENGTH_BYTES * NO_OF_FRAMES) #define NXDN_TX_BUFFER_LEN 538U // 11 frames + pad @@ -211,7 +211,8 @@ namespace modem ADF_GAIN_HIGH = 3U }; - const uint8_t DVM_FRAME_START = 0xFEU; + const uint8_t DVM_SHORT_FRAME_START = 0xFEU; + const uint8_t DVM_LONG_FRAME_START = 0xFDU; const uint8_t DVM_CONF_AREA_VER = 0x02U; const uint8_t DVM_CONF_AREA_LEN = 246U; @@ -513,7 +514,7 @@ namespace modem void printDebug(const uint8_t* buffer, uint16_t len); /// Helper to get the raw response packet from modem. - RESP_TYPE_DVM getResponse(bool noReportInvalid = false); + RESP_TYPE_DVM getResponse(); /// Helper to convert a serial opcode to a string. std::string cmdToString(uint8_t opcode); diff --git a/src/host/modem/port/ModemNullPort.cpp b/src/host/modem/port/ModemNullPort.cpp index 9498dfc6..ed6ae145 100644 --- a/src/host/modem/port/ModemNullPort.cpp +++ b/src/host/modem/port/ModemNullPort.cpp @@ -9,7 +9,7 @@ * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * * Copyright (C) 2021 Jonathan Naylor, G4KLX -* Copyright (C) 2021 Bryan Biedenkapp, N2PLL +* Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL * */ #include "modem/port/ModemNullPort.h" @@ -115,7 +115,7 @@ void ModemNullPort::getVersion() { unsigned char reply[200U]; - reply[0U] = DVM_FRAME_START; + reply[0U] = DVM_SHORT_FRAME_START; reply[1U] = 0U; reply[2U] = CMD_GET_VERSION; @@ -142,7 +142,7 @@ void ModemNullPort::getStatus() unsigned char reply[15U]; // Send all sorts of interesting internal values - reply[0U] = DVM_FRAME_START; + reply[0U] = DVM_SHORT_FRAME_START; reply[1U] = 11U; reply[2U] = CMD_GET_STATUS; @@ -172,7 +172,7 @@ void ModemNullPort::writeAck(uint8_t type) { unsigned char reply[4U]; - reply[0U] = DVM_FRAME_START; + reply[0U] = DVM_SHORT_FRAME_START; reply[1U] = 4U; reply[2U] = CMD_ACK; reply[3U] = type; @@ -189,7 +189,7 @@ void ModemNullPort::writeNAK(uint8_t opcode, uint8_t err) { uint8_t reply[5U]; - reply[0U] = DVM_FRAME_START; + reply[0U] = DVM_SHORT_FRAME_START; reply[1U] = 5U; reply[2U] = CMD_NAK; reply[3U] = opcode; diff --git a/src/host/p25/packet/ControlSignaling.cpp b/src/host/p25/packet/ControlSignaling.cpp index 5b97340a..00b910f2 100644 --- a/src/host/p25/packet/ControlSignaling.cpp +++ b/src/host/p25/packet/ControlSignaling.cpp @@ -1260,8 +1260,8 @@ ControlSignaling::ControlSignaling(Control* p25, bool dumpTSBKData, bool debug, m_verbose(verbose), m_debug(debug) { - m_rfMBF = new uint8_t[P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U]; - ::memset(m_rfMBF, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + m_rfMBF = new uint8_t[P25_PDU_FRAME_LENGTH_BYTES + 2U]; + ::memset(m_rfMBF, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); m_adjSiteTable.clear(); m_adjSiteUpdateCnt.clear(); @@ -1549,7 +1549,7 @@ void ControlSignaling::writeNet_TSDU(lc::TSBK* tsbk) void ControlSignaling::writeRF_TSDU_MBF(lc::TSBK* tsbk) { if (!m_p25->m_enableControl) { - ::memset(m_rfMBF, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + ::memset(m_rfMBF, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); m_mbfCnt = 0U; return; } @@ -1563,7 +1563,7 @@ void ControlSignaling::writeRF_TSDU_MBF(lc::TSBK* tsbk) // trunking data is unsupported in simplex operation if (!m_p25->m_duplex) { - ::memset(m_rfMBF, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + ::memset(m_rfMBF, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); m_mbfCnt = 0U; return; } @@ -1636,7 +1636,7 @@ void ControlSignaling::writeRF_TSDU_MBF(lc::TSBK* tsbk) m_p25->addFrame(data, P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES + 2U); - ::memset(m_rfMBF, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + ::memset(m_rfMBF, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); m_mbfCnt = 0U; return; } @@ -1669,8 +1669,8 @@ void ControlSignaling::writeRF_TSDU_AMBT(lc::AMBT* ambt) assert(ambt != nullptr); DataHeader header = DataHeader(); - uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * P25_MAX_PDU_COUNT]; - ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * P25_MAX_PDU_COUNT); + uint8_t pduUserData[P25_MAX_PDU_BLOCKS * P25_PDU_UNCONFIRMED_LENGTH_BYTES]; + ::memset(pduUserData, 0x00U, P25_MAX_PDU_BLOCKS * P25_PDU_UNCONFIRMED_LENGTH_BYTES); // Generate TSBK block ambt->setLastBlock(true); // always set last block -- this a Single Block TSDU diff --git a/src/host/p25/packet/Data.cpp b/src/host/p25/packet/Data.cpp index 32e83bed..5925331e 100644 --- a/src/host/p25/packet/Data.cpp +++ b/src/host/p25/packet/Data.cpp @@ -87,26 +87,22 @@ bool Data::process(uint8_t* data, uint32_t len) m_rfPDUCount = 0U; m_rfPDUBits = 0U; - ::memset(m_rfPDU, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + ::memset(m_rfPDU, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); m_p25->m_rfState = RS_RF_DATA; - ::memset(m_pduUserData, 0x00U, P25_MAX_PDU_COUNT * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U); + ::memset(m_pduUserData, 0x00U, P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U); m_pduUserDataLength = 0U; } - uint32_t start = m_rfPDUCount * P25_LDU_FRAME_LENGTH_BITS; + uint32_t start = m_rfPDUCount * P25_PDU_FRAME_LENGTH_BITS; - uint8_t buffer[P25_MAX_PDU_LENGTH]; - ::memset(buffer, 0x00U, P25_MAX_PDU_LENGTH); + uint8_t buffer[P25_PDU_FRAME_LENGTH_BYTES]; + ::memset(buffer, 0x00U, P25_PDU_FRAME_LENGTH_BYTES); - // Utils::dump(2U, "* !!! P25_DUID_PDU - data", data + 2U, len - 2U); - - uint32_t bits = P25Utils::decode(data + 2U, buffer, start, start + P25_LDU_FRAME_LENGTH_BITS); + uint32_t bits = P25Utils::decode(data + 2U, buffer, start, start + P25_PDU_FRAME_LENGTH_BITS); m_rfPDUBits = Utils::getBits(buffer, m_rfPDU, 0U, bits); - // Utils::dump(2U, "* !!! P25_DUID_PDU - m_rfPDU", m_rfPDU, P25_LDU_FRAME_LENGTH_BYTES * 2U); - uint32_t offset = P25_PREAMBLE_LENGTH_BITS + P25_PDU_FEC_LENGTH_BITS; if (m_rfPDUCount == 0U) { ::memset(buffer, 0x00U, P25_PDU_FEC_LENGTH_BYTES); @@ -133,8 +129,8 @@ bool Data::process(uint8_t* data, uint32_t len) } // make sure we don't get a PDU with more blocks then we support - if (m_rfDataHeader.getBlocksToFollow() >= P25_MAX_PDU_COUNT) { - LogError(LOG_RF, P25_PDU_STR ", ISP, too many PDU blocks to process, %u > %u", m_rfDataHeader.getBlocksToFollow(), P25_MAX_PDU_COUNT); + if (m_rfDataHeader.getBlocksToFollow() >= P25_MAX_PDU_BLOCKS) { + LogError(LOG_RF, P25_PDU_STR ", ISP, too many PDU blocks to process, %u > %u", m_rfDataHeader.getBlocksToFollow(), P25_MAX_PDU_BLOCKS); m_rfDataHeader.reset(); m_rfSecondHeader.reset(); @@ -254,10 +250,10 @@ bool Data::process(uint8_t* data, uint32_t len) m_rfData[i].getSerialNo(), m_rfData[i].getFormat(), m_rfData[i].getLastBlock(), m_rfData[i].getSAP(), m_rfData[i].getLLId()); if (m_dumpPDUData) { - uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; - ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); + uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES]; + ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); m_rfData[i].getData(dataBlock); - Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); + Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); } } @@ -276,10 +272,10 @@ bool Data::process(uint8_t* data, uint32_t len) m_rfData[i].getLastBlock()); if (m_dumpPDUData) { - uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; - ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); + uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES]; + ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); m_rfData[i].getData(dataBlock); - Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); + Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); } } } @@ -460,6 +456,8 @@ bool Data::processNetwork(uint8_t* data, uint32_t len, uint32_t blockLength) m_netDataBlockCnt = 0U; m_netPDUCount = 0U; + ::memset(m_netPDU, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); + m_p25->m_netState = RS_NET_DATA; uint8_t buffer[P25_PDU_FEC_LENGTH_BYTES]; @@ -487,8 +485,8 @@ bool Data::processNetwork(uint8_t* data, uint32_t len, uint32_t blockLength) } // make sure we don't get a PDU with more blocks then we support - if (m_netDataHeader.getBlocksToFollow() >= P25_MAX_PDU_COUNT) { - LogError(LOG_NET, P25_PDU_STR ", too many PDU blocks to process, %u > %u", m_netDataHeader.getBlocksToFollow(), P25_MAX_PDU_COUNT); + if (m_netDataHeader.getBlocksToFollow() >= P25_MAX_PDU_BLOCKS) { + LogError(LOG_NET, P25_PDU_STR ", too many PDU blocks to process, %u > %u", m_netDataHeader.getBlocksToFollow(), P25_MAX_PDU_BLOCKS); m_netDataHeader.reset(); m_netSecondHeader.reset(); @@ -820,18 +818,18 @@ Data::Data(Control* p25, bool dumpPDUData, bool repeatPDU, bool debug, bool verb m_verbose(verbose), m_debug(debug) { - m_rfData = new data::DataBlock[P25_MAX_PDU_COUNT]; + m_rfData = new data::DataBlock[P25_MAX_PDU_BLOCKS]; - m_rfPDU = new uint8_t[P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U]; - ::memset(m_rfPDU, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + m_rfPDU = new uint8_t[P25_PDU_FRAME_LENGTH_BYTES + 2U]; + ::memset(m_rfPDU, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); - m_netData = new data::DataBlock[P25_MAX_PDU_COUNT]; + m_netData = new data::DataBlock[P25_MAX_PDU_BLOCKS]; - m_netPDU = new uint8_t[P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U]; - ::memset(m_netPDU, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + m_netPDU = new uint8_t[P25_PDU_FRAME_LENGTH_BYTES + 2U]; + ::memset(m_netPDU, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); - m_pduUserData = new uint8_t[P25_MAX_PDU_COUNT * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U]; - ::memset(m_pduUserData, 0x00U, P25_MAX_PDU_COUNT * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U); + m_pduUserData = new uint8_t[P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U]; + ::memset(m_pduUserData, 0x00U, P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U); m_fneRegTable.clear(); m_connQueueTable.clear(); @@ -876,16 +874,13 @@ void Data::writeNetwork(const uint8_t currentBlock, const uint8_t *data, uint32_ /// /// /// -/// This simply takes data packed into m_rfPDU and transmits it. void Data::writeRF_PDU(const uint8_t* pdu, uint32_t bitLength, bool noNulls) { assert(pdu != nullptr); assert(bitLength > 0U); - uint8_t data[P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U]; - ::memset(data, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); - - // Utils::dump(2U, "!!! *Raw PDU Frame Data - pdu", pdu, bitLength / 8U); + uint8_t data[P25_PDU_FRAME_LENGTH_BYTES + 2U]; + ::memset(data, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U); // Add the data uint32_t newBitLength = P25Utils::encode(pdu, data + 2U, bitLength); @@ -905,8 +900,6 @@ void Data::writeRF_PDU(const uint8_t* pdu, uint32_t bitLength, bool noNulls) // Add idle bits P25Utils::addIdleBits(data + 2U, newBitLength, true, true); - // Utils::dump(2U, "!!! *P25_DUID_PDU - data", data + 2U, newByteLength); - if (m_p25->m_duplex) { data[0U] = modem::TAG_DATA; data[1U] = 0x00U; @@ -991,10 +984,10 @@ void Data::writeNet_PDU_Buffered() m_netData[i].getSerialNo(), m_netData[i].getFormat(), m_netData[i].getLastBlock(), m_netData[i].getSAP(), m_netData[i].getLLId()); if (m_dumpPDUData) { - uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; - ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); + uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES]; + ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); m_netData[i].getData(dataBlock); - Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); + Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); } } } @@ -1005,10 +998,10 @@ void Data::writeNet_PDU_Buffered() m_netData[i].getLastBlock()); if (m_dumpPDUData) { - uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; - ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); + uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES]; + ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); m_netData[i].getData(dataBlock); - Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); + Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); } } } @@ -1087,10 +1080,10 @@ void Data::writeRF_PDU_Buffered() m_rfData[i].getSerialNo(), m_rfData[i].getFormat(), m_rfData[i].getLastBlock(), m_rfData[i].getSAP(), m_rfData[i].getLLId()); if (m_dumpPDUData) { - uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; - ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); + uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES]; + ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); m_rfData[i].getData(dataBlock); - Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); + Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); } } } @@ -1101,10 +1094,10 @@ void Data::writeRF_PDU_Buffered() m_rfData[i].getLastBlock()); if (m_dumpPDUData) { - uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; - ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); + uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES]; + ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); m_rfData[i].getData(dataBlock); - Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); + Utils::dump(2U, "Data Block", dataBlock, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); } } } @@ -1198,7 +1191,7 @@ void Data::writeRF_PDU_Ack_Response(uint8_t ackClass, uint8_t ackType, uint8_t a if (ackClass == PDU_ACK_CLASS_ACK && ackType != PDU_ACK_TYPE_ACK) return; - uint32_t bitLength = (2U * P25_PDU_FEC_LENGTH_BITS) + P25_PREAMBLE_LENGTH_BITS; + uint32_t bitLength = (1U * P25_PDU_FEC_LENGTH_BITS) + P25_PREAMBLE_LENGTH_BITS; uint32_t offset = P25_PREAMBLE_LENGTH_BITS; uint8_t data[bitLength / 8U]; diff --git a/src/host/setup/HostSetup.cpp b/src/host/setup/HostSetup.cpp index 475b7033..976f97cb 100644 --- a/src/host/setup/HostSetup.cpp +++ b/src/host/setup/HostSetup.cpp @@ -339,7 +339,7 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp uint8_t buffer[250U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = dataLen + 2U; buffer[2U] = CMD_P25_DATA; @@ -362,9 +362,20 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp } if (rspType == RTM_OK && len > 0) { - switch (buffer[2U]) { + uint8_t cmdOffset = 2U; + if (rspDblLen) { + cmdOffset = 3U; + } + + switch (buffer[cmdOffset]) { + /** Calibration */ case CMD_CAL_DATA: { + if (rspDblLen) { + LogError(LOG_MODEM, "CMD_CAL_DATA double length?; len = %u", len); + break; + } + bool inverted = (buffer[3U] == 0x80U); short high = buffer[4U] << 8 | buffer[5U]; short low = buffer[6U] << 8 | buffer[7U]; @@ -375,6 +386,11 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp break; case CMD_RSSI_DATA: { + if (rspDblLen) { + LogError(LOG_MODEM, "CMD_RSSI_DATA double length?; len = %u", len); + break; + } + uint16_t max = buffer[3U] << 8 | buffer[4U]; uint16_t min = buffer[5U] << 8 | buffer[6U]; uint16_t ave = buffer[7U] << 8 | buffer[8U]; @@ -382,14 +398,27 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp } break; + /** Digital Mobile Radio */ case CMD_DMR_DATA1: case CMD_DMR_DATA2: + { + if (rspDblLen) { + LogError(LOG_MODEM, "CMD_DMR_DATA double length?; len = %u", len); + break; + } + processDMRBER(buffer + 4U, buffer[3]); - break; + } + break; case CMD_DMR_LOST1: case CMD_DMR_LOST2: { + if (rspDblLen) { + LogError(LOG_MODEM, "CMD_DMR_LOST double length?; len = %u", len); + break; + } + LogMessage(LOG_CAL, "DMR Transmission lost, total frames: %d, bits: %d, uncorrectable frames: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_berFrames, m_berBits, m_berUncorrectable, m_berUndecodableLC, m_berErrs, float(m_berErrs * 100U) / float(m_berBits)); if (m_dmrEnabled) { @@ -402,12 +431,18 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp } break; + /** Project 25 */ case CMD_P25_DATA: processP25BER(buffer + 4U); break; case CMD_P25_LOST: { + if (rspDblLen) { + LogError(LOG_MODEM, "CMD_P25_LOST double length?; len = %u", len); + break; + } + LogMessage(LOG_CAL, "P25 Transmission lost, total frames: %d, bits: %d, uncorrectable frames: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_berFrames, m_berBits, m_berUncorrectable, m_berUndecodableLC, m_berErrs, float(m_berErrs * 100U) / float(m_berBits)); if (m_p25Enabled) { @@ -420,12 +455,25 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp } break; + /** Next Generation Digital Narrowband */ case CMD_NXDN_DATA: + { + if (rspDblLen) { + LogError(LOG_MODEM, "CMD_NXDN_DATA double length?; len = %u", len); + break; + } + processNXDNBER(buffer + 4U); - break; + } + break; case CMD_NXDN_LOST: { + if (rspDblLen) { + LogError(LOG_MODEM, "CMD_NXDN_DATA double length?; len = %u", len); + break; + } + LogMessage(LOG_CAL, "NXDN Transmission lost, total frames: %d, bits: %d, uncorrectable frames: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_berFrames, m_berBits, m_berUncorrectable, m_berUndecodableLC, m_berErrs, float(m_berErrs * 100U) / float(m_berBits)); if (m_nxdnEnabled) { @@ -438,6 +486,7 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp } break; + /** General */ case CMD_GET_STATUS: { m_isHotspot = (buffer[3U] & 0x01U) == 0x01U; @@ -870,7 +919,7 @@ bool HostSetup::setTransmit() uint8_t buffer[50U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 4U; buffer[2U] = CMD_CAL_DATA; buffer[3U] = m_transmit ? 0x01U : 0x00U; @@ -1236,8 +1285,8 @@ void HostSetup::processP25BER(const uint8_t* buffer) uint8_t pduBuffer[P25_LDU_FRAME_LENGTH_BYTES]; uint32_t bits = P25Utils::decode(buffer, pduBuffer, 0, P25_LDU_FRAME_LENGTH_BITS); - uint8_t* rfPDU = new uint8_t[P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U]; - ::memset(rfPDU, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); + uint8_t* rfPDU = new uint8_t[P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U]; + ::memset(rfPDU, 0x00U, P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U); uint32_t rfPDUBits = 0U; for (uint32_t i = 0U; i < bits; i++, rfPDUBits++) { @@ -1481,7 +1530,7 @@ bool HostSetup::writeConfig(uint8_t modeOverride) ::memset(buffer, 0x00U, 25U); uint8_t lengthToWrite = 17U; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[2U] = CMD_SET_CONFIG; buffer[3U] = 0x00U; @@ -1591,7 +1640,7 @@ bool HostSetup::writeRFParams() ::memset(buffer, 0x00U, 22U); uint8_t lengthToWrite = 18U; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[2U] = CMD_SET_RFPARAMS; buffer[3U] = 0x00U; @@ -1661,7 +1710,7 @@ bool HostSetup::writeSymbolAdjust() ::memset(buffer, 0x00U, 20U); uint8_t lengthToWrite = 7U; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[2U] = CMD_SET_SYMLVLADJ; m_conf["system"]["modem"]["repeater"]["dmrSymLvl3Adj"] = __INT_STR(m_modem->m_dmrSymLevel3Adj); @@ -1705,7 +1754,7 @@ bool HostSetup::writeFifoLength() uint8_t buffer[9U]; ::memset(buffer, 0x00U, 9U); - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 9U; buffer[2U] = CMD_SET_BUFFERS; @@ -1750,7 +1799,7 @@ bool HostSetup::readFlash() uint8_t buffer[3U]; ::memset(buffer, 0x00U, 3U); - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 3U; buffer[2U] = CMD_FLSH_READ; @@ -1892,7 +1941,7 @@ bool HostSetup::eraseFlash() uint8_t buffer[249U]; ::memset(buffer, 0x00U, 249U); - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 249U; buffer[2U] = CMD_FLSH_WRITE; @@ -1926,7 +1975,7 @@ bool HostSetup::writeFlash() uint8_t buffer[249U]; ::memset(buffer, 0x00U, 249U); - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 249U; buffer[2U] = CMD_FLSH_WRITE; @@ -2070,7 +2119,7 @@ void HostSetup::getStatus() { uint8_t buffer[50U]; - buffer[0U] = DVM_FRAME_START; + buffer[0U] = DVM_SHORT_FRAME_START; buffer[1U] = 4U; buffer[2U] = CMD_GET_STATUS;