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;
pull/59/head
Bryan Biedenkapp 2 years ago committed by GitHub
parent cf2469a2aa
commit 24082b9652
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -473,7 +473,7 @@ system:
# Size (in bytes) of the DMR transmit FIFO buffer. # Size (in bytes) of the DMR transmit FIFO buffer.
dmrFifoLength: 505 dmrFifoLength: 505
# Size (in bytes) of the P25 transmit FIFO buffer. # Size (in bytes) of the P25 transmit FIFO buffer.
p25FifoLength: 442 p25FifoLength: 522
# Size (in bytes) of the NXDN transmit FIFO buffer. # Size (in bytes) of the NXDN transmit FIFO buffer.
nxdnFifoLength: 538 nxdnFifoLength: 538

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * 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" #include "Defines.h"
@ -49,22 +49,6 @@ const uint8_t CRC8_TABLE[] = {
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF,
0xFA, 0xFD, 0xF4, 0xF3, 0x01 }; 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[] = { const uint16_t CCITT16_TABLE1[] = {
0x0000U, 0x1189U, 0x2312U, 0x329BU, 0x4624U, 0x57ADU, 0x6536U, 0x74BFU, 0x0000U, 0x1189U, 0x2312U, 0x329BU, 0x4624U, 0x57ADU, 0x6536U, 0x74BFU,
0x8C48U, 0x9DC1U, 0xAF5AU, 0xBED3U, 0xCA6CU, 0xDBE5U, 0xE97EU, 0xF8F7U, 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; return crc;
} }
/// <summary>
/// Generate 9-bit CRC.
/// </summary>
/// <param name="in">Input byte array.</param>
/// <param name="bitLength">Length of byte array in bits.</param>
/// <returns>Calculated 9-bit CRC value.</returns>
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;
}
/// <summary> /// <summary>
/// Check 6-bit CRC. /// Check 6-bit CRC.
/// </summary> /// </summary>
@ -694,7 +646,31 @@ uint16_t CRC::addCRC16(uint8_t* in, uint32_t bitLength)
} }
/// <summary> /// <summary>
/// /// Generate 9-bit CRC.
/// </summary>
/// <param name="in">Input byte array.</param>
/// <param name="bitLength">Length of byte array in bits.</param>
/// <returns></returns>
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;
}
/// <summary>
/// Generate 16-bit CRC.
/// </summary> /// </summary>
/// <param name="in">Input byte array.</param> /// <param name="in">Input byte array.</param>
/// <param name="bitLength">Length of byte array in bits.</param> /// <param name="bitLength">Length of byte array in bits.</param>

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * 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__) #if !defined(__CRC_H__)
@ -49,9 +49,6 @@ namespace edac
/// <summary>Generate 8-bit CRC.</summary> /// <summary>Generate 8-bit CRC.</summary>
static uint8_t crc8(const uint8_t* in, uint32_t length); static uint8_t crc8(const uint8_t* in, uint32_t length);
/// <summary>Generate 9-bit CRC.</summary>
static uint16_t crc9(const uint8_t* in, uint32_t bitLength);
/// <summary>Check 6-bit CRC.</summary> /// <summary>Check 6-bit CRC.</summary>
static bool checkCRC6(const uint8_t* in, uint32_t bitLength); static bool checkCRC6(const uint8_t* in, uint32_t bitLength);
/// <summary>Encode 6-bit CRC.</summary> /// <summary>Encode 6-bit CRC.</summary>
@ -72,7 +69,9 @@ namespace edac
/// <summary>Encode 16-bit CRC CCITT-162 w/ initial generator of 1.</summary> /// <summary>Encode 16-bit CRC CCITT-162 w/ initial generator of 1.</summary>
static uint16_t addCRC16(uint8_t* in, uint32_t bitLength); static uint16_t addCRC16(uint8_t* in, uint32_t bitLength);
/// <summary></summary> /// <summary>Generate 9-bit CRC.</summary>
static uint16_t createCRC9(const uint8_t* in, uint32_t bitLength);
/// <summary>Generate 16-bit CRC.</summary>
static uint16_t createCRC16(const uint8_t* in, uint32_t bitLength); static uint16_t createCRC16(const uint8_t* in, uint32_t bitLength);
private: private:

@ -41,6 +41,9 @@ namespace p25
const uint32_t P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES = 90U; 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_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_BYTES = 54U;
const uint32_t P25_TDULC_FRAME_LENGTH_BITS = P25_TDULC_FRAME_LENGTH_BYTES * 8U; 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_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_TSBK_LENGTH_BYTES = 12U;
const uint32_t P25_MAX_PDU_COUNT = 32U; const uint32_t P25_MAX_PDU_BLOCKS = 42U;
const uint32_t P25_MAX_PDU_LENGTH = 512U;
const uint32_t P25_PDU_HEADER_LENGTH_BYTES = 12U; const uint32_t P25_PDU_HEADER_LENGTH_BYTES = 12U;
const uint32_t P25_PDU_CONFIRMED_LENGTH_BYTES = 18U; const uint32_t P25_PDU_CONFIRMED_LENGTH_BYTES = 18U;
const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U; const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U;

@ -100,11 +100,24 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
} }
else { else {
::memcpy(m_data, buffer + 2U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); // Payload Data ::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 // compute CRC-9 for the packet
uint16_t calculated = edac::CRC::crc9(buffer, 144U); uint16_t calculated = edac::CRC::createCRC9(crcBuffer, 135U);
if (((crc ^ calculated) != 0) && ((crc ^ calculated) != 0x1FFU)) { if ((crc ^ calculated) != 0) {
LogWarning(LOG_P25, "P25_DUID_PDU, fmt = $%02X, invalid crc = $%04X != $%04X (computed)", m_fmt, crc, calculated); 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); ::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[0U] = buffer[0U] + ((crc >> 8) & 0x01U); // CRC-9 Check Sum (b8)
buffer[1U] = (crc & 0xFFU); // CRC-9 Check Sum (b0 - b7) buffer[1U] = (crc & 0xFFU); // CRC-9 Check Sum (b0 - b7)

@ -1 +1 @@
Subproject commit 07ec4612fc6e7c018b77a880c59154bd88e80492 Subproject commit 882244795b9bec1f2c86d596d4ab4ecd4346c8b9

@ -1 +1 @@
Subproject commit 93a59264ff2e8515d11aa259577ee106287fd51d Subproject commit 98d3bb1cd9bd1bdfa8d723c15f8847841739e9ca

@ -454,6 +454,22 @@ bool Host::createModem()
uint16_t p25FifoLength = (uint16_t)modemConf["p25FifoLength"].as<uint32_t>(P25_TX_BUFFER_LEN); uint16_t p25FifoLength = (uint16_t)modemConf["p25FifoLength"].as<uint32_t>(P25_TX_BUFFER_LEN);
uint16_t nxdnFifoLength = (uint16_t)modemConf["nxdnFifoLength"].as<uint32_t>(NXDN_TX_BUFFER_LEN); uint16_t nxdnFifoLength = (uint16_t)modemConf["nxdnFifoLength"].as<uint32_t>(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<float>(50.0F); float rxLevel = modemConf["rxLevel"].as<float>(50.0F);
float cwIdTXLevel = modemConf["cwIdTxLevel"].as<float>(50.0F); float cwIdTXLevel = modemConf["cwIdTxLevel"].as<float>(50.0F);
float dmrTXLevel = modemConf["dmrTxLevel"].as<float>(50.0F); float dmrTXLevel = modemConf["dmrTxLevel"].as<float>(50.0F);

@ -43,7 +43,7 @@ void Host::interruptP25Control(p25::Control* control)
/// <param name="afterReadCallback"></param> /// <param name="afterReadCallback"></param>
void Host::readFramesP25(p25::Control* control, std::function<void()>&& afterReadCallback) void Host::readFramesP25(p25::Control* control, std::function<void()>&& 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 // read P25 frames from modem, and if there are frames
// write those frames to the P25 controller // write those frames to the P25 controller

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2011-2021 Jonathan Naylor, G4KLX * 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 * Copyright (C) 2021 Nat Moore
* *
*/ */
@ -377,7 +377,7 @@ void Modem::setRXLevel(float rxLevel)
uint8_t buffer[4U]; uint8_t buffer[4U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 4U; buffer[1U] = 4U;
buffer[2U] = CMD_SET_RXLEVEL; 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]; uint8_t buffer[9U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 9U; buffer[1U] = 9U;
buffer[2U] = CMD_SET_BUFFERS; buffer[2U] = CMD_SET_BUFFERS;
@ -628,7 +628,12 @@ void Modem::clock(uint32_t ms)
} }
else { else {
// type == RTM_OK // type == RTM_OK
switch (m_buffer[2U]) { uint8_t cmdOffset = 2U;
if (m_rspDoubleLength) {
cmdOffset = 3U;
}
switch (m_buffer[cmdOffset]) {
/** Digital Mobile Radio */ /** Digital Mobile Radio */
case CMD_DMR_DATA1: case CMD_DMR_DATA1:
{ {
@ -727,18 +732,15 @@ void Modem::clock(uint32_t ms)
//if (m_trace) //if (m_trace)
// Utils::dump(1U, "RX P25 Data", m_buffer, m_length); // Utils::dump(1U, "RX P25 Data", m_buffer, m_length);
if (m_rspDoubleLength) { uint8_t length[2U];
LogError(LOG_MODEM, "CMD_P25_DATA double length?; len = %u", m_length); length[0U] = ((m_length - cmdOffset) >> 8U) & 0xFFU;
break; 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); m_rxP25Queue.addData(&data, 1U);
data = TAG_DATA; m_rxP25Queue.addData(m_buffer + (cmdOffset + 1U), m_length - (cmdOffset + 1U));
m_rxP25Queue.addData(&data, 1U);
m_rxP25Queue.addData(m_buffer + 3U, m_length - 3U);
} }
} }
break; break;
@ -1036,10 +1038,14 @@ uint32_t Modem::readP25Frame(uint8_t* data)
if (m_rxP25Queue.isEmpty()) if (m_rxP25Queue.isEmpty())
return 0U; return 0U;
uint8_t len = 0U; uint8_t length[2U];
m_rxP25Queue.peek(&len, 1U); ::memset(length, 0x00U, 2U);
m_rxP25Queue.peek(length, 2U);
uint16_t len = 0U;
len = (length[0U] << 8) + length[1U];
if (m_rxP25Queue.dataSize() >= len) { 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); m_rxP25Queue.get(data, len);
return len; return len;
@ -1161,7 +1167,7 @@ void Modem::clearDMRFrame1()
{ {
uint8_t buffer[3U]; uint8_t buffer[3U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_DMR_CLEAR1; buffer[2U] = CMD_DMR_CLEAR1;
#if DEBUG_MODEM #if DEBUG_MODEM
@ -1178,7 +1184,7 @@ void Modem::clearDMRFrame2()
{ {
uint8_t buffer[3U]; uint8_t buffer[3U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_DMR_CLEAR2; buffer[2U] = CMD_DMR_CLEAR2;
#if DEBUG_MODEM #if DEBUG_MODEM
@ -1195,7 +1201,7 @@ void Modem::clearP25Frame()
{ {
uint8_t buffer[3U]; uint8_t buffer[3U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_P25_CLEAR; buffer[2U] = CMD_P25_CLEAR;
#if DEBUG_MODEM #if DEBUG_MODEM
@ -1212,7 +1218,7 @@ void Modem::clearNXDNFrame()
{ {
uint8_t buffer[3U]; uint8_t buffer[3U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_NXDN_CLEAR; buffer[2U] = CMD_NXDN_CLEAR;
#if DEBUG_MODEM #if DEBUG_MODEM
@ -1350,7 +1356,7 @@ bool Modem::writeDMRFrame1(const uint8_t* data, uint32_t length)
uint8_t buffer[MAX_LENGTH]; uint8_t buffer[MAX_LENGTH];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = length + 2U; buffer[1U] = length + 2U;
buffer[2U] = CMD_DMR_DATA1; buffer[2U] = CMD_DMR_DATA1;
@ -1408,7 +1414,7 @@ bool Modem::writeDMRFrame2(const uint8_t* data, uint32_t length)
uint8_t buffer[MAX_LENGTH]; uint8_t buffer[MAX_LENGTH];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = length + 2U; buffer[1U] = length + 2U;
buffer[2U] = CMD_DMR_DATA2; buffer[2U] = CMD_DMR_DATA2;
@ -1454,7 +1460,7 @@ bool Modem::writeP25Frame(const uint8_t* data, uint32_t length)
assert(length > 0U); assert(length > 0U);
if (m_p25Enabled) { if (m_p25Enabled) {
const uint8_t MAX_LENGTH = 250U; const uint16_t MAX_LENGTH = 520U;
if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) if (data[0U] != TAG_DATA && data[0U] != TAG_EOT)
return false; return false;
@ -1466,11 +1472,19 @@ bool Modem::writeP25Frame(const uint8_t* data, uint32_t length)
uint8_t buffer[MAX_LENGTH]; uint8_t buffer[MAX_LENGTH];
buffer[0U] = DVM_FRAME_START; if (length < 252U) {
buffer[1U] = length + 2U; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[2U] = CMD_P25_DATA; buffer[1U] = length + 2U;
buffer[2U] = CMD_P25_DATA;
::memcpy(buffer + 3U, data + 1U, length - 1U); ::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; uint8_t len = length + 2U;
@ -1524,7 +1538,7 @@ bool Modem::writeNXDNFrame(const uint8_t* data, uint32_t length)
uint8_t buffer[MAX_LENGTH]; uint8_t buffer[MAX_LENGTH];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = length + 2U; buffer[1U] = length + 2U;
buffer[2U] = CMD_NXDN_DATA; buffer[2U] = CMD_NXDN_DATA;
@ -1573,7 +1587,7 @@ bool Modem::writeDMRStart(bool tx)
uint8_t buffer[4U]; uint8_t buffer[4U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 4U; buffer[1U] = 4U;
buffer[2U] = CMD_DMR_START; buffer[2U] = CMD_DMR_START;
buffer[3U] = tx ? 0x01U : 0x00U; buffer[3U] = tx ? 0x01U : 0x00U;
@ -1599,7 +1613,7 @@ bool Modem::writeDMRShortLC(const uint8_t* lc)
if (m_dmrEnabled) { if (m_dmrEnabled) {
uint8_t buffer[12U]; uint8_t buffer[12U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 12U; buffer[1U] = 12U;
buffer[2U] = CMD_DMR_SHORTLC; buffer[2U] = CMD_DMR_SHORTLC;
buffer[3U] = lc[0U]; buffer[3U] = lc[0U];
@ -1631,7 +1645,7 @@ bool Modem::writeDMRAbort(uint32_t slotNo)
if (m_dmrEnabled) { if (m_dmrEnabled) {
uint8_t buffer[4U]; uint8_t buffer[4U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 4U; buffer[1U] = 4U;
buffer[2U] = CMD_DMR_ABORT; buffer[2U] = CMD_DMR_ABORT;
buffer[3U] = slotNo; buffer[3U] = slotNo;
@ -1655,7 +1669,7 @@ bool Modem::setDMRIgnoreCACH_AT(uint8_t slotNo)
if (m_dmrEnabled) { if (m_dmrEnabled) {
uint8_t buffer[4U]; uint8_t buffer[4U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 4U; buffer[1U] = 4U;
buffer[2U] = CMD_DMR_CACH_AT_CTRL; buffer[2U] = CMD_DMR_CACH_AT_CTRL;
buffer[3U] = slotNo; buffer[3U] = slotNo;
@ -1705,7 +1719,7 @@ bool Modem::setState(DVM_STATE state)
{ {
uint8_t buffer[4U]; uint8_t buffer[4U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 4U; buffer[1U] = 4U;
buffer[2U] = CMD_SET_MODE; buffer[2U] = CMD_SET_MODE;
buffer[3U] = state; buffer[3U] = state;
@ -1730,7 +1744,7 @@ bool Modem::sendCWId(const std::string& callsign)
uint8_t buffer[205U]; uint8_t buffer[205U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = length + 3U; buffer[1U] = length + 3U;
buffer[2U] = CMD_SEND_CWID; buffer[2U] = CMD_SEND_CWID;
@ -1790,7 +1804,7 @@ bool Modem::getFirmwareVersion()
for (uint32_t i = 0U; i < 6U; i++) { for (uint32_t i = 0U; i < 6U; i++) {
uint8_t buffer[3U]; uint8_t buffer[3U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_GET_VERSION; buffer[2U] = CMD_GET_VERSION;
@ -1800,7 +1814,7 @@ bool Modem::getFirmwareVersion()
for (uint32_t count = 0U; count < MAX_RESPONSES; count++) { for (uint32_t count = 0U; count < MAX_RESPONSES; count++) {
Thread::sleep(10U); Thread::sleep(10U);
RESP_TYPE_DVM resp = getResponse(true); RESP_TYPE_DVM resp = getResponse();
if (resp == RTM_ERROR) if (resp == RTM_ERROR)
continue; continue;
@ -1858,7 +1872,7 @@ bool Modem::getStatus()
{ {
uint8_t buffer[3U]; uint8_t buffer[3U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_GET_STATUS; buffer[2U] = CMD_GET_STATUS;
@ -1877,7 +1891,7 @@ bool Modem::writeConfig()
::memset(buffer, 0x00U, 25U); ::memset(buffer, 0x00U, 25U);
uint8_t lengthToWrite = 17U; uint8_t lengthToWrite = 17U;
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[2U] = CMD_SET_CONFIG; buffer[2U] = CMD_SET_CONFIG;
buffer[3U] = 0x00U; buffer[3U] = 0x00U;
@ -1993,7 +2007,7 @@ bool Modem::writeSymbolAdjust()
::memset(buffer, 0x00U, 20U); ::memset(buffer, 0x00U, 20U);
uint8_t lengthToWrite = 7U; uint8_t lengthToWrite = 7U;
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[2U] = CMD_SET_SYMLVLADJ; buffer[2U] = CMD_SET_SYMLVLADJ;
buffer[3U] = (uint8_t)(m_dmrSymLevel3Adj + 128); buffer[3U] = (uint8_t)(m_dmrSymLevel3Adj + 128);
@ -2049,7 +2063,7 @@ bool Modem::writeRFParams()
::memset(buffer, 0x00U, 22U); ::memset(buffer, 0x00U, 22U);
uint8_t lengthToWrite = 18U; uint8_t lengthToWrite = 18U;
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[2U] = CMD_SET_RFPARAMS; buffer[2U] = CMD_SET_RFPARAMS;
buffer[3U] = 0x00U; buffer[3U] = 0x00U;
@ -2130,7 +2144,7 @@ bool Modem::readFlash()
for (uint32_t i = 0U; i < 6U; i++) { for (uint32_t i = 0U; i < 6U; i++) {
uint8_t buffer[3U]; uint8_t buffer[3U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_FLSH_READ; buffer[2U] = CMD_FLSH_READ;
@ -2140,7 +2154,7 @@ bool Modem::readFlash()
for (uint32_t count = 0U; count < MAX_RESPONSES; count++) { for (uint32_t count = 0U; count < MAX_RESPONSES; count++) {
Thread::sleep(10U); Thread::sleep(10U);
RESP_TYPE_DVM resp = getResponse(true); RESP_TYPE_DVM resp = getResponse();
if (resp == RTM_ERROR) if (resp == RTM_ERROR)
continue; continue;
@ -2368,9 +2382,8 @@ void Modem::printDebug(const uint8_t* buffer, uint16_t len)
/// <summary> /// <summary>
/// Helper to get the raw response packet from modem. /// Helper to get the raw response packet from modem.
/// </summary> /// </summary>
/// <param name="noReportInvalid">Ignores invalid frame start and does not report as error.</param>
/// <returns>Response type from modem.</returns> /// <returns>Response type from modem.</returns>
RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid) RESP_TYPE_DVM Modem::getResponse()
{ {
m_rspDoubleLength = false; m_rspDoubleLength = false;
@ -2390,22 +2403,23 @@ RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid)
return RTM_TIMEOUT; return RTM_TIMEOUT;
} }
if (m_buffer[0U] != DVM_FRAME_START) { if (m_buffer[0U] != DVM_SHORT_FRAME_START &&
if (!noReportInvalid) { 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]); //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);
}
::memset(m_buffer, 0x00U, BUFFER_LENGTH); ::memset(m_buffer, 0x00U, BUFFER_LENGTH);
return RTM_ERROR; return RTM_ERROR;
} }
if (m_buffer[0U] == DVM_LONG_FRAME_START) {
m_rspDoubleLength = true;
}
//LogDebug(LOG_MODEM, "getResponse(), RESP_START"); //LogDebug(LOG_MODEM, "getResponse(), RESP_START");
m_rspState = RESP_LENGTH1; 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 // get the length of the frame, 1/2
if (m_rspState == RESP_LENGTH1) { if (m_rspState == RESP_LENGTH1) {
int ret = m_port->read(m_buffer + 1U, 1U); int ret = m_port->read(m_buffer + 1U, 1U);
@ -2418,21 +2432,21 @@ RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid)
if (ret == 0) if (ret == 0)
return RTM_TIMEOUT; 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]); LogError(LOG_MODEM, "Invalid length received from the modem, len = %u", m_buffer[1U]);
return RTM_ERROR; return RTM_ERROR;
} }
m_length = m_buffer[1U]; if (m_rspDoubleLength) {
if (m_length == 0U)
m_rspState = RESP_LENGTH2; m_rspState = RESP_LENGTH2;
else m_length = ((m_buffer[1U] & 0xFFU) << 8);
} else {
m_rspState = RESP_TYPE; m_rspState = RESP_TYPE;
m_length = m_buffer[1U];
}
//LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH1, len = %u", m_length); //LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH1, len = %u", m_length);
m_rspDoubleLength = false;
m_rspOffset = 2U; m_rspOffset = 2U;
} }
@ -2449,7 +2463,7 @@ RESP_TYPE_DVM Modem::getResponse(bool noReportInvalid)
if (ret == 0) if (ret == 0)
return RTM_TIMEOUT; return RTM_TIMEOUT;
m_length = m_buffer[2U] + 255U; m_length = (m_length + (m_buffer[2U] & 0xFFU));
m_rspState = RESP_TYPE; m_rspState = RESP_TYPE;
//LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH2, len = %u", m_length); //LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH2, len = %u", m_length);

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2011-2021 Jonathan Naylor, G4KLX * 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 * 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) // 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 #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) // 522 = P25_PDU_FRAME_LENGTH_BYTES + 10 (BUFFER_LEN = P25_PDU_FRAME_LENGTH_BYTES + 10)
#define P25_TX_BUFFER_LEN 442U // 2 frames + pad #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) // 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 #define NXDN_TX_BUFFER_LEN 538U // 11 frames + pad
@ -211,7 +211,8 @@ namespace modem
ADF_GAIN_HIGH = 3U 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_VER = 0x02U;
const uint8_t DVM_CONF_AREA_LEN = 246U; const uint8_t DVM_CONF_AREA_LEN = 246U;
@ -513,7 +514,7 @@ namespace modem
void printDebug(const uint8_t* buffer, uint16_t len); void printDebug(const uint8_t* buffer, uint16_t len);
/// <summary>Helper to get the raw response packet from modem.</summary> /// <summary>Helper to get the raw response packet from modem.</summary>
RESP_TYPE_DVM getResponse(bool noReportInvalid = false); RESP_TYPE_DVM getResponse();
/// <summary>Helper to convert a serial opcode to a string.</summary> /// <summary>Helper to convert a serial opcode to a string.</summary>
std::string cmdToString(uint8_t opcode); std::string cmdToString(uint8_t opcode);

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2021 Jonathan Naylor, G4KLX * Copyright (C) 2021 Jonathan Naylor, G4KLX
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "modem/port/ModemNullPort.h" #include "modem/port/ModemNullPort.h"
@ -115,7 +115,7 @@ void ModemNullPort::getVersion()
{ {
unsigned char reply[200U]; unsigned char reply[200U];
reply[0U] = DVM_FRAME_START; reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = 0U; reply[1U] = 0U;
reply[2U] = CMD_GET_VERSION; reply[2U] = CMD_GET_VERSION;
@ -142,7 +142,7 @@ void ModemNullPort::getStatus()
unsigned char reply[15U]; unsigned char reply[15U];
// Send all sorts of interesting internal values // Send all sorts of interesting internal values
reply[0U] = DVM_FRAME_START; reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = 11U; reply[1U] = 11U;
reply[2U] = CMD_GET_STATUS; reply[2U] = CMD_GET_STATUS;
@ -172,7 +172,7 @@ void ModemNullPort::writeAck(uint8_t type)
{ {
unsigned char reply[4U]; unsigned char reply[4U];
reply[0U] = DVM_FRAME_START; reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = 4U; reply[1U] = 4U;
reply[2U] = CMD_ACK; reply[2U] = CMD_ACK;
reply[3U] = type; reply[3U] = type;
@ -189,7 +189,7 @@ void ModemNullPort::writeNAK(uint8_t opcode, uint8_t err)
{ {
uint8_t reply[5U]; uint8_t reply[5U];
reply[0U] = DVM_FRAME_START; reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = 5U; reply[1U] = 5U;
reply[2U] = CMD_NAK; reply[2U] = CMD_NAK;
reply[3U] = opcode; reply[3U] = opcode;

@ -1260,8 +1260,8 @@ ControlSignaling::ControlSignaling(Control* p25, bool dumpTSBKData, bool debug,
m_verbose(verbose), m_verbose(verbose),
m_debug(debug) m_debug(debug)
{ {
m_rfMBF = new uint8_t[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_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); ::memset(m_rfMBF, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U);
m_adjSiteTable.clear(); m_adjSiteTable.clear();
m_adjSiteUpdateCnt.clear(); m_adjSiteUpdateCnt.clear();
@ -1549,7 +1549,7 @@ void ControlSignaling::writeNet_TSDU(lc::TSBK* tsbk)
void ControlSignaling::writeRF_TSDU_MBF(lc::TSBK* tsbk) void ControlSignaling::writeRF_TSDU_MBF(lc::TSBK* tsbk)
{ {
if (!m_p25->m_enableControl) { 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; m_mbfCnt = 0U;
return; return;
} }
@ -1563,7 +1563,7 @@ void ControlSignaling::writeRF_TSDU_MBF(lc::TSBK* tsbk)
// trunking data is unsupported in simplex operation // trunking data is unsupported in simplex operation
if (!m_p25->m_duplex) { 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; m_mbfCnt = 0U;
return; return;
} }
@ -1636,7 +1636,7 @@ void ControlSignaling::writeRF_TSDU_MBF(lc::TSBK* tsbk)
m_p25->addFrame(data, P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES + 2U); 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; m_mbfCnt = 0U;
return; return;
} }
@ -1669,8 +1669,8 @@ void ControlSignaling::writeRF_TSDU_AMBT(lc::AMBT* ambt)
assert(ambt != nullptr); assert(ambt != nullptr);
DataHeader header = DataHeader(); DataHeader header = DataHeader();
uint8_t pduUserData[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_PDU_UNCONFIRMED_LENGTH_BYTES * P25_MAX_PDU_COUNT); ::memset(pduUserData, 0x00U, P25_MAX_PDU_BLOCKS * P25_PDU_UNCONFIRMED_LENGTH_BYTES);
// Generate TSBK block // Generate TSBK block
ambt->setLastBlock(true); // always set last block -- this a Single Block TSDU ambt->setLastBlock(true); // always set last block -- this a Single Block TSDU

@ -87,26 +87,22 @@ bool Data::process(uint8_t* data, uint32_t len)
m_rfPDUCount = 0U; m_rfPDUCount = 0U;
m_rfPDUBits = 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; 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; 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]; uint8_t buffer[P25_PDU_FRAME_LENGTH_BYTES];
::memset(buffer, 0x00U, P25_MAX_PDU_LENGTH); ::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_PDU_FRAME_LENGTH_BITS);
uint32_t bits = P25Utils::decode(data + 2U, buffer, start, start + P25_LDU_FRAME_LENGTH_BITS);
m_rfPDUBits = Utils::getBits(buffer, m_rfPDU, 0U, 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; uint32_t offset = P25_PREAMBLE_LENGTH_BITS + P25_PDU_FEC_LENGTH_BITS;
if (m_rfPDUCount == 0U) { if (m_rfPDUCount == 0U) {
::memset(buffer, 0x00U, P25_PDU_FEC_LENGTH_BYTES); ::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 // make sure we don't get a PDU with more blocks then we support
if (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_COUNT); 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_rfDataHeader.reset();
m_rfSecondHeader.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()); m_rfData[i].getSerialNo(), m_rfData[i].getFormat(), m_rfData[i].getLastBlock(), m_rfData[i].getSAP(), m_rfData[i].getLLId());
if (m_dumpPDUData) { if (m_dumpPDUData) {
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES];
::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
m_rfData[i].getData(dataBlock); 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()); m_rfData[i].getLastBlock());
if (m_dumpPDUData) { if (m_dumpPDUData) {
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES];
::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
m_rfData[i].getData(dataBlock); 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_netDataBlockCnt = 0U;
m_netPDUCount = 0U; m_netPDUCount = 0U;
::memset(m_netPDU, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U);
m_p25->m_netState = RS_NET_DATA; m_p25->m_netState = RS_NET_DATA;
uint8_t buffer[P25_PDU_FEC_LENGTH_BYTES]; 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 // make sure we don't get a PDU with more blocks then we support
if (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_COUNT); 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_netDataHeader.reset();
m_netSecondHeader.reset(); m_netSecondHeader.reset();
@ -820,18 +818,18 @@ Data::Data(Control* p25, bool dumpPDUData, bool repeatPDU, bool debug, bool verb
m_verbose(verbose), m_verbose(verbose),
m_debug(debug) 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]; m_rfPDU = new uint8_t[P25_PDU_FRAME_LENGTH_BYTES + 2U];
::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_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]; m_netPDU = new uint8_t[P25_PDU_FRAME_LENGTH_BYTES + 2U];
::memset(m_netPDU, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_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]; m_pduUserData = new uint8_t[P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U];
::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_fneRegTable.clear(); m_fneRegTable.clear();
m_connQueueTable.clear(); m_connQueueTable.clear();
@ -876,16 +874,13 @@ void Data::writeNetwork(const uint8_t currentBlock, const uint8_t *data, uint32_
/// <param name="pdu"></param> /// <param name="pdu"></param>
/// <param name="bitlength"></param> /// <param name="bitlength"></param>
/// <param name="noNulls"></param> /// <param name="noNulls"></param>
/// <remarks>This simply takes data packed into m_rfPDU and transmits it.</remarks>
void Data::writeRF_PDU(const uint8_t* pdu, uint32_t bitLength, bool noNulls) void Data::writeRF_PDU(const uint8_t* pdu, uint32_t bitLength, bool noNulls)
{ {
assert(pdu != nullptr); assert(pdu != nullptr);
assert(bitLength > 0U); assert(bitLength > 0U);
uint8_t data[P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U]; uint8_t data[P25_PDU_FRAME_LENGTH_BYTES + 2U];
::memset(data, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); ::memset(data, 0x00U, P25_PDU_FRAME_LENGTH_BYTES + 2U);
// Utils::dump(2U, "!!! *Raw PDU Frame Data - pdu", pdu, bitLength / 8U);
// Add the data // Add the data
uint32_t newBitLength = P25Utils::encode(pdu, data + 2U, bitLength); 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 // Add idle bits
P25Utils::addIdleBits(data + 2U, newBitLength, true, true); P25Utils::addIdleBits(data + 2U, newBitLength, true, true);
// Utils::dump(2U, "!!! *P25_DUID_PDU - data", data + 2U, newByteLength);
if (m_p25->m_duplex) { if (m_p25->m_duplex) {
data[0U] = modem::TAG_DATA; data[0U] = modem::TAG_DATA;
data[1U] = 0x00U; 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()); m_netData[i].getSerialNo(), m_netData[i].getFormat(), m_netData[i].getLastBlock(), m_netData[i].getSAP(), m_netData[i].getLLId());
if (m_dumpPDUData) { if (m_dumpPDUData) {
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES];
::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
m_netData[i].getData(dataBlock); 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()); m_netData[i].getLastBlock());
if (m_dumpPDUData) { if (m_dumpPDUData) {
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES];
::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
m_netData[i].getData(dataBlock); 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()); m_rfData[i].getSerialNo(), m_rfData[i].getFormat(), m_rfData[i].getLastBlock(), m_rfData[i].getSAP(), m_rfData[i].getLLId());
if (m_dumpPDUData) { if (m_dumpPDUData) {
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES];
::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
m_rfData[i].getData(dataBlock); 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()); m_rfData[i].getLastBlock());
if (m_dumpPDUData) { if (m_dumpPDUData) {
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES];
::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0xAAU, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
m_rfData[i].getData(dataBlock); 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) if (ackClass == PDU_ACK_CLASS_ACK && ackType != PDU_ACK_TYPE_ACK)
return; 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; uint32_t offset = P25_PREAMBLE_LENGTH_BITS;
uint8_t data[bitLength / 8U]; uint8_t data[bitLength / 8U];

@ -339,7 +339,7 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp
uint8_t buffer[250U]; uint8_t buffer[250U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = dataLen + 2U; buffer[1U] = dataLen + 2U;
buffer[2U] = CMD_P25_DATA; 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) { 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: case CMD_CAL_DATA:
{ {
if (rspDblLen) {
LogError(LOG_MODEM, "CMD_CAL_DATA double length?; len = %u", len);
break;
}
bool inverted = (buffer[3U] == 0x80U); bool inverted = (buffer[3U] == 0x80U);
short high = buffer[4U] << 8 | buffer[5U]; short high = buffer[4U] << 8 | buffer[5U];
short low = buffer[6U] << 8 | buffer[7U]; short low = buffer[6U] << 8 | buffer[7U];
@ -375,6 +386,11 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp
break; break;
case CMD_RSSI_DATA: 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 max = buffer[3U] << 8 | buffer[4U];
uint16_t min = buffer[5U] << 8 | buffer[6U]; uint16_t min = buffer[5U] << 8 | buffer[6U];
uint16_t ave = buffer[7U] << 8 | buffer[8U]; 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; break;
/** Digital Mobile Radio */
case CMD_DMR_DATA1: case CMD_DMR_DATA1:
case CMD_DMR_DATA2: case CMD_DMR_DATA2:
{
if (rspDblLen) {
LogError(LOG_MODEM, "CMD_DMR_DATA double length?; len = %u", len);
break;
}
processDMRBER(buffer + 4U, buffer[3]); processDMRBER(buffer + 4U, buffer[3]);
break; }
break;
case CMD_DMR_LOST1: case CMD_DMR_LOST1:
case CMD_DMR_LOST2: 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)); 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) { if (m_dmrEnabled) {
@ -402,12 +431,18 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp
} }
break; break;
/** Project 25 */
case CMD_P25_DATA: case CMD_P25_DATA:
processP25BER(buffer + 4U); processP25BER(buffer + 4U);
break; break;
case CMD_P25_LOST: 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)); 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) { if (m_p25Enabled) {
@ -420,12 +455,25 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp
} }
break; break;
/** Next Generation Digital Narrowband */
case CMD_NXDN_DATA: case CMD_NXDN_DATA:
{
if (rspDblLen) {
LogError(LOG_MODEM, "CMD_NXDN_DATA double length?; len = %u", len);
break;
}
processNXDNBER(buffer + 4U); processNXDNBER(buffer + 4U);
break; }
break;
case CMD_NXDN_LOST: 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)); 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) { if (m_nxdnEnabled) {
@ -438,6 +486,7 @@ bool HostSetup::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspTyp
} }
break; break;
/** General */
case CMD_GET_STATUS: case CMD_GET_STATUS:
{ {
m_isHotspot = (buffer[3U] & 0x01U) == 0x01U; m_isHotspot = (buffer[3U] & 0x01U) == 0x01U;
@ -870,7 +919,7 @@ bool HostSetup::setTransmit()
uint8_t buffer[50U]; uint8_t buffer[50U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 4U; buffer[1U] = 4U;
buffer[2U] = CMD_CAL_DATA; buffer[2U] = CMD_CAL_DATA;
buffer[3U] = m_transmit ? 0x01U : 0x00U; 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]; uint8_t pduBuffer[P25_LDU_FRAME_LENGTH_BYTES];
uint32_t bits = P25Utils::decode(buffer, pduBuffer, 0, P25_LDU_FRAME_LENGTH_BITS); 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]; uint8_t* rfPDU = new uint8_t[P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U];
::memset(rfPDU, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); ::memset(rfPDU, 0x00U, P25_MAX_PDU_BLOCKS * P25_PDU_CONFIRMED_LENGTH_BYTES + 2U);
uint32_t rfPDUBits = 0U; uint32_t rfPDUBits = 0U;
for (uint32_t i = 0U; i < bits; i++, rfPDUBits++) { for (uint32_t i = 0U; i < bits; i++, rfPDUBits++) {
@ -1481,7 +1530,7 @@ bool HostSetup::writeConfig(uint8_t modeOverride)
::memset(buffer, 0x00U, 25U); ::memset(buffer, 0x00U, 25U);
uint8_t lengthToWrite = 17U; uint8_t lengthToWrite = 17U;
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[2U] = CMD_SET_CONFIG; buffer[2U] = CMD_SET_CONFIG;
buffer[3U] = 0x00U; buffer[3U] = 0x00U;
@ -1591,7 +1640,7 @@ bool HostSetup::writeRFParams()
::memset(buffer, 0x00U, 22U); ::memset(buffer, 0x00U, 22U);
uint8_t lengthToWrite = 18U; uint8_t lengthToWrite = 18U;
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[2U] = CMD_SET_RFPARAMS; buffer[2U] = CMD_SET_RFPARAMS;
buffer[3U] = 0x00U; buffer[3U] = 0x00U;
@ -1661,7 +1710,7 @@ bool HostSetup::writeSymbolAdjust()
::memset(buffer, 0x00U, 20U); ::memset(buffer, 0x00U, 20U);
uint8_t lengthToWrite = 7U; uint8_t lengthToWrite = 7U;
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[2U] = CMD_SET_SYMLVLADJ; buffer[2U] = CMD_SET_SYMLVLADJ;
m_conf["system"]["modem"]["repeater"]["dmrSymLvl3Adj"] = __INT_STR(m_modem->m_dmrSymLevel3Adj); m_conf["system"]["modem"]["repeater"]["dmrSymLvl3Adj"] = __INT_STR(m_modem->m_dmrSymLevel3Adj);
@ -1705,7 +1754,7 @@ bool HostSetup::writeFifoLength()
uint8_t buffer[9U]; uint8_t buffer[9U];
::memset(buffer, 0x00U, 9U); ::memset(buffer, 0x00U, 9U);
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 9U; buffer[1U] = 9U;
buffer[2U] = CMD_SET_BUFFERS; buffer[2U] = CMD_SET_BUFFERS;
@ -1750,7 +1799,7 @@ bool HostSetup::readFlash()
uint8_t buffer[3U]; uint8_t buffer[3U];
::memset(buffer, 0x00U, 3U); ::memset(buffer, 0x00U, 3U);
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 3U; buffer[1U] = 3U;
buffer[2U] = CMD_FLSH_READ; buffer[2U] = CMD_FLSH_READ;
@ -1892,7 +1941,7 @@ bool HostSetup::eraseFlash()
uint8_t buffer[249U]; uint8_t buffer[249U];
::memset(buffer, 0x00U, 249U); ::memset(buffer, 0x00U, 249U);
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 249U; buffer[1U] = 249U;
buffer[2U] = CMD_FLSH_WRITE; buffer[2U] = CMD_FLSH_WRITE;
@ -1926,7 +1975,7 @@ bool HostSetup::writeFlash()
uint8_t buffer[249U]; uint8_t buffer[249U];
::memset(buffer, 0x00U, 249U); ::memset(buffer, 0x00U, 249U);
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 249U; buffer[1U] = 249U;
buffer[2U] = CMD_FLSH_WRITE; buffer[2U] = CMD_FLSH_WRITE;
@ -2070,7 +2119,7 @@ void HostSetup::getStatus()
{ {
uint8_t buffer[50U]; uint8_t buffer[50U];
buffer[0U] = DVM_FRAME_START; buffer[0U] = DVM_SHORT_FRAME_START;
buffer[1U] = 4U; buffer[1U] = 4U;
buffer[2U] = CMD_GET_STATUS; buffer[2U] = CMD_GET_STATUS;

Loading…
Cancel
Save

Powered by TurnKey Linux.