correct bad handling for signal and compact fields of the TIA-102 control octet; enhance how the length of a TIA-102 full rate voice frame is determined; better handle initialization of the additional data fields for a TIA-102 full rate voice frame; correct bug using LDU2 frame 10 vs LDU2 frame 18 for LSD data on a full rate voice frame; implement a naive approach to performing superframe counting; correct bug causing the first full rate voice frames to never be transmitted for LDU1 or LDU2; remove assertion check for control port;

82-dvmbridge---implement-notch-filter-for-2175hz-trc-guard-tone
Bryan Biedenkapp 1 year ago
parent 95a8d269be
commit a82f848de4

@ -49,8 +49,8 @@ bool ControlOctet::decode(const uint8_t* data)
{
assert(data != nullptr);
m_signal = (data[0U] & 0x07U) == 0x07U; // Signal Flag
m_compact = (data[0U] & 0x06U) == 0x06U; // Compact Flag
m_signal = (data[0U] & 0x80U) == 0x80U; // Signal Flag
m_compact = (data[0U] & 0x40U) == 0x40U; // Compact Flag
m_blockHeaderCnt = (uint8_t)(data[0U] & 0x3FU); // Block Header Count
return true;
@ -62,7 +62,7 @@ void ControlOctet::encode(uint8_t* data)
{
assert(data != nullptr);
data[0U] = (uint8_t)((m_signal ? 0x07U : 0x00U) + // Signal Flag
(m_compact ? 0x06U : 0x00U) + // Control Flag
data[0U] = (uint8_t)((m_signal ? 0x80U : 0x00U) + // Signal Flag
(m_compact ? 0x40U : 0x00U) + // Control Flag
(m_blockHeaderCnt & 0x3F));
}

@ -38,6 +38,8 @@ FullRateVoice::FullRateVoice() :
{
imbeData = new uint8_t[IMBE_BUF_LEN];
::memset(imbeData, 0x00U, IMBE_BUF_LEN);
additionalData = new uint8_t[ADDITIONAL_LENGTH];
::memset(additionalData, 0x00U, ADDITIONAL_LENGTH);
}
/* Initializes a instance of the FullRateVoice class. */
@ -65,6 +67,21 @@ FullRateVoice::~FullRateVoice()
delete[] additionalData;
}
/* */
uint8_t FullRateVoice::getLength()
{
if (isVoice9or18()) {
return LENGTH_918;
}
if (isVoice3thru8() || isVoice12thru17()) {
return LENGTH;
}
return LENGTH_121011;
}
/* Decode a full rate voice frame. */
bool FullRateVoice::decode(const uint8_t* data)
@ -85,25 +102,14 @@ bool FullRateVoice::decode(const uint8_t* data)
m_superframeCnt = (uint8_t)((data[13U] >> 2) & 0x03U); // Superframe Counter
m_busy = (uint8_t)(data[13U] & 0x03U);
if (isVoice3thru8() || isVoice12thru17() || isVoice9or10()) {
if (additionalData != nullptr)
delete additionalData;
additionalData = new uint8_t[ADDITIONAL_LENGTH];
if (isVoice3thru8() || isVoice12thru17() || isVoice9or18()) {
::memset(additionalData, 0x00U, ADDITIONAL_LENGTH);
if (isVoice9or10()) {
// CAI 9 and 10 are 3 bytes of additional data not 4
if (isVoice9or18()) {
// CAI 9 and 18 are 3 bytes of additional data not 4
::memcpy(additionalData, data + 14U, ADDITIONAL_LENGTH - 1U);
} else {
uint8_t buffer[ADDITIONAL_LENGTH - 1U];
::memset(buffer, 0x00U, ADDITIONAL_LENGTH - 1U);
::memcpy(buffer, data + 14U, ADDITIONAL_LENGTH - 1U);
buffer[2U] &= 0xC0U; // mask low bits
uint32_t offset = 0;
for (uint8_t i = 0; i < ADDITIONAL_LENGTH - 1U; i++, offset += 6) {
Utils::hex2Bin(additionalData[i], buffer, offset);
}
::memcpy(additionalData, data + 14U, ADDITIONAL_LENGTH);
}
} else {
if (additionalData != nullptr)
@ -130,22 +136,12 @@ void FullRateVoice::encode(uint8_t* data)
data[13U] = (uint8_t)(((m_superframeCnt & 0x03U) << 2) + // Superframe Count
(m_busy & 0x03U)); // Busy Status
if ((isVoice3thru8() || isVoice12thru17() || isVoice9or10()) &&
additionalData != nullptr) {
if (isVoice9or10()) {
// CAI 9 and 10 are 3 bytes of additional data not 4
if (isVoice3thru8() || isVoice12thru17() || isVoice9or18()) {
if (isVoice9or18()) {
// CAI 9 and 18 are 3 bytes of additional data not 4
::memcpy(data + 14U, additionalData, ADDITIONAL_LENGTH - 1U);
} else {
uint8_t buffer[ADDITIONAL_LENGTH - 1U];
::memset(buffer, 0x00U, ADDITIONAL_LENGTH - 1U);
::memcpy(buffer, additionalData, ADDITIONAL_LENGTH - 1U);
uint32_t offset = 0;
for (uint8_t i = 0; i < ADDITIONAL_LENGTH - 1U; i++, offset += 6) {
buffer[i] = Utils::bin2Hex(additionalData, offset);
}
::memcpy(data + 14U, buffer, ADDITIONAL_LENGTH - 1U);
::memcpy(data + 14U, additionalData, ADDITIONAL_LENGTH);
}
}
}
@ -180,9 +176,9 @@ bool FullRateVoice::isVoice12thru17()
/* Helper indicating if the frame is voice 9 or 10. */
bool FullRateVoice::isVoice9or10()
bool FullRateVoice::isVoice9or18()
{
if ( (m_frameType == DFSIFrameType::LDU1_VOICE9) || (m_frameType == DFSIFrameType::LDU2_VOICE10) ) {
if ( (m_frameType == DFSIFrameType::LDU1_VOICE9) || (m_frameType == DFSIFrameType::LDU2_VOICE18) ) {
return true;
} else {
return false;

@ -37,6 +37,7 @@ namespace p25
* @brief Implements a P25 full rate voice packet.
* \code{.unparsed}
* CAI Frames 1, 2, 10 and 11.
* 14 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -52,6 +53,7 @@ namespace p25
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* CAI Frames 3 - 8.
* 18 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -69,6 +71,7 @@ namespace p25
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* CAI Frames 12 - 17.
* 18 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -86,6 +89,7 @@ namespace p25
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* CAI Frames 9 and 10.
* 17 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -108,6 +112,7 @@ namespace p25
* the layout with 8-bit aligned IMBE blocks instead of message vectors:
*
* CAI Frames 1, 2, 10 and 11.
* 14 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -123,6 +128,7 @@ namespace p25
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* CAI Frames 3 - 8.
* 18 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -140,6 +146,7 @@ namespace p25
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* CAI Frames 12 - 17.
* 18 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -156,7 +163,8 @@ namespace p25
* |Syn|R| Status | Rsvd |
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* CAI Frames 9 and 10.
* CAI Frames 9 and 18.
* 17 bytes
*
* Byte 0 1 2 3
* Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@ -177,6 +185,9 @@ namespace p25
*/
class HOST_SW_API FullRateVoice {
public:
static const uint8_t LENGTH_121011 = 14U;
static const uint8_t LENGTH_918 = 17U;
static const uint8_t LENGTH = 18U;
static const uint8_t ADDITIONAL_LENGTH = 4U;
static const uint8_t IMBE_BUF_LEN = 11U;
@ -195,9 +206,16 @@ namespace p25
*/
~FullRateVoice();
/**
* @brief
* @returns uint8_t
*/
uint8_t getLength();
/**
* @brief Decode a full rate voice frame.
* @param[in] data Buffer to containing FullRateVoice to decode.
* @returns bool
*/
bool decode(const uint8_t* data);
/**
@ -247,10 +265,10 @@ namespace p25
*/
bool isVoice12thru17();
/**
* @brief Helper indicating if the frame is voice 9 or 10.
* @returns bool True, if frame is voice 9, or 10, otherwise false.
* @brief Helper indicating if the frame is voice 9 or 18.
* @returns bool True, if frame is voice 9, or 18, otherwise false.
*/
bool isVoice9or10();
bool isVoice9or18();
};
} // namespace frames
} // namespace dfsi

@ -585,7 +585,7 @@ bool Host::createModem()
LogInfo(" DFSI Use FSC: %s", useFSCForUDP ? "yes" : "no");
LogInfo(" DFSI FSC Heartbeat: %us", fscHeartbeat);
LogInfo(" DFSI FSC Initiator: %s", fscInitiator ? "yes" : "no");
LogInfo(" DFSI FSC TIA Frames: %s", dfsiTIAMode ? "yes" : "no");
LogInfo(" DFSI TIA-102 Frames: %s", dfsiTIAMode ? "yes" : "no");
}
}

@ -44,6 +44,7 @@ ModemV24::ModemV24(port::IModemPort* port, bool duplex, uint32_t p25QueueSize, u
false, false, dumpModemStatus, trace, debug),
m_rtrt(rtrt),
m_diu(diu),
m_superFrameCnt(0U),
m_audio(),
m_nid(nullptr),
m_txP25Queue(p25TxQueueSize, "TX P25 Queue"),
@ -1253,6 +1254,7 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length)
case BlockType::FULL_RATE_VOICE:
{
FullRateVoice voice = FullRateVoice();
//m_superFrameCnt = voice.getSuperframeCnt();
voice.decode(dfsiData + dataOffs);
DFSIFrameType::E frameType = voice.getFrameType();
@ -1742,6 +1744,7 @@ uint16_t ModemV24::generateNID(DUID::E duid)
void ModemV24::startOfStreamTIA(const p25::lc::LC& control)
{
m_txCallInProgress = true;
m_superFrameCnt = 0U;
p25::lc::LC lc = p25::lc::LC(control);
@ -1864,6 +1867,8 @@ void ModemV24::startOfStreamTIA(const p25::lc::LC& control)
void ModemV24::endOfStreamTIA()
{
m_superFrameCnt = 0U;
uint16_t length = 0U;
uint8_t buffer[2U];
::memset(buffer, 0x00U, 2U);
@ -2474,37 +2479,24 @@ void ModemV24::convertFromAirTIA(uint8_t* data, uint32_t length)
break;
}
// For n=0 (VHDR1/10) case we create the buffer in the switch, for all other frame types we do that here
if (n != 0) {
buffer = new uint8_t[P25_PDU_FRAME_LENGTH_BYTES];
::memset(buffer, 0x00U, P25_PDU_FRAME_LENGTH_BYTES);
// generate control octet
ControlOctet ctrl = ControlOctet();
ctrl.setBlockHeaderCnt(2U);
ctrl.encode(buffer);
bufferSize += ControlOctet::LENGTH;
// generate block header
BlockHeader hdr = BlockHeader();
hdr.setBlockType(BlockType::FULL_RATE_VOICE);
hdr.encode(buffer + 1U);
bufferSize += BlockHeader::LENGTH;
// generate block header
hdr.setBlockType(BlockType::START_OF_STREAM);
hdr.encode(buffer + 2U);
bufferSize += BlockHeader::LENGTH;
voice.encode(buffer + bufferSize);
bufferSize += FullRateVoice::LENGTH;
// generate start of stream
StartOfStream start = StartOfStream();
start.setNID(generateNID());
start.encode(buffer + bufferSize);
bufferSize += StartOfStream::LENGTH;
}
buffer = new uint8_t[P25_PDU_FRAME_LENGTH_BYTES];
::memset(buffer, 0x00U, P25_PDU_FRAME_LENGTH_BYTES);
// generate control octet
ControlOctet ctrl = ControlOctet();
ctrl.setBlockHeaderCnt(1U);
ctrl.encode(buffer);
bufferSize += ControlOctet::LENGTH;
// generate block header
BlockHeader hdr = BlockHeader();
hdr.setBlockType(BlockType::FULL_RATE_VOICE);
hdr.encode(buffer + 1U);
bufferSize += BlockHeader::LENGTH;
voice.setSuperframeCnt(m_superFrameCnt);
voice.encode(buffer + bufferSize);
bufferSize += voice.getLength(); // 18, 17 or 14 depending on voice frame type
if (buffer != nullptr) {
if (m_trace) {
@ -2515,5 +2507,14 @@ void ModemV24::convertFromAirTIA(uint8_t* data, uint32_t length)
delete[] buffer;
}
}
// bryanb: this is a naive way of incrementing the superframe counter, we basically just increment it after
// processing and LDU2
if (duid == DUID::LDU2) {
if (m_superFrameCnt == 255U)
m_superFrameCnt = 0U;
else
m_superFrameCnt++;
}
}
}

@ -302,6 +302,8 @@ namespace modem
bool m_rtrt;
bool m_diu;
uint8_t m_superFrameCnt;
p25::Audio m_audio;
p25::NID* m_nid;

@ -79,7 +79,6 @@ V24UDPPort::V24UDPPort(uint32_t peerId, const std::string& address, uint16_t mod
assert(peerId > 0U);
assert(!address.empty());
assert(modemPort > 0U);
assert(controlPort > 0U);
if (controlPort > 0U && useFSC) {
m_controlSocket = new Socket(controlPort);

Loading…
Cancel
Save

Powered by TurnKey Linux.