diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp index 69bbc647..9200bc10 100644 --- a/p25/lc/TSBK.cpp +++ b/p25/lc/TSBK.cpp @@ -334,13 +334,10 @@ bool TSBK::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* b /// Encode a alternate trunking signalling block. /// /// -/// -void TSBK::encodeMBT(data::DataHeader& dataHeader, data::DataBlock* blocks) +/// +void TSBK::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData) { - assert(blocks != NULL); - - uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * 2U]; - ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * 2U); + assert(pduUserData != NULL); dataHeader.setFormat(PDU_FMT_UNCONFIRMED); dataHeader.setMFId(m_mfId); @@ -394,15 +391,8 @@ void TSBK::encodeMBT(data::DataHeader& dataHeader, data::DataBlock* blocks) // generate packet CRC-32 and set data blocks if (dataHeader.getBlocksToFollow() > 1U) { edac::CRC::addCRC32(pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()); - - uint8_t offs = 0U; - for (uint8_t i = 0; i < dataHeader.getBlocksToFollow(); i++) { - blocks[i].setData(pduUserData + offs); - offs += P25_PDU_UNCONFIRMED_LENGTH_BYTES; - } } else { edac::CRC::addCRC32(pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES); - blocks[0U].setData(pduUserData); } } diff --git a/p25/lc/TSBK.h b/p25/lc/TSBK.h index c19f9297..d2680dba 100644 --- a/p25/lc/TSBK.h +++ b/p25/lc/TSBK.h @@ -84,7 +84,7 @@ namespace p25 /// Decode a alternate trunking signalling block. bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks); /// Encode a alternate trunking signalling block. - void encodeMBT(data::DataHeader& dataHeader, data::DataBlock* blocks); + void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData); /// Decode a trunking signalling block. bool decode(const uint8_t* data, bool rawTSBK = false); diff --git a/p25/packet/Data.h b/p25/packet/Data.h index 193fdfe0..d959b595 100644 --- a/p25/packet/Data.h +++ b/p25/packet/Data.h @@ -51,6 +51,7 @@ namespace p25 // --------------------------------------------------------------------------- class HOST_SW_API Control; + namespace packet { class HOST_SW_API Trunk; } namespace packet { @@ -78,6 +79,7 @@ namespace p25 private: friend class p25::Control; Control* m_p25; + friend class p25::packet::Trunk; network::BaseNetwork* m_network; diff --git a/p25/packet/Trunk.cpp b/p25/packet/Trunk.cpp index 82a94f6d..8527f6c6 100644 --- a/p25/packet/Trunk.cpp +++ b/p25/packet/Trunk.cpp @@ -1666,6 +1666,67 @@ void Trunk::writeRF_TSDU_MBF(bool clearBeforeWrite) m_mbfCnt++; } +/// +/// Helper to write a alternate multi-block trunking PDU packet. +/// +/// +void Trunk::writeRF_PDU_AMBT(bool clearBeforeWrite) +{ + if (!m_p25->m_control) + return; + + DataHeader rspHeader = DataHeader(); + uint8_t rspData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * P25_MAX_PDU_COUNT]; + ::memset(rspData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * P25_MAX_PDU_COUNT); + + // Generate TSBK block + m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU + m_rfTSBK.encodeMBT(rspHeader, rspData); + + if (m_debug) { + LogDebug(LOG_RF, P25_PDU_STR " AMBT, lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X", + m_rfTSBK.getLCO(), m_rfTSBK.getMFId(), m_rfTSBK.getLastBlock(), m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId(), + m_rfTSBK.getSysId(), m_rfTSBK.getNetId()); + + Utils::dump(1U, "!!! *TSDU (AMBT) TSBK Block Data", rspData, P25_PDU_UNCONFIRMED_LENGTH_BYTES * rspHeader.getBlocksToFollow()); + } + + uint32_t bitLength = ((rspHeader.getBlocksToFollow() + 1U) * P25_PDU_FEC_LENGTH_BITS) + P25_PREAMBLE_LENGTH_BITS; + uint32_t offset = P25_PREAMBLE_LENGTH_BITS; + + uint8_t data[bitLength / 8U]; + ::memset(data, 0x00U, bitLength / 8U); + uint8_t block[P25_PDU_FEC_LENGTH_BYTES]; + ::memset(block, 0x00U, P25_PDU_FEC_LENGTH_BYTES); + + // Generate the PDU header and 1/2 rate Trellis + rspHeader.encode(block); + Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS); + offset += P25_PDU_FEC_LENGTH_BITS; + + // Generate the PDU data + DataBlock rspBlock = DataBlock(); + uint8_t offs = 0U; + for (uint8_t i = 0; i < rspHeader.getBlocksToFollow(); i++) { + rspBlock.setFormat(PDU_FMT_UNCONFIRMED); + rspBlock.setSerialNo(0U); + rspBlock.setData(rspData + offs); + + ::memset(block, 0x00U, P25_PDU_FEC_LENGTH_BYTES); + rspBlock.encode(block); + Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS); + offset += P25_PDU_FEC_LENGTH_BITS; + offs += P25_PDU_UNCONFIRMED_LENGTH_BYTES; + } + + if (clearBeforeWrite) { + m_p25->m_modem->clearP25Data(); + m_p25->m_queue.clear(); + } + + m_p25->m_data->writeRF_PDU(data, bitLength); +} + /// /// Helper to generate the given control TSBK into the TSDU frame queue. /// diff --git a/p25/packet/Trunk.h b/p25/packet/Trunk.h index f1485564..31498fe3 100644 --- a/p25/packet/Trunk.h +++ b/p25/packet/Trunk.h @@ -178,6 +178,8 @@ namespace p25 virtual void writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite = false, bool force = false); /// Helper to write a multi-block (3-block) P25 TSDU packet. void writeRF_TSDU_MBF(bool clearBeforeWrite = false); + /// Helper to write a alternate multi-block trunking PDU packet. + void writeRF_PDU_AMBT(bool clearBeforeWrite = false); /// Helper to generate the given control TSBK into the TSDU frame queue. void queueRF_TSBK_Ctrl(uint8_t lco);