diff --git a/src/common/p25/dfsi/frames/ControlOctet.cpp b/src/common/p25/dfsi/frames/ControlOctet.cpp index 0308b526..6f4a6e20 100644 --- a/src/common/p25/dfsi/frames/ControlOctet.cpp +++ b/src/common/p25/dfsi/frames/ControlOctet.cpp @@ -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)); } diff --git a/src/common/p25/dfsi/frames/FullRateVoice.cpp b/src/common/p25/dfsi/frames/FullRateVoice.cpp index c3b50a63..d334e84f 100644 --- a/src/common/p25/dfsi/frames/FullRateVoice.cpp +++ b/src/common/p25/dfsi/frames/FullRateVoice.cpp @@ -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; diff --git a/src/common/p25/dfsi/frames/FullRateVoice.h b/src/common/p25/dfsi/frames/FullRateVoice.h index afde4e83..100fa7b9 100644 --- a/src/common/p25/dfsi/frames/FullRateVoice.h +++ b/src/common/p25/dfsi/frames/FullRateVoice.h @@ -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 diff --git a/src/host/Host.Config.cpp b/src/host/Host.Config.cpp index 73141abe..86410d98 100644 --- a/src/host/Host.Config.cpp +++ b/src/host/Host.Config.cpp @@ -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"); } } diff --git a/src/host/modem/ModemV24.cpp b/src/host/modem/ModemV24.cpp index 07206c11..7d7deba3 100644 --- a/src/host/modem/ModemV24.cpp +++ b/src/host/modem/ModemV24.cpp @@ -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++; + } } } diff --git a/src/host/modem/ModemV24.h b/src/host/modem/ModemV24.h index bd78e475..cb48e31a 100644 --- a/src/host/modem/ModemV24.h +++ b/src/host/modem/ModemV24.h @@ -302,6 +302,8 @@ namespace modem bool m_rtrt; bool m_diu; + uint8_t m_superFrameCnt; + p25::Audio m_audio; p25::NID* m_nid; diff --git a/src/host/modem/port/specialized/V24UDPPort.cpp b/src/host/modem/port/specialized/V24UDPPort.cpp index 44e69441..fc3f2018 100644 --- a/src/host/modem/port/specialized/V24UDPPort.cpp +++ b/src/host/modem/port/specialized/V24UDPPort.cpp @@ -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);