V.24 PDU work;

pull/115/head
Bryan Biedenkapp 2 months ago
parent 2e33132cbc
commit 78cb47dce1

@ -82,7 +82,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header, bool noTre
return false; return false;
} }
} else { } else {
::memcpy(buffer, data, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); ::memcpy(buffer, data, P25_PDU_CONFIRMED_LENGTH_BYTES);
} }
#if DEBUG_P25_PDU_DATA #if DEBUG_P25_PDU_DATA

@ -659,8 +659,10 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
DECLARE_UINT8_ARRAY(dfsiData, length - 1U); DECLARE_UINT8_ARRAY(dfsiData, length - 1U);
::memcpy(dfsiData, data + 1U, length - 1U); ::memcpy(dfsiData, data + 1U, length - 1U);
if (m_debug) if (m_debug) {
LogDebugEx(LOG_MODEM, "ModemV24::convertToAirV24()", "msgType = $%02X", dfsiData[0U]);
Utils::dump("ModemV24::convertToAirV24(), V.24 RX Data From Modem", dfsiData, length - 1U); Utils::dump("ModemV24::convertToAirV24(), V.24 RX Data From Modem", dfsiData, length - 1U);
}
DFSIFrameType::E frameType = (DFSIFrameType::E)dfsiData[0U]; DFSIFrameType::E frameType = (DFSIFrameType::E)dfsiData[0U];
m_rxLastFrameTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); m_rxLastFrameTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
@ -974,18 +976,24 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
m_rxCall->dataHeader = pduHeader; m_rxCall->dataHeader = pduHeader;
int skipBytes = 1U; // skip padding between PDU blocks int skipBytes = 1U; // skip padding between PDU blocks
for (uint8_t i = 0U; i < pduHeader->getBlocksToFollow() + 1U; i++) { for (uint8_t i = 0U; i < pduHeader->getBlocksToFollow(); i++) {
uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES) + skipBytes; uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES) + skipBytes;
uint8_t dataBlock[P25_PDU_UNCONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_UNCONFIRMED_LENGTH_BYTES];
::memset(dataBlock, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), PDU Unconfirmed Data Block", dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
uint32_t offset = i * P25_PDU_UNCONFIRMED_LENGTH_BYTES; uint32_t offset = i * P25_PDU_UNCONFIRMED_LENGTH_BYTES;
::memcpy(m_rxCall->pduUserData + offset, dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(m_rxCall->pduUserData + offset, dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
skipBytes++; // each block is separated by a padding byte skipBytes++; // each block is separated by a padding byte
} }
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), Final PDU Unconfirmed Data", m_rxCall->pduUserData, (pduHeader->getBlocksToFollow() + 1U) * P25_PDU_UNCONFIRMED_LENGTH_BYTES);
storeConvertedRxPDU(pduHeader, m_rxCall->pduUserData); storeConvertedRxPDU(pduHeader, m_rxCall->pduUserData);
} }
break; break;
@ -1034,6 +1042,9 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
::memset(dataBlock, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), PDU Unconfirmed Data Block", dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
m_rxCall->pduUserDataOffset += P25_PDU_UNCONFIRMED_LENGTH_BYTES; m_rxCall->pduUserDataOffset += P25_PDU_UNCONFIRMED_LENGTH_BYTES;
m_rxCall->pduTotalBlocks++; m_rxCall->pduTotalBlocks++;
@ -1065,12 +1076,15 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
// PDU_UNCONF_BLOCK_X and PDU_UNCONF_END only contains 4 blocks each // PDU_UNCONF_BLOCK_X and PDU_UNCONF_END only contains 4 blocks each
int skipBytes = 0U; // skip padding between PDU blocks int skipBytes = 0U; // skip padding between PDU blocks
for (uint8_t i = 0U; i < blockCnt; i++) { for (uint8_t i = 0U; i < blockCnt; i++) {
uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES) + skipBytes; uint32_t blockOffset = 1U + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES) + skipBytes;
uint8_t dataBlock[P25_PDU_UNCONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_UNCONFIRMED_LENGTH_BYTES];
::memset(dataBlock, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), PDU Unconfirmed Data Block", dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
m_rxCall->pduUserDataOffset += P25_PDU_UNCONFIRMED_LENGTH_BYTES; m_rxCall->pduUserDataOffset += P25_PDU_UNCONFIRMED_LENGTH_BYTES;
m_rxCall->pduTotalBlocks++; m_rxCall->pduTotalBlocks++;
@ -1078,6 +1092,9 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
} }
if (frameType == DFSIFrameType::MOT_PDU_UNCONF_END) { if (frameType == DFSIFrameType::MOT_PDU_UNCONF_END) {
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), Final PDU Unconfirmed Data", m_rxCall->pduUserData, m_rxCall->pduTotalBlocks * P25_PDU_UNCONFIRMED_LENGTH_BYTES);
storeConvertedRxPDU(m_rxCall->dataHeader, m_rxCall->pduUserData); storeConvertedRxPDU(m_rxCall->dataHeader, m_rxCall->pduUserData);
} }
} }
@ -1110,19 +1127,25 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
m_rxCall->dataCall = true; m_rxCall->dataCall = true;
m_rxCall->dataHeader = pduHeader; m_rxCall->dataHeader = pduHeader;
int skipBytes = 1U; // skip padding between PDU blocks int skipBytes = 2U; // skip padding between PDU blocks -- and first block serial number
for (uint8_t i = 0U; i < pduHeader->getBlocksToFollow() + 1U; i++) { for (uint8_t i = 0U; i < pduHeader->getBlocksToFollow(); i++) {
uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_CONFIRMED_LENGTH_BYTES) + skipBytes; uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_CONFIRMED_LENGTH_BYTES) + skipBytes;
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES];
::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_CONFIRMED_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), PDU Confirmed Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES);
uint32_t offset = i * P25_PDU_CONFIRMED_LENGTH_BYTES; uint32_t offset = i * P25_PDU_CONFIRMED_LENGTH_BYTES;
::memcpy(m_rxCall->pduUserData + offset, dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memcpy(m_rxCall->pduUserData + offset, dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES);
skipBytes++; // each block is separated by a padding byte skipBytes++; // each block is separated by a padding byte
} }
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), Final PDU Confirmed Data", m_rxCall->pduUserData, (pduHeader->getBlocksToFollow() + 1U) * P25_PDU_CONFIRMED_LENGTH_BYTES);
storeConvertedRxPDU(pduHeader, m_rxCall->pduUserData); storeConvertedRxPDU(pduHeader, m_rxCall->pduUserData);
} }
break; break;
@ -1163,7 +1186,7 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
m_rxCall->dataHeader = pduHeader; m_rxCall->dataHeader = pduHeader;
// PDU_CONF_HEADER only contains 3 blocks // PDU_CONF_HEADER only contains 3 blocks
int skipBytes = 1U; // skip padding between PDU blocks int skipBytes = 2U; // skip padding between PDU blocks -- and first block serial number
for (uint8_t i = 0U; i < 3U; i++) { for (uint8_t i = 0U; i < 3U; i++) {
uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_CONFIRMED_LENGTH_BYTES) + skipBytes; uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_CONFIRMED_LENGTH_BYTES) + skipBytes;
@ -1171,6 +1194,9 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_CONFIRMED_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), PDU Confirmed Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES);
::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES);
m_rxCall->pduUserDataOffset += P25_PDU_CONFIRMED_LENGTH_BYTES; m_rxCall->pduUserDataOffset += P25_PDU_CONFIRMED_LENGTH_BYTES;
m_rxCall->pduTotalBlocks++; m_rxCall->pduTotalBlocks++;
@ -1202,11 +1228,15 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
// PDU_CONF_BLOCK_X only contains 4 blocks each // PDU_CONF_BLOCK_X only contains 4 blocks each
int skipBytes = 0U; // skip padding between PDU blocks int skipBytes = 0U; // skip padding between PDU blocks
for (uint8_t i = 0U; i < blockCnt; i++) { for (uint8_t i = 0U; i < blockCnt; i++) {
uint32_t blockOffset = 9U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_CONFIRMED_LENGTH_BYTES) + skipBytes; uint32_t blockOffset = 1U + (i * P25_PDU_CONFIRMED_LENGTH_BYTES) + skipBytes;
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES];
::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memcpy(dataBlock, dfsiData + blockOffset, P25_PDU_CONFIRMED_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), PDU Confirmed Data Block", dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES);
::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memcpy(m_rxCall->pduUserData + m_rxCall->pduUserDataOffset, dataBlock, P25_PDU_CONFIRMED_LENGTH_BYTES);
m_rxCall->pduUserDataOffset += P25_PDU_CONFIRMED_LENGTH_BYTES; m_rxCall->pduUserDataOffset += P25_PDU_CONFIRMED_LENGTH_BYTES;
m_rxCall->pduTotalBlocks++; m_rxCall->pduTotalBlocks++;
@ -1214,6 +1244,9 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
} }
if (frameType == DFSIFrameType::MOT_PDU_CONF_END) { if (frameType == DFSIFrameType::MOT_PDU_CONF_END) {
if (m_trace)
Utils::dump(1U, "ModemV24::convertToAirV24(), Final PDU Confirmed Data", m_rxCall->pduUserData, m_rxCall->pduTotalBlocks * P25_PDU_CONFIRMED_LENGTH_BYTES);
storeConvertedRxPDU(m_rxCall->dataHeader, m_rxCall->pduUserData); storeConvertedRxPDU(m_rxCall->dataHeader, m_rxCall->pduUserData);
} }
} }
@ -1667,8 +1700,9 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length)
DECLARE_UINT8_ARRAY(dfsiData, length - 1U); DECLARE_UINT8_ARRAY(dfsiData, length - 1U);
::memcpy(dfsiData, data + 1U, length - 1U); ::memcpy(dfsiData, data + 1U, length - 1U);
if (m_debug) if (m_debug) {
Utils::dump("ModemV24::converToAirTIA(), DFSI RX Data From UDP", dfsiData, length - 1U); Utils::dump("ModemV24::convertToAirTIA(), DFSI RX Data From UDP", dfsiData, length - 1U);
}
ControlOctet ctrl = ControlOctet(); ControlOctet ctrl = ControlOctet();
ctrl.decode(dfsiData); ctrl.decode(dfsiData);
@ -2271,10 +2305,10 @@ void ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType
assert(data != nullptr); assert(data != nullptr);
assert(len > 0U); assert(len > 0U);
if (m_debug) if (m_debug) {
LogDebugEx(LOG_MODEM, "ModemV24::queueP25Frame()", "msgType = $%02X", msgType); LogDebugEx(LOG_MODEM, "ModemV24::queueP25Frame()", "msgType = $%02X", msgType);
if (m_trace) Utils::dump("ModemV24::queueP25Frame(), V.24 TX Data To Modem", data, len);
Utils::dump(1U, "ModemV24::queueP25Frame(), data", data, len); }
// get current time in ms // get current time in ms
uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
@ -2834,39 +2868,63 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
offset += P25_PDU_FEC_LENGTH_BITS; offset += P25_PDU_FEC_LENGTH_BITS;
} }
MotStartOfStream start = MotStartOfStream();
start.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
start.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
start.setArgument1(MotStreamPayload::DATA);
// create buffer for bytes and encode
uint8_t startBuf[DFSI_MOT_START_LEN];
::memset(startBuf, 0x00U, DFSI_MOT_START_LEN);
start.encode(startBuf);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU StartOfStream", startBuf, DFSI_MOT_START_LEN);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_START_STOP);
// assemble V.24 PDU frames // assemble V.24 PDU frames
/*
** If there are 3 or fewer blocks, we can send them all in a single PDU frame.
*/
if (blocksToFollow <= 3U) { if (blocksToFollow <= 3U) {
DECLARE_UINT8_ARRAY(pduBuf, ((blocksToFollow + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)) + 9U); uint32_t pduLen = P25_PDU_HEADER_LENGTH_BYTES + (blocksToFollow * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? (P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 2U) : P25_PDU_UNCONFIRMED_LENGTH_BYTES)) + 9U;
uint32_t pduLen = ((blocksToFollow + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)) + 9U; DECLARE_UINT8_ARRAY(pduBuf, pduLen);
pduBuf[0U] = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_SINGLE_CONF : DFSIFrameType::MOT_PDU_SINGLE_UNCONF;
// header block contains the embedded start of stream // header block contains the embedded start of stream
MotStartOfStream embedded = MotStartOfStream(); MotStartOfStream embedded = MotStartOfStream();
embedded.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE); embedded.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
embedded.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD); embedded.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
embedded.setArgument1((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? MotStreamPayload::DATA_18 : MotStreamPayload::DATA_12); embedded.setArgument1((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? MotStreamPayload::DATA_18 : MotStreamPayload::DATA_12);
embedded.encode(pduBuf + 1U); embedded.encode(pduBuf);
// set opcode properly
pduBuf[0U] = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_SINGLE_CONF : DFSIFrameType::MOT_PDU_SINGLE_UNCONF;
dataHeader.encode(pduBuf + 9U, true); dataHeader.encode(pduBuf + 9U, true);
for (uint32_t i = 0U; i < blocksToFollow; i++) { for (uint32_t i = 0U; i < blocksToFollow; i++) {
dataBlocks[i].encode(pduBuf + 9U + ((i + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)), true); if (dataHeader.getFormat() == PDUFormatType::CONFIRMED) {
} uint32_t blockOffset = 10U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
MotStartOfStream start = MotStartOfStream(); pduBuf[blockOffset] = dataBlocks[i].getSerialNo();
start.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
start.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
start.setArgument1(MotStreamPayload::DATA);
// create buffer for bytes and encode uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES + 1U];
uint8_t startBuf[DFSI_MOT_START_LEN]; ::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES + 1U);
::memset(startBuf, 0x00U, DFSI_MOT_START_LEN); dataBlocks[i].encode(dataBlock, true);
start.encode(startBuf);
if (m_trace) ::memcpy(pduBuf + blockOffset + 1U, dataBlock + 2U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU StartOfStream", startBuf, DFSI_MOT_START_LEN);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Confirmed Data Block", pduBuf + blockOffset, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
} else {
uint32_t blockOffset = 10U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_START_STOP); dataBlocks[i].encode(pduBuf + blockOffset, true);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Unconfirmed Data Block", pduBuf + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
}
}
if (m_trace) if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen); Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen);
@ -2886,44 +2944,54 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP); queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP); queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP);
} }
/*
** More than 3 blocks, need to segment into multiple PDU frames.
*/
else { else {
uint32_t remainderBlocks = (blocksToFollow - 3U) % DFSI_PDU_BLOCK_CNT; uint32_t remainderBlocks = (blocksToFollow - 3U) % DFSI_PDU_BLOCK_CNT;
uint32_t baseBlockCnt = (blocksToFollow - 3U) / DFSI_PDU_BLOCK_CNT; uint32_t baseBlockCnt = (blocksToFollow - 3U) / DFSI_PDU_BLOCK_CNT;
uint32_t currentBlock = 0U; uint32_t currentBlock = 0U;
DECLARE_UINT8_ARRAY(pduBuf, ((DFSI_PDU_BLOCK_CNT + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)) + 9U); uint32_t pduLen = P25_PDU_HEADER_LENGTH_BYTES + (DFSI_PDU_BLOCK_CNT * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? (P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 2U) : P25_PDU_UNCONFIRMED_LENGTH_BYTES)) + 9U;
uint32_t pduLen = ((DFSI_PDU_BLOCK_CNT + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)) + 9U; DECLARE_UINT8_ARRAY(pduBuf, pduLen);
MotStartOfStream start = MotStartOfStream();
start.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
start.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
start.setArgument1(MotStreamPayload::DATA);
// assemble the first frame // assemble the first frame
pduBuf[0U] = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_CONF_HEADER : DFSIFrameType::MOT_PDU_UNCONF_HEADER;
// header block contains the embedded start of stream // header block contains the embedded start of stream
MotStartOfStream embedded = MotStartOfStream(); MotStartOfStream embedded = MotStartOfStream();
embedded.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE); embedded.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
embedded.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD); embedded.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
embedded.setArgument1((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? MotStreamPayload::DATA_18 : MotStreamPayload::DATA_12); embedded.setArgument1((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? MotStreamPayload::DATA_18 : MotStreamPayload::DATA_12);
embedded.encode(pduBuf + 1U); embedded.encode(pduBuf);
// set opcode properly
pduBuf[0U] = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_CONF_HEADER : DFSIFrameType::MOT_PDU_UNCONF_HEADER;
dataHeader.encode(pduBuf + 9U, true); dataHeader.encode(pduBuf + 9U, true);
for (uint32_t i = 0U; i < DFSI_PDU_BLOCK_CNT - 1U; i++) { for (uint32_t i = 0U; i < DFSI_PDU_BLOCK_CNT - 1U; i++) {
dataBlocks[currentBlock].encode(pduBuf + 9U + ((i + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)), true); if (dataHeader.getFormat() == PDUFormatType::CONFIRMED) {
currentBlock++; uint32_t blockOffset = 10U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
}
// create buffer for bytes and encode pduBuf[blockOffset] = dataBlocks[i].getSerialNo();
uint8_t startBuf[DFSI_MOT_START_LEN];
::memset(startBuf, 0x00U, DFSI_MOT_START_LEN);
start.encode(startBuf);
if (m_trace) uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES + 1U];
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU StartOfStream", startBuf, DFSI_MOT_START_LEN); ::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES + 1U);
dataBlocks[currentBlock].encode(dataBlock, true);
::memcpy(pduBuf + blockOffset + 1U, dataBlock + 2U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Confirmed Header Data Block", pduBuf + blockOffset, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
} else {
uint32_t blockOffset = 10U + P25_PDU_HEADER_LENGTH_BYTES + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_START_STOP); dataBlocks[currentBlock].encode(pduBuf + blockOffset, true);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Unconfirmed Header Data Block", pduBuf + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
}
currentBlock++;
}
if (m_trace) if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen); Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen);
@ -2936,10 +3004,32 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
// reset buffer and set data // reset buffer and set data
::memset(pduBuf, 0x00U, pduLen); ::memset(pduBuf, 0x00U, pduLen);
pduBuf[0U] = currentOpcode; pduBuf[0U] = currentOpcode;
embedded.encode(pduBuf + 1U);
pduLen = 1U;
for (uint32_t i = 0U; i < DFSI_PDU_BLOCK_CNT - 1U; i++) { for (uint32_t i = 0U; i < DFSI_PDU_BLOCK_CNT - 1U; i++) {
dataBlocks[currentBlock].encode(pduBuf + 9U + ((i + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)), true); if (dataHeader.getFormat() == PDUFormatType::CONFIRMED) {
uint32_t blockOffset = 1U + (i * P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
pduBuf[blockOffset] = dataBlocks[i].getSerialNo();
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES];
::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
dataBlocks[currentBlock].encode(dataBlock, true);
::memcpy(pduBuf + blockOffset + 1U, dataBlock + 2U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Confirmed Data Block", pduBuf + blockOffset, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
} else {
uint32_t blockOffset = 1U + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES);
dataBlocks[currentBlock].encode(pduBuf + blockOffset, true);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Unconfirmed Data Block", pduBuf + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
}
pduLen += 1U + (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? (P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U) : P25_PDU_UNCONFIRMED_LENGTH_BYTES;
currentBlock++; currentBlock++;
} }
@ -2958,12 +3048,32 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
// reset buffer and set data // reset buffer and set data
::memset(pduBuf, 0x00U, pduLen); ::memset(pduBuf, 0x00U, pduLen);
pduBuf[0U] = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_CONF_END : DFSIFrameType::MOT_PDU_UNCONF_END; pduBuf[0U] = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_CONF_END : DFSIFrameType::MOT_PDU_UNCONF_END;
embedded.encode(pduBuf + 1U);
pduLen = 0U; pduLen = 1U;
for (uint32_t i = 0U; i < remainderBlocks; i++) { for (uint32_t i = 0U; i < remainderBlocks; i++) {
dataBlocks[currentBlock].encode(pduBuf + 9U + ((i + 1U) * ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES)), true); if (dataHeader.getFormat() == PDUFormatType::CONFIRMED) {
pduLen += 1U + (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES; uint32_t blockOffset = 1U + (i * P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
pduBuf[blockOffset] = dataBlocks[i].getSerialNo();
uint8_t dataBlock[P25_PDU_CONFIRMED_LENGTH_BYTES];
::memset(dataBlock, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
dataBlocks[currentBlock].encode(dataBlock, true);
::memcpy(pduBuf + blockOffset + 1U, dataBlock + 2U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Confirmed End Data Block", pduBuf + blockOffset, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
} else {
uint32_t blockOffset = 1U + (i * P25_PDU_UNCONFIRMED_LENGTH_BYTES);
dataBlocks[currentBlock].encode(pduBuf + blockOffset, true);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU Tx Unconfirmed End Data Block", pduBuf + blockOffset, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
}
pduLen += 1U + (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? (P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U) : P25_PDU_UNCONFIRMED_LENGTH_BYTES;
currentBlock++; currentBlock++;
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.