From 87ad34f539d1a69b450d259fd56276547095cb9e Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Wed, 4 Feb 2026 13:40:26 -0500 Subject: [PATCH] properly set the V.24 Tx buffer size to the FIFO length like done for air and hotspot modems; pass whether or not the frame being written to the modem is an immediate frame; modify V.24 modem to properly maintain two independant buffers, one for background/normal priority frames, and one for immediate priority frames (this helps with CC mode delays, there are more buffering issues, likely at the modem to mitgate but thats a future project); --- src/host/Host.Config.cpp | 2 +- src/host/Host.DMR.cpp | 6 ++- src/host/Host.NXDN.cpp | 3 +- src/host/Host.P25.cpp | 3 +- src/host/dmr/Control.cpp | 6 +-- src/host/dmr/Control.h | 3 +- src/host/dmr/Slot.cpp | 8 +++- src/host/dmr/Slot.h | 3 +- src/host/modem/Modem.cpp | 18 +++---- src/host/modem/Modem.h | 15 ++++-- src/host/modem/ModemV24.cpp | 93 ++++++++++++++++++++++++++----------- src/host/modem/ModemV24.h | 19 ++++++-- src/host/nxdn/Control.cpp | 8 +++- src/host/nxdn/Control.h | 3 +- src/host/p25/Control.cpp | 8 +++- src/host/p25/Control.h | 3 +- 16 files changed, 141 insertions(+), 60 deletions(-) diff --git a/src/host/Host.Config.cpp b/src/host/Host.Config.cpp index 75c70c39..76630916 100644 --- a/src/host/Host.Config.cpp +++ b/src/host/Host.Config.cpp @@ -721,7 +721,7 @@ bool Host::createModem() } if (m_isModemDFSI) { - m_modem = new ModemV24(modemPort, m_duplex, m_p25QueueSizeBytes, m_p25QueueSizeBytes, rtrt, jitter, + m_modem = new ModemV24(modemPort, m_duplex, m_p25QueueSizeBytes, p25FifoLength, rtrt, jitter, dumpModemStatus, displayModemDebugMessages, trace, debug); ((ModemV24*)m_modem)->setCallTimeout(dfsiCallTimeout); ((ModemV24*)m_modem)->setTIAFormat(dfsiTIAMode); diff --git a/src/host/Host.DMR.cpp b/src/host/Host.DMR.cpp index da87c784..54cac4a4 100644 --- a/src/host/Host.DMR.cpp +++ b/src/host/Host.DMR.cpp @@ -267,7 +267,8 @@ void* Host::threadDMRWriter1(void* arg) } } - uint32_t len = host->m_dmr->getFrame(1U, data); + bool imm = false; + uint32_t len = host->m_dmr->getFrame(1U, data, &imm); if (len > 0U) { // if the state is idle; set to DMR, start mode timer and start DMR idle frames if (host->m_state == STATE_IDLE) { @@ -551,7 +552,8 @@ void* Host::threadDMRWriter2(void* arg) } } - uint32_t len = host->m_dmr->getFrame(2U, data); + bool imm = false; + uint32_t len = host->m_dmr->getFrame(2U, data, &imm); if (len > 0U) { // if the state is idle; set to DMR, start mode timer and start DMR idle frames if (host->m_state == STATE_IDLE) { diff --git a/src/host/Host.NXDN.cpp b/src/host/Host.NXDN.cpp index d478bd5f..a165d631 100644 --- a/src/host/Host.NXDN.cpp +++ b/src/host/Host.NXDN.cpp @@ -213,7 +213,8 @@ void* Host::threadNXDNWriter(void* arg) } } - uint32_t len = host->m_nxdn->getFrame(data); + bool imm = false; + uint32_t len = host->m_nxdn->getFrame(data, &imm); if (len > 0U) { // if the state is idle; set to NXDN and start mode timer if (host->m_state == STATE_IDLE) { diff --git a/src/host/Host.P25.cpp b/src/host/Host.P25.cpp index eb0c7ff9..1db6a6ba 100644 --- a/src/host/Host.P25.cpp +++ b/src/host/Host.P25.cpp @@ -256,7 +256,8 @@ void* Host::threadP25Writer(void* arg) if (nextLen > 0U) { bool ret = host->m_modem->hasP25Space(nextLen); if (ret) { - uint32_t len = host->m_p25->getFrame(data); + bool imm = false; + uint32_t len = host->m_p25->getFrame(data, &imm); if (len > 0U) { // if the state is idle; set to P25 and start mode timer if (host->m_state == STATE_IDLE) { diff --git a/src/host/dmr/Control.cpp b/src/host/dmr/Control.cpp index 39557903..24a2e4bb 100644 --- a/src/host/dmr/Control.cpp +++ b/src/host/dmr/Control.cpp @@ -372,15 +372,15 @@ bool Control::isQueueFull(uint32_t slotNo) /* Get a data frame for slot, from data ring buffer. */ -uint32_t Control::getFrame(uint32_t slotNo, uint8_t* data) +uint32_t Control::getFrame(uint32_t slotNo, uint8_t* data, bool *imm) { assert(data != nullptr); switch (slotNo) { case 1U: - return m_slot1->getFrame(data); + return m_slot1->getFrame(data, imm); case 2U: - return m_slot2->getFrame(data); + return m_slot2->getFrame(data, imm); default: LogError(LOG_DMR, "DMR, invalid slot, slotNo = %u", slotNo); return 0U; diff --git a/src/host/dmr/Control.h b/src/host/dmr/Control.h index e9741e56..10161ba8 100644 --- a/src/host/dmr/Control.h +++ b/src/host/dmr/Control.h @@ -159,9 +159,10 @@ namespace dmr * @brief Get frame data from data ring buffer. * @param slotNo DMR slot number. * @param[out] data Buffer to store frame data. + * @param[out] imm Flag indicating whether the frame is immediate. * @returns uint32_t Length of frame data retrieved. */ - uint32_t getFrame(uint32_t slotNo, uint8_t* data); + uint32_t getFrame(uint32_t slotNo, uint8_t* data, bool *imm = nullptr); /** @} */ /** @name Data Clocking */ diff --git a/src/host/dmr/Slot.cpp b/src/host/dmr/Slot.cpp index 874bf8ef..bb00a933 100644 --- a/src/host/dmr/Slot.cpp +++ b/src/host/dmr/Slot.cpp @@ -361,7 +361,7 @@ bool Slot::isQueueFull() /* Get frame data from data ring buffer. */ -uint32_t Slot::getFrame(uint8_t* data) +uint32_t Slot::getFrame(uint8_t* data, bool* imm) { assert(data != nullptr); @@ -374,10 +374,16 @@ uint32_t Slot::getFrame(uint8_t* data) // tx immediate queue takes priority if (!m_txImmQueue.isEmpty()) { + if (imm != nullptr) + *imm = true; + m_txImmQueue.get(&len, 1U); m_txImmQueue.get(data, len); } else { + if (imm != nullptr) + *imm = false; + m_txQueue.get(&len, 1U); m_txQueue.get(data, len); } diff --git a/src/host/dmr/Slot.h b/src/host/dmr/Slot.h index 3f139536..ba96aefb 100644 --- a/src/host/dmr/Slot.h +++ b/src/host/dmr/Slot.h @@ -146,9 +146,10 @@ namespace dmr /** * @brief Get frame data from data ring buffer. * @param[out] data Buffer to store frame data. + * @param[out] imm Flag indicating whether the frame is immediate. * @returns uint32_t Length of frame data retrieved. */ - uint32_t getFrame(uint8_t* data); + uint32_t getFrame(uint8_t* data, bool* imm); /** * @brief Process a data frames from the network. diff --git a/src/host/modem/Modem.cpp b/src/host/modem/Modem.cpp index 49625ab2..91cbdcbe 100644 --- a/src/host/modem/Modem.cpp +++ b/src/host/modem/Modem.cpp @@ -1371,7 +1371,7 @@ void Modem::injectNXDNFrame(const uint8_t* data, uint32_t length) /* Writes DMR Slot 1 frame data to the DMR Slot 1 ring buffer. */ -bool Modem::writeDMRFrame1(const uint8_t* data, uint32_t length) +bool Modem::writeDMRFrame1(const uint8_t* data, uint32_t length, bool imm) { assert(data != nullptr); assert(length > 0U); @@ -1404,7 +1404,7 @@ bool Modem::writeDMRFrame1(const uint8_t* data, uint32_t length) if (m_trace) Utils::dump(1U, "Modem::writeDMRFrame1(), Immediate TX DMR Data 1", buffer + 3U, length - 1U); - int ret = write(buffer, len); + int ret = write(buffer, len, imm); if (ret != int(len)) { LogError(LOG_MODEM, "Error writing DMR slot 1 data"); return false; @@ -1425,7 +1425,7 @@ bool Modem::writeDMRFrame1(const uint8_t* data, uint32_t length) /* Writes DMR Slot 2 frame data to the DMR Slot 2 ring buffer. */ -bool Modem::writeDMRFrame2(const uint8_t* data, uint32_t length) +bool Modem::writeDMRFrame2(const uint8_t* data, uint32_t length, bool imm) { assert(data != nullptr); assert(length > 0U); @@ -1458,7 +1458,7 @@ bool Modem::writeDMRFrame2(const uint8_t* data, uint32_t length) if (m_trace) Utils::dump(1U, "Modem::writeDMRFrame2(), Immediate TX DMR Data 2", buffer + 3U, length - 1U); - int ret = write(buffer, len); + int ret = write(buffer, len, imm); if (ret != int(len)) { LogError(LOG_MODEM, "Error writing DMR slot 2 data"); return false; @@ -1479,7 +1479,7 @@ bool Modem::writeDMRFrame2(const uint8_t* data, uint32_t length) /* Writes P25 frame data to the P25 ring buffer. */ -bool Modem::writeP25Frame(const uint8_t* data, uint32_t length) +bool Modem::writeP25Frame(const uint8_t* data, uint32_t length, bool imm) { assert(data != nullptr); assert(length > 0U); @@ -1523,7 +1523,7 @@ bool Modem::writeP25Frame(const uint8_t* data, uint32_t length) if (m_trace) Utils::dump(1U, "Modem::writeP25Frame(), Immediate TX P25 Data", buffer + 3U, length - 3U); - int ret = write(buffer, len); + int ret = write(buffer, len, imm); if (ret != int(len)) { LogError(LOG_MODEM, "Error writing P25 data"); return false; @@ -1544,7 +1544,7 @@ bool Modem::writeP25Frame(const uint8_t* data, uint32_t length) /* Writes NXDN frame data to the NXDN ring buffer. */ -bool Modem::writeNXDNFrame(const uint8_t* data, uint32_t length) +bool Modem::writeNXDNFrame(const uint8_t* data, uint32_t length, bool imm) { assert(data != nullptr); assert(length > 0U); @@ -1577,7 +1577,7 @@ bool Modem::writeNXDNFrame(const uint8_t* data, uint32_t length) if (m_trace) Utils::dump(1U, "Modem::writeNXDNFrame(), Immediate TX NXDN Data", buffer + 3U, length - 1U); - int ret = write(buffer, len); + int ret = write(buffer, len, imm); if (ret != int(len)) { LogError(LOG_MODEM, "Error writing NXDN data"); return false; @@ -1704,7 +1704,7 @@ bool Modem::setDMRIgnoreCACH_AT(uint8_t slotNo) /* Writes raw data to the air interface modem. */ -int Modem::write(const uint8_t* data, uint32_t length) +int Modem::write(const uint8_t* data, uint32_t length, bool imm) { return m_port->write(data, length); } diff --git a/src/host/modem/Modem.h b/src/host/modem/Modem.h index 8c2b145c..83bd70a7 100644 --- a/src/host/modem/Modem.h +++ b/src/host/modem/Modem.h @@ -602,30 +602,34 @@ namespace modem * @brief Writes DMR Slot 1 frame data to the DMR Slot 1 ring buffer. * @param[in] data Data to write to ring buffer. * @param length Length of data to write. + * @param imm Flag indicating whether the frame is immediate. * @returns bool True, if data is written, otherwise false. */ - bool writeDMRFrame1(const uint8_t* data, uint32_t length); + bool writeDMRFrame1(const uint8_t* data, uint32_t length, bool imm = false); /** * @brief Writes DMR Slot 2 frame data to the DMR Slot 2 ring buffer. * @param[in] data Data to write to ring buffer. * @param length Length of data to write. + * @param imm Flag indicating whether the frame is immediate. * @returns bool True, if data is written, otherwise false. */ - bool writeDMRFrame2(const uint8_t* data, uint32_t length); + bool writeDMRFrame2(const uint8_t* data, uint32_t length, bool imm = false); /** * @brief Writes P25 frame data to the P25 ring buffer. * @param[in] data Data to write to ring buffer. * @param length Length of data to write. + * @param imm Flag indicating whether the frame is immediate. * @returns bool True, if data is written, otherwise false. */ - bool writeP25Frame(const uint8_t* data, uint32_t length); + bool writeP25Frame(const uint8_t* data, uint32_t length, bool imm = false); /** * @brief Writes NXDN frame data to the NXDN ring buffer. * @param[in] data Data to write to ring buffer. * @param length Length of data to write. + * @param imm Flag indicating whether the frame is immediate. * @returns bool True, if data is written, otherwise false. */ - bool writeNXDNFrame(const uint8_t* data, uint32_t length); + bool writeNXDNFrame(const uint8_t* data, uint32_t length, bool imm = false); /** * @brief Triggers the start of DMR transmit. @@ -656,9 +660,10 @@ namespace modem * @brief Writes raw data to the air interface modem. * @param data Data to write to modem. * @param length Length of data to write. + * @param imm Flag indicating whether the frame is immediate. * @returns int Actual length of data written. */ - virtual int write(const uint8_t* data, uint32_t length); + virtual int write(const uint8_t* data, uint32_t length, bool imm = false); /** * @brief Gets the flag for the V.24 connection state. diff --git a/src/host/modem/ModemV24.cpp b/src/host/modem/ModemV24.cpp index c34642bf..eb2b9e2a 100644 --- a/src/host/modem/ModemV24.cpp +++ b/src/host/modem/ModemV24.cpp @@ -47,7 +47,8 @@ ModemV24::ModemV24(port::IModemPort* port, bool duplex, uint32_t p25QueueSize, u m_superFrameCnt(0U), m_audio(), m_nid(nullptr), - m_txP25Queue(p25TxQueueSize, "TX P25 Queue"), + m_txP25Queue(p25TxQueueSize, "V.24 TX P25 Queue"), + m_txImmP25Queue(p25TxQueueSize, "V.24 TX Immediate P25 Queue"), m_txCall(), m_rxCall(), m_txCallInProgress(false), @@ -58,7 +59,8 @@ ModemV24::ModemV24(port::IModemPort* port, bool duplex, uint32_t p25QueueSize, u m_jitter(jitter), m_lastP25Tx(0U), m_rs(), - m_useTIAFormat(false) + m_useTIAFormat(false), + m_txP25QueueLock() { m_v24Connected = false; // defaulted to false for V.24 modems @@ -389,8 +391,13 @@ void ModemV24::clock(uint32_t ms) reset(); } + int len = 0; + // write anything waiting to the serial port - int len = writeSerial(); + if (!m_txImmP25Queue.isEmpty()) + len = writeSerial(&m_txImmP25Queue); + else + len = writeSerial(&m_txP25Queue); if (m_debug && len > 0) { LogDebug(LOG_MODEM, "Wrote %u-byte message to the serial V24 device", len); } else if (len < 0) { @@ -430,7 +437,7 @@ bool ModemV24::hasP25Space(uint32_t length) const /* Writes raw data to the air interface modem. */ -int ModemV24::write(const uint8_t* data, uint32_t length) +int ModemV24::write(const uint8_t* data, uint32_t length, bool imm) { assert(data != nullptr); @@ -446,12 +453,12 @@ int ModemV24::write(const uint8_t* data, uint32_t length) ::memcpy(buffer, data + 2U, length); if (m_useTIAFormat) - convertFromAirTIA(buffer, length); + convertFromAirTIA(buffer, length, imm); else - convertFromAirV24(buffer, length); + convertFromAirV24(buffer, length, imm); return length; } else { - return Modem::write(data, length); + return Modem::write(data, length, imm); } } @@ -461,7 +468,7 @@ int ModemV24::write(const uint8_t* data, uint32_t length) /* Helper to write data from the P25 Tx queue to the serial interface. */ -int ModemV24::writeSerial() +int ModemV24::writeSerial(RingBuffer* queue) { /* * Serial TX ringbuffer format: @@ -471,32 +478,38 @@ int ModemV24::writeSerial() */ // check empty - if (m_txP25Queue.isEmpty()) + if (queue->isEmpty()) return 0U; // get length uint8_t length[2U]; ::memset(length, 0x00U, 2U); - m_txP25Queue.peek(length, 2U); + queue->peek(length, 2U); // convert length byets to int uint16_t len = 0U; len = (length[0U] << 8) + length[1U]; // this ensures we never get in a situation where we have length & type bytes stuck in the queue by themselves - if (m_txP25Queue.dataSize() == 2U && len > m_txP25Queue.dataSize()) { - m_txP25Queue.get(length, 2U); // ensure we pop bytes off + if (queue->dataSize() == 2U && len > queue->dataSize()) { + queue->get(length, 2U); // ensure we pop bytes off return 0U; } + // check available modem space + if (m_p25Space < len) + return 0U; + + std::lock_guard lock(m_txP25QueueLock); + // get current timestamp int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); // peek the timestamp to see if we should wait - if (m_txP25Queue.dataSize() >= 11U) { + if (queue->dataSize() >= 11U) { uint8_t lengthTagTs[11U]; ::memset(lengthTagTs, 0x00U, 11U); - m_txP25Queue.peek(lengthTagTs, 11U); + queue->peek(lengthTagTs, 11U); // get the timestamp int64_t ts; @@ -510,14 +523,14 @@ int ModemV24::writeSerial() } // check if we have enough data to get everything - len + 2U (length bytes) + 1U (tag) + 8U (timestamp) - if (m_txP25Queue.dataSize() >= len + 11U) { + if (queue->dataSize() >= len + 11U) { // Get the length, tag and timestamp uint8_t lengthTagTs[11U]; - m_txP25Queue.get(lengthTagTs, 11U); + queue->get(lengthTagTs, 11U); // Get the actual data DECLARE_UINT8_ARRAY(buffer, len); - m_txP25Queue.get(buffer, len); + queue->get(buffer, len); // Sanity check on data tag uint8_t tag = lengthTagTs[2U]; @@ -2300,7 +2313,7 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) /* Helper to add a V.24 data frame to the P25 TX queue with the proper timestamp and formatting */ -void ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType) +bool ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType, bool imm) { assert(data != nullptr); assert(len > 0U); @@ -2347,6 +2360,17 @@ void ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType len += 4U; + std::lock_guard lock(m_txP25QueueLock); + + // check available ringbuffer space + if (imm) { + if (m_txImmP25Queue.freeSpace() < (len + 11U)) + return false; + } else { + if (m_txP25Queue.freeSpace() < (len + 11U)) + return false; + } + // convert 16-bit length to 2 bytes uint8_t length[2U]; if (len > 255U) @@ -2355,17 +2379,26 @@ void ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType length[0U] = 0x00U; length[1U] = len & 0xFFU; - m_txP25Queue.addData(length, 2U); + if (imm) + m_txImmP25Queue.addData(length, 2U); + else + m_txP25Queue.addData(length, 2U); // add the data tag uint8_t tag = TAG_DATA; - m_txP25Queue.addData(&tag, 1U); + if (imm) + m_txImmP25Queue.addData(&tag, 1U); + else + m_txP25Queue.addData(&tag, 1U); // convert 64-bit timestamp to 8 bytes and add uint8_t tsBytes[8U]; assert(sizeof msgTime == 8U); ::memcpy(tsBytes, &msgTime, 8U); - m_txP25Queue.addData(tsBytes, 8U); + if (imm) + m_txImmP25Queue.addData(tsBytes, 8U); + else + m_txP25Queue.addData(tsBytes, 8U); // add the DVM start byte, length byte, CMD byte, and padding 0 uint8_t header[4U]; @@ -2373,13 +2406,21 @@ void ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType header[1U] = len & 0xFFU; header[2U] = CMD_P25_DATA; header[3U] = 0x00U; - m_txP25Queue.addData(header, 4U); + if (imm) + m_txImmP25Queue.addData(header, 4U); + else + m_txP25Queue.addData(header, 4U); // add the data - m_txP25Queue.addData(data, len - 4U); + if (imm) + m_txImmP25Queue.addData(data, len - 4U); + else + m_txP25Queue.addData(data, len - 4U); // update the last message time m_lastP25Tx = msgTime; + + return true; } /* Send a start of stream sequence (HDU, etc) to the connected serial V.24 device */ @@ -2680,7 +2721,7 @@ void ModemV24::ackStartOfStreamTIA() /* Internal helper to convert from TIA-102 air interface to V.24/DFSI. */ -void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length) +void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length, bool imm) { assert(data != nullptr); assert(length > 0U); @@ -3131,7 +3172,7 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length) if (m_trace) Utils::dump(1U, "ModemV24::convertFromAirV24(), MotTSBKFrame", tsbkBuf, DFSI_MOT_TSBK_LEN); - queueP25Frame(tsbkBuf, DFSI_MOT_TSBK_LEN, STT_DATA_FAST); + queueP25Frame(tsbkBuf, DFSI_MOT_TSBK_LEN, STT_DATA_FAST, imm); } break; @@ -3322,7 +3363,7 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length) /* Internal helper to convert from TIA-102 air interface to TIA-102 DFSI. */ -void ModemV24::convertFromAirTIA(uint8_t* data, uint32_t length) +void ModemV24::convertFromAirTIA(uint8_t* data, uint32_t length, bool imm) { assert(data != nullptr); assert(length > 0U); diff --git a/src/host/modem/ModemV24.h b/src/host/modem/ModemV24.h index 6e7fba3d..8f33e926 100644 --- a/src/host/modem/ModemV24.h +++ b/src/host/modem/ModemV24.h @@ -578,9 +578,10 @@ namespace modem * @brief Writes raw data to the air interface modem. * @param data Data to write to modem. * @param length Length of data to write. + * @param imm Flag indicating whether the frame is immediate. * @returns int Actual length of data written. */ - int write(const uint8_t* data, uint32_t length) override; + int write(const uint8_t* data, uint32_t length, bool imm = false) override; private: bool m_rtrt; @@ -592,6 +593,7 @@ namespace modem p25::NID* m_nid; RingBuffer m_txP25Queue; + RingBuffer m_txImmP25Queue; DFSICallData* m_txCall; DFSICallData* m_rxCall; @@ -609,11 +611,14 @@ namespace modem bool m_useTIAFormat; + std::mutex m_txP25QueueLock; + /** * @brief Helper to write data from the P25 Tx queue to the serial interface. + * @param[in] queue Pointer to the ring buffer containing data to write. * @return int Actual number of bytes written to the serial interface. */ - int writeSerial(); + int writeSerial(RingBuffer* queue); /** * @brief Helper to store converted Rx frames. @@ -651,8 +656,10 @@ namespace modem * @param data Buffer containing V.24 data frame to send. * @param len Length of buffer. * @param msgType Type of message to send (used for proper jitter clocking). + * @param imm Flag indicating whether the frame is immediate. + * @returns bool True, if data is queued, otherwise false. */ - void queueP25Frame(uint8_t* data, uint16_t length, SERIAL_TX_TYPE msgType); + bool queueP25Frame(uint8_t* data, uint16_t length, SERIAL_TX_TYPE msgType, bool imm = false); /** * @brief Send a start of stream sequence (HDU, etc) to the connected serial V24 device. @@ -689,14 +696,16 @@ namespace modem * @brief Internal helper to convert from TIA-102 air interface to V.24/DFSI. * @param data Buffer containing data to convert. * @param length Length of buffer. + * @param imm Flag indicating whether the frame is immediate. */ - void convertFromAirV24(uint8_t* data, uint32_t length); + void convertFromAirV24(uint8_t* data, uint32_t length, bool imm); /** * @brief Internal helper to convert from TIA-102 air interface to TIA-102 DFSI. * @param data Buffer containing data to convert. * @param length Length of buffer. + * @param imm Flag indicating whether the frame is immediate. */ - void convertFromAirTIA(uint8_t* data, uint32_t length); + void convertFromAirTIA(uint8_t* data, uint32_t length, bool imm); }; } // namespace modem diff --git a/src/host/nxdn/Control.cpp b/src/host/nxdn/Control.cpp index b5d02463..e2e6b1b8 100644 --- a/src/host/nxdn/Control.cpp +++ b/src/host/nxdn/Control.cpp @@ -550,7 +550,7 @@ bool Control::isQueueFull() /* Get frame data from data ring buffer. */ -uint32_t Control::getFrame(uint8_t* data) +uint32_t Control::getFrame(uint8_t* data, bool* imm) { assert(data != nullptr); @@ -563,10 +563,16 @@ uint32_t Control::getFrame(uint8_t* data) // tx immediate queue takes priority if (!m_txImmQueue.isEmpty()) { + if (imm != nullptr) + *imm = true; + m_txImmQueue.get(&len, 1U); m_txImmQueue.get(data, len); } else { + if (imm != nullptr) + *imm = false; + m_txQueue.get(&len, 1U); m_txQueue.get(data, len); } diff --git a/src/host/nxdn/Control.h b/src/host/nxdn/Control.h index e02de635..cf358302 100644 --- a/src/host/nxdn/Control.h +++ b/src/host/nxdn/Control.h @@ -160,9 +160,10 @@ namespace nxdn /** * @brief Get frame data from data ring buffer. * @param[out] data Buffer to store frame data. + * @param[out] imm Flag indicating whether the frame is immediate. * @returns uint32_t Length of frame data retrieved. */ - uint32_t getFrame(uint8_t* data); + uint32_t getFrame(uint8_t* data, bool* imm = nullptr); /** @} */ /** @name Data Clocking */ diff --git a/src/host/p25/Control.cpp b/src/host/p25/Control.cpp index 29d373d7..839a0297 100644 --- a/src/host/p25/Control.cpp +++ b/src/host/p25/Control.cpp @@ -819,7 +819,7 @@ bool Control::isQueueFull() /* Get frame data from data ring buffer. */ -uint32_t Control::getFrame(uint8_t* data) +uint32_t Control::getFrame(uint8_t* data, bool *imm) { assert(data != nullptr); @@ -835,12 +835,18 @@ uint32_t Control::getFrame(uint8_t* data) // tx immediate queue takes priority if (!m_txImmQueue.isEmpty()) { + if (imm != nullptr) + *imm = true; + m_txImmQueue.get(length, 2U); len = (length[0U] << 8) + length[1U]; m_txImmQueue.get(data, len); } else { + if (imm != nullptr) + *imm = false; + m_txQueue.get(length, 2U); len = (length[0U] << 8) + length[1U]; diff --git a/src/host/p25/Control.h b/src/host/p25/Control.h index b2f35052..9f428b27 100644 --- a/src/host/p25/Control.h +++ b/src/host/p25/Control.h @@ -170,9 +170,10 @@ namespace p25 /** * @brief Get frame data from data ring buffer. * @param[out] data Buffer to store frame data. + * @param[out] imm Flag indicating whether the frame is immediate. * @returns uint32_t Length of frame data retrieved. */ - uint32_t getFrame(uint8_t* data); + uint32_t getFrame(uint8_t* data, bool* imm = nullptr); /** @} */ /**