correct TSBK, TDULC and PDU transmission using V.24 DFSI, timing must be applied like IMBE; lengthen the high-level CC generation timer by 10ms, this has no impact on regular air and hotspot modems, but better times CC frames for V.24 DFSI modems; refactor naming to be clearer for the V.24 jitter buffer transmit types; because V.24 uses OSP_TSBK_RAW and LC_TDULC_RAW correct several off by 2 shift bugs; remove unnecessary V.24 start of stream and end of stream calls;

r05a04_dev
Bryan Biedenkapp 5 days ago
parent 5c74c90f48
commit a5689d8df8

@ -130,7 +130,7 @@ namespace p25
const uint32_t P25_TDULC_FEC_LENGTH_BYTES = 36U;
const uint32_t P25_TDULC_LENGTH_BYTES = 18U;
const uint32_t P25_TDULC_PAYLOAD_LENGTH_BYTES = 8U;
const uint32_t P25_TDULC_PAYLOAD_LENGTH_BYTES = 8U; // 9 bytes including LCO, 8 bytes payload
const uint32_t P25_TSBK_FEC_LENGTH_BYTES = 25U;
const uint32_t P25_TSBK_FEC_LENGTH_BITS = P25_TSBK_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits

@ -79,22 +79,7 @@ bool MotTDULCFrame::decode(const uint8_t* data)
// decode start of stream
startOfStream->decode(startBuffer);
uint8_t tdulcBuffer[9U];
::memcpy(tdulcBuffer, data + DFSI_MOT_START_LEN, 9U);
::memset(tdulcData, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES);
tdulcData[0U] = (uint8_t)((tdulcBuffer[0U] >> 3) & 0x3FU);
tdulcData[1U] = (uint8_t)(((tdulcBuffer[0U] & 0x07U) << 3) | ((tdulcBuffer[1U] >> 4) & 0x07U));
tdulcData[2U] = (uint8_t)(((tdulcBuffer[1U] & 0x0FU) << 2) | ((tdulcBuffer[2U] >> 5) & 0x03U));
tdulcData[3U] = (uint8_t)(tdulcBuffer[2U] & 0x1FU);
tdulcData[4U] = (uint8_t)((tdulcBuffer[3U] >> 3) & 0x3FU);
tdulcData[5U] = (uint8_t)(((tdulcBuffer[3U] & 0x07U) << 3) | ((tdulcBuffer[4U] >> 4) & 0x07U));
tdulcData[6U] = (uint8_t)(((tdulcBuffer[4U] & 0x0FU) << 2) | ((tdulcBuffer[5U] >> 5) & 0x03U));
tdulcData[7U] = (uint8_t)(tdulcBuffer[5U] & 0x1FU);
tdulcData[8U] = (uint8_t)((tdulcBuffer[6U] >> 3) & 0x3FU);
tdulcData[9U] = (uint8_t)(((tdulcBuffer[6U] & 0x07U) << 3) | ((tdulcBuffer[7U] >> 4) & 0x07U));
tdulcData[10U] = (uint8_t)(((tdulcBuffer[7U] & 0x0FU) << 2) | ((tdulcBuffer[8U] >> 5) & 0x03U));
tdulcData[11U] = (uint8_t)(tdulcBuffer[8U] & 0x1FU);
::memcpy(tdulcData, data + DFSI_MOT_START_LEN, P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U);
return true;
}
@ -118,18 +103,7 @@ void MotTDULCFrame::encode(uint8_t* data)
// encode TDULC - scope is intentional
{
data[0U] = DFSIFrameType::MOT_TDULC;
data[DFSI_MOT_START_LEN + 1U] = (uint8_t)((tdulcData[0U] & 0x3FU) << 3) | ((tdulcData[1U] >> 3) & 0x07U);
data[DFSI_MOT_START_LEN + 2U] = (uint8_t)((tdulcData[1U] & 0x0FU) << 4) | ((tdulcData[2U] >> 2) & 0x0FU);
data[DFSI_MOT_START_LEN + 3U] = (uint8_t)((tdulcData[2U] & 0x03U)) | (tdulcData[3U] & 0x3FU);
data[DFSI_MOT_START_LEN + 4U] = (uint8_t)((tdulcData[4U] & 0x3FU) << 3) | ((tdulcData[5U] >> 3) & 0x07U);
data[DFSI_MOT_START_LEN + 5U] = (uint8_t)((tdulcData[5U] & 0x0FU) << 4) | ((tdulcData[6U] >> 2) & 0x0FU);
data[DFSI_MOT_START_LEN + 6U] = (uint8_t)((tdulcData[6U] & 0x03U)) | (tdulcData[7U] & 0x3FU);
data[DFSI_MOT_START_LEN + 7U] = (uint8_t)((tdulcData[8U] & 0x3FU) << 3) | ((tdulcData[9U] >> 3) & 0x07U);
data[DFSI_MOT_START_LEN + 8U] = (uint8_t)((tdulcData[9U] & 0x0FU) << 4) | ((tdulcData[10U] >> 2) & 0x0FU);
data[DFSI_MOT_START_LEN + 9U] = (uint8_t)((tdulcData[10U] & 0x03U)) | (tdulcData[11U] & 0x3FU);
::memcpy(data + DFSI_MOT_START_LEN, tdulcData, P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U);
data[DFSI_MOT_START_LEN + 11U] = DFSI_BUSY_BITS_IDLE;
}

@ -192,8 +192,8 @@ bool TDULC::decode(const uint8_t* data, uint8_t* payload, bool rawTDULC)
if (m_raw != nullptr)
delete[] m_raw;
m_raw = new uint8_t[P25_TDULC_PAYLOAD_LENGTH_BYTES];
::memcpy(m_raw, rs + 1U, P25_TDULC_PAYLOAD_LENGTH_BYTES);
m_raw = new uint8_t[P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U];
::memcpy(m_raw, rs, P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U);
::memcpy(payload, rs + 1U, P25_TDULC_PAYLOAD_LENGTH_BYTES);
return true;

@ -94,6 +94,8 @@ void LC_TDULC_RAW::setTDULC(const uint8_t* tdulc)
{
assert(tdulc != nullptr);
m_lco = tdulc[0U] & 0x3F; // LCO
m_tdulc = new uint8_t[P25_TDULC_PAYLOAD_LENGTH_BYTES];
::memset(m_tdulc, 0x00U, P25_TDULC_PAYLOAD_LENGTH_BYTES);

@ -66,7 +66,7 @@ void OSP_TSBK_RAW::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
/* stub */
TSBK::encode(data, m_tsbk + 2U, rawTSBK, noTrellis);
TSBK::encode(data, m_tsbk, rawTSBK, noTrellis);
}
/* Sets the TSBK to encode. */

@ -140,6 +140,7 @@ bool ModemV24::open()
LogInfoEx(LOG_MODEM, "Modem Ready [Direct Mode / TIA-102]");
else
LogInfoEx(LOG_MODEM, "Modem Ready [Direct Mode / V.24]");
return true;
}
@ -914,6 +915,12 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
if (!tdulc.decode(tf.tdulcData, true)) {
LogError(LOG_MODEM, "V.24/DFSI traffic failed to decode TDULC FEC");
} else {
if (m_debug) {
::LogDebugEx(LOG_MODEM, "ModemV24::convertToAirV24()", "V.24 RX, TDULC ISP, mfId = $%02X, lco = $%02X",
tdulc.getMFId(), tdulc.getLCO());
Utils::dump(1U, "V.24 RX, TDULC ISP", tf.tdulcData, P25_TDULC_FRAME_LENGTH_BYTES);
}
uint8_t buffer[P25_TDULC_FRAME_LENGTH_BYTES + 2U];
::memset(buffer, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES + 2U);
@ -1192,6 +1199,12 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length)
if (!tsbk.decode(tf.tsbkData, true)) {
LogError(LOG_MODEM, "V.24/DFSI traffic failed to decode TSBK FEC");
} else {
if (m_debug) {
::LogDebugEx(LOG_MODEM, "ModemV24::convertToAirV24()", "V.24 RX, TSBK ISP, mfId = $%02X, lco = $%02X",
tsbk.getMFId(), tsbk.getLCO());
Utils::dump(1U, "V.24 RX, TSBK ISP", tf.tsbkData, P25_TSBK_LENGTH_BYTES);
}
uint8_t buffer[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
::memset(buffer, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
@ -2247,7 +2260,7 @@ void ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType
msgTime = now + m_jitter;
// if the message type requests no jitter delay -- just set the message time to now
if (msgType == STT_NON_IMBE_NO_JITTER)
if (msgType == STT_START_STOP_NO_JITTER)
msgTime = now;
}
// if we had a message before this, calculate the new timestamp dynamically
@ -2258,7 +2271,7 @@ void ModemV24::queueP25Frame(uint8_t* data, uint16_t len, SERIAL_TX_TYPE msgType
}
// otherwise, we time out messages as required by the message type
else {
if (msgType == STT_IMBE) {
if (msgType == STT_DATA) {
// IMBEs must go out at 20ms intervals
msgTime = m_lastP25Tx + 20U;
} else {
@ -2324,7 +2337,7 @@ void ModemV24::startOfStreamV24(const p25::lc::LC& control)
if (m_trace)
Utils::dump(1U, "ModemV24::startOfStreamV24(), StartOfStream", startBuf, DFSI_MOT_START_LEN);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_NON_IMBE);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_START_STOP);
uint8_t mi[MI_LENGTH_BYTES];
::memset(mi, 0x00U, MI_LENGTH_BYTES);
@ -2365,7 +2378,7 @@ void ModemV24::startOfStreamV24(const p25::lc::LC& control)
if (m_trace)
Utils::dump(1U, "ModemV24::startOfStreamV24(), VoiceHeader1", vhdr1Buf, DFSI_MOT_VHDR_1_LEN);
queueP25Frame(vhdr1Buf, DFSI_MOT_VHDR_1_LEN, STT_NON_IMBE);
queueP25Frame(vhdr1Buf, DFSI_MOT_VHDR_1_LEN, STT_START_STOP);
// prepare VHDR2
uint8_t vhdr2Buf[DFSI_MOT_VHDR_2_LEN];
@ -2382,7 +2395,7 @@ void ModemV24::startOfStreamV24(const p25::lc::LC& control)
if (m_trace)
Utils::dump(1U, "ModemV24::startOfStreamV24(), VoiceHeader2", vhdr2Buf, DFSI_MOT_VHDR_2_LEN);
queueP25Frame(vhdr2Buf, DFSI_MOT_VHDR_2_LEN, STT_NON_IMBE);
queueP25Frame(vhdr2Buf, DFSI_MOT_VHDR_2_LEN, STT_START_STOP);
}
/* Send an end of stream sequence (TDU, etc) to the connected serial V.24 device */
@ -2402,7 +2415,7 @@ void ModemV24::endOfStreamV24()
if (m_trace)
Utils::dump(1U, "ModemV24::endOfStreamV24(), StartOfStream", endBuf, DFSI_MOT_START_LEN);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP);
m_txCallInProgress = false;
}
@ -2455,7 +2468,7 @@ void ModemV24::startOfStreamTIA(const p25::lc::LC& control)
if (m_trace)
Utils::dump(1U, "ModemV24::startOfStreamTIA(), StartOfStream", buffer, length);
queueP25Frame(buffer, length, STT_NON_IMBE);
queueP25Frame(buffer, length, STT_START_STOP);
uint8_t mi[MI_LENGTH_BYTES];
::memset(mi, 0x00U, MI_LENGTH_BYTES);
@ -2513,7 +2526,7 @@ void ModemV24::startOfStreamTIA(const p25::lc::LC& control)
if (m_trace)
Utils::dump(1U, "ModemV24::startOfStreamTIA(), VoiceHeader1", buffer, length);
queueP25Frame(buffer, length, STT_NON_IMBE);
queueP25Frame(buffer, length, STT_START_STOP);
::memset(buffer, 0x00U, P25_HDU_LENGTH_BYTES);
length = 0U;
@ -2542,7 +2555,7 @@ void ModemV24::startOfStreamTIA(const p25::lc::LC& control)
if (m_trace)
Utils::dump(1U, "ModemV24::startOfStreamTIA(), VoiceHeader2", buffer, length);
queueP25Frame(buffer, length, STT_NON_IMBE);
queueP25Frame(buffer, length, STT_START_STOP);
}
/* Send an end of stream sequence (TDU, etc) to the connected UDP TIA-102 device. */
@ -2570,7 +2583,7 @@ void ModemV24::endOfStreamTIA()
if (m_trace)
Utils::dump(1U, "ModemV24::endOfStreamTIA(), EndOfStream", buffer, length);
queueP25Frame(buffer, length, STT_NON_IMBE);
queueP25Frame(buffer, length, STT_START_STOP);
m_txCallInProgress = false;
}
@ -2598,7 +2611,7 @@ void ModemV24::ackStartOfStreamTIA()
if (m_trace)
Utils::dump(1U, "ModemV24::ackStartOfStreamTIA(), Ack StartOfStream", buffer, length);
queueP25Frame(buffer, length, STT_NON_IMBE_NO_JITTER);
queueP25Frame(buffer, length, STT_START_STOP);
}
/* Internal helper to convert from TIA-102 air interface to V.24/DFSI. */
@ -2703,30 +2716,15 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
return;
}
MotStartOfStream start = MotStartOfStream();
start.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
start.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
start.setArgument1(MotStreamPayload::TERM_LC);
// 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(), TDULC MotStartOfStream", startBuf, DFSI_MOT_START_LEN);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
MotTDULCFrame tf = MotTDULCFrame();
tf.startOfStream->setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
tf.startOfStream->setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
tf.startOfStream->setArgument1(MotStreamPayload::TERM_LC);
delete[] tf.tdulcData;
tf.tdulcData = new uint8_t[P25_TDULC_PAYLOAD_LENGTH_BYTES];
::memset(tf.tdulcData, 0x00U, P25_TDULC_PAYLOAD_LENGTH_BYTES);
::memcpy(tf.tdulcData, tdulc.getDecodedRaw(), P25_TDULC_PAYLOAD_LENGTH_BYTES);
tf.tdulcData = new uint8_t[P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U];
::memset(tf.tdulcData, 0x00U, P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U);
::memcpy(tf.tdulcData, tdulc.getDecodedRaw(), P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U);
// create buffer and encode
uint8_t tdulcBuf[DFSI_MOT_TDULC_LEN];
@ -2736,20 +2734,7 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), MotTDULCFrame", tdulcBuf, DFSI_MOT_TDULC_LEN);
queueP25Frame(tdulcBuf, DFSI_MOT_TDULC_LEN, STT_NON_IMBE_NO_JITTER);
MotStartOfStream end = MotStartOfStream();
end.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
end.setParam1(DFSI_MOT_ICW_PARM_STOP);
end.setArgument1(MotStreamPayload::TERM_LC);
// create buffer and encode
uint8_t endBuf[DFSI_MOT_START_LEN];
::memset(endBuf, 0x00U, DFSI_MOT_START_LEN);
end.encode(endBuf);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(tdulcBuf, DFSI_MOT_TDULC_LEN, STT_DATA);
}
break;
@ -2847,12 +2832,12 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU StartOfStream", startBuf, DFSI_MOT_START_LEN);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_START_STOP);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen);
queueP25Frame(pduBuf, pduLen, STT_NON_IMBE_NO_JITTER);
queueP25Frame(pduBuf, pduLen, STT_DATA);
MotStartOfStream end = MotStartOfStream();
end.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
@ -2864,8 +2849,8 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
::memset(endBuf, 0x00U, DFSI_MOT_START_LEN);
end.encode(endBuf);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP);
}
else {
uint32_t remainderBlocks = (blocksToFollow - 3U) % DFSI_PDU_BLOCK_CNT;
@ -2897,12 +2882,12 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), PDU StartOfStream", startBuf, DFSI_MOT_START_LEN);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_START_STOP);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen);
queueP25Frame(pduBuf, pduLen, STT_NON_IMBE_NO_JITTER);
queueP25Frame(pduBuf, pduLen, STT_DATA);
// iterate through the count of full 4 block buffers and send
uint8_t currentOpcode = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_CONF_BLOCK_1 : DFSIFrameType::MOT_PDU_UNCONF_BLOCK_1;
@ -2920,20 +2905,10 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
if (currentOpcode > ((dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_CONF_BLOCK_4 : DFSIFrameType::MOT_PDU_UNCONF_BLOCK_4))
currentOpcode = (dataHeader.getFormat() == PDUFormatType::CONFIRMED) ? DFSIFrameType::MOT_PDU_CONF_BLOCK_1 : DFSIFrameType::MOT_PDU_UNCONF_BLOCK_1;
// 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_NON_IMBE_NO_JITTER);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen);
queueP25Frame(pduBuf, pduLen, STT_NON_IMBE_NO_JITTER);
queueP25Frame(pduBuf, pduLen, STT_DATA);
}
// do we have any remaining blocks?
@ -2948,20 +2923,11 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
currentBlock++;
}
// 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_NON_IMBE_NO_JITTER);
if (m_trace)
Utils::dump(1U, "ModemV24::convertFromAirV24(), MotPDUFrame", pduBuf, pduLen);
queueP25Frame(pduBuf, pduLen, STT_NON_IMBE_NO_JITTER);
queueP25Frame(pduBuf, pduLen, STT_DATA);
}
MotStartOfStream end = MotStartOfStream();
end.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
@ -2973,9 +2939,8 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
::memset(endBuf, 0x00U, DFSI_MOT_START_LEN);
end.encode(endBuf);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
}
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_START_STOP);
}
delete[] dataBlocks;
@ -2991,21 +2956,6 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
return;
}
MotStartOfStream start = MotStartOfStream();
start.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
start.setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
start.setArgument1(MotStreamPayload::TSBK);
// 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(), TSBK StartOfStream", startBuf, DFSI_MOT_START_LEN);
queueP25Frame(startBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
MotTSBKFrame tf = MotTSBKFrame();
tf.startOfStream->setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
tf.startOfStream->setParam1(DSFI_MOT_ICW_PARM_PAYLOAD);
@ -3024,20 +2974,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_NON_IMBE_NO_JITTER);
MotStartOfStream end = MotStartOfStream();
end.setOpcode(m_rtrt ? MotStartStreamOpcode::TRANSMIT : MotStartStreamOpcode::RECEIVE);
end.setParam1(DFSI_MOT_ICW_PARM_STOP);
end.setArgument1(MotStreamPayload::TSBK);
// create buffer and encode
uint8_t endBuf[DFSI_MOT_START_LEN];
::memset(endBuf, 0x00U, DFSI_MOT_START_LEN);
end.encode(endBuf);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(endBuf, DFSI_MOT_START_LEN, STT_NON_IMBE_NO_JITTER);
queueP25Frame(tsbkBuf, DFSI_MOT_TSBK_LEN, STT_DATA);
}
break;
@ -3219,7 +3156,7 @@ void ModemV24::convertFromAirV24(uint8_t* data, uint32_t length)
Utils::dump("ModemV24::convertFromAirV24(), Encoded V.24 Voice Frame Data", buffer, bufferSize);
}
queueP25Frame(buffer, bufferSize, STT_IMBE);
queueP25Frame(buffer, bufferSize, STT_DATA);
delete[] buffer;
}
}
@ -3511,7 +3448,7 @@ void ModemV24::convertFromAirTIA(uint8_t* data, uint32_t length)
Utils::dump("ModemV24::convertFromAirTIA(), Encoded V.24 Voice Frame Data", buffer, bufferSize);
}
queueP25Frame(buffer, bufferSize, STT_IMBE);
queueP25Frame(buffer, bufferSize, STT_DATA);
delete[] buffer;
}
}

@ -42,9 +42,9 @@ namespace modem
*/
enum SERIAL_TX_TYPE {
STT_NO_DATA, //!< No Data
STT_NON_IMBE, //!< Non-IMBE Data/Signalling Frame
STT_NON_IMBE_NO_JITTER, //!< Non-IMBE Data/Signalling Frame with Jitter Disabled
STT_IMBE //!< IMBE Voice Frame
STT_START_STOP, //!< Start/Stop Signalling Frame
STT_START_STOP_NO_JITTER, //!< Start/Stop Signalling Frame with Jitter Disabled
STT_DATA //!< Paced Data/Signalling Frame or IMBE Voice Frame
};
/** @} */

@ -116,7 +116,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q
m_networkWatchdog(1000U, 0U, 1500U),
m_adjSiteUpdate(1000U, 75U),
m_activeTGUpdate(1000U, 5U),
m_ccPacketInterval(1000U, 0U, 10U),
m_ccPacketInterval(1000U, 0U, 20U),
m_rfVoiceCallTermTimeout(1000U, VOICE_CALL_TERM_TIMEOUT),
m_interval(),
m_hangCount(3U * 8U),

@ -44,6 +44,9 @@ TEST_CASE("TSBK", "[p25][tsbk]") {
testTSBK[0] = 0x34; // Example LCO (OSP_SCCB)
testTSBK[1] = 0x00; // Mfg ID (standard)
tsbk1.setLCO(0x34U);
tsbk1.setMFId(0x00U);
// Set some payload data
for (uint32_t i = 2; i < P25_TSBK_LENGTH_BYTES - 2; i++) {
testTSBK[i] = (uint8_t)(i * 0x11);
@ -63,18 +66,21 @@ TEST_CASE("TSBK", "[p25][tsbk]") {
Utils::dump(2U, "encoded", encoded, P25_TSBK_LENGTH_BYTES);
// Verify encoded matches input
for (uint32_t i = 0; i < P25_TSBK_LENGTH_BYTES - 2; i++) {
REQUIRE(encoded[i] == testTSBK[i]);
}
// Decode back
// Decode back and verify roundtrip
OSP_TSBK_RAW tsbk2;
bool result = tsbk2.decode(encoded, true);
REQUIRE(result == true);
REQUIRE(tsbk2.getLCO() == (testTSBK[0] & 0x3F));
REQUIRE(tsbk2.getMFId() == testTSBK[1]);
// Encode again and verify it matches the first encode
uint8_t encoded2[P25_TSBK_LENGTH_BYTES];
tsbk2.encode(encoded2, true, true);
for (uint32_t i = 0; i < P25_TSBK_LENGTH_BYTES; i++) {
REQUIRE(encoded2[i] == encoded[i]);
}
}
SECTION("RawTSBK_Encode_Decode_WithTrellis") {
@ -209,7 +215,7 @@ TEST_CASE("TSBK", "[p25][tsbk]") {
// Payload is bytes 2-9 (8 bytes)
uint8_t expectedPayload[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
::memcpy(testTSBK + 2, expectedPayload, 8);
::memcpy(testTSBK, expectedPayload, 8);
edac::CRC::addCCITT162(testTSBK, P25_TSBK_LENGTH_BYTES);

Loading…
Cancel
Save

Powered by TurnKey Linux.