diff --git a/src/host/modem/ModemV24.cpp b/src/host/modem/ModemV24.cpp index a3c8bdcc..d76ec04c 100644 --- a/src/host/modem/ModemV24.cpp +++ b/src/host/modem/ModemV24.cpp @@ -920,6 +920,10 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length) lc.setKId(m_rxCall->kId); lc.setMI(m_rxCall->MI); + m_rxCall->lastLDU1 = lc; + m_rxCall->lastLDU2 = lc; + ::memcpy(m_rxCall->lastMI, m_rxCall->MI, MI_LENGTH_BYTES); + // generate Sync Sync::addP25Sync(buffer + 2U); @@ -1672,13 +1676,54 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length) // encode LDU1 if ready if (duid == DUID::LDU1) { + bool valid = false; + // decode RS (24,12,13) FEC - // bryanb: for now this won't abort the frame if RS fails, but maybe it should in the future, for now - // we'll just log the error try { bool ret = m_rs.decode241213(m_rxCall->LDULC); if (!ret) { LogError(LOG_MODEM, "V.24/DFSI LDU1, failed to decode RS (24,12,13) FEC"); + + // ensure our srcId and dstId are sane from the last LDU1 + if (m_rxCall->lastLDU1.getDstId() != 0U) { + if (m_rxCall->dstId != m_rxCall->lastLDU1.getDstId()) { + LogWarning(LOG_MODEM, "V.24/DFSI LDU1, dstId = %u doesn't match last LDU1 dstId = %u, fixing", + m_rxCall->dstId, m_rxCall->lastLDU1.getDstId()); + m_rxCall->dstId = m_rxCall->lastLDU1.getDstId(); + } + } + else { + LogWarning(LOG_MODEM, "V.24/DFSI LDU1, last LDU1 LC has bad data, dstId = 0"); + } + + if (m_rxCall->lastLDU1.getSrcId() != 0U) { + if (m_rxCall->srcId != m_rxCall->lastLDU1.getSrcId()) { + LogWarning(LOG_MODEM, "V.24/DFSI LDU1, srcId = %u doesn't match last LDU1 srcId = %u, fixing", + m_rxCall->srcId, m_rxCall->lastLDU1.getSrcId()); + m_rxCall->srcId = m_rxCall->lastLDU1.getSrcId(); + } + } + else { + LogWarning(LOG_MODEM, "V.24/DFSI LDU1, last LDU1 LC has bad data, srcId = 0"); + } + + // recover LC data using the last known good LDU1 + if (m_rxCall->lastLDU1.getSrcId() != 0U && m_rxCall->lastLDU1.getDstId() != 0U) { + m_rxCall->lco = m_rxCall->lastLDU1.getLCO(); + m_rxCall->mfId = m_rxCall->lastLDU1.getMFId(); + + bool emergency = m_rxCall->lastLDU1.getEmergency(); + bool encryption = m_rxCall->lastLDU1.getEncrypted(); + uint8_t priority = m_rxCall->lastLDU1.getPriority(); + m_rxCall->serviceOptions = (emergency ? 0x80U : 0x00U) + // Emergency Flag + (encryption ? 0x40U : 0x00U) + // Encrypted Flag + (priority & 0x07U); // Priority + + m_rxCall->srcId = m_rxCall->lastLDU1.getSrcId(); + m_rxCall->dstId = m_rxCall->lastLDU1.getDstId(); + } + } else { + valid = true; } } catch (...) { @@ -1732,6 +1777,14 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length) lc.setEncrypted(encryption); lc.setPriority(priority); + if (valid) + m_rxCall->lastLDU1 = lc; + + if (m_debug) { + LogInfoEx(LOG_MODEM, "V.24/DFSI LDU1, audio, mfId = $%02X srcId = %u, dstId = %u, group = %u, emerg = %u, encrypt = %u, prio = %u, errs = %u/1233 (%.1f%%)", + lc.getMFId(), lc.getSrcId(), lc.getDstId(), lc.getGroup(), lc.getEmergency(), lc.getEncrypted(), lc.getPriority(), m_rxCall->errors, float(m_rxCall->errors) / 12.33F); + } + data::LowSpeedData lsd = data::LowSpeedData(); lsd.setLSD1(m_rxCall->lsd1); lsd.setLSD2(m_rxCall->lsd2); @@ -1764,20 +1817,42 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length) buffer[0U] = modem::TAG_DATA; buffer[1U] = 0x01U; - storeConvertedRx(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U); + + buffer[217U] = (m_rxCall->errors >> 8) & 0xFFU; + buffer[218U] = (m_rxCall->errors >> 0) & 0xFFU; + + storeConvertedRx(buffer, P25_LDU_FRAME_LENGTH_BYTES + 4U); m_rxCall->resetLDU1State(); } // encode LDU2 if ready if (duid == DUID::LDU2) { + bool valid = false; + // decode RS (24,16,9) FEC - // bryanb: for now this won't abort the frame if RS fails, but maybe it should in the future, for now - // we'll just log the error try { bool ret = m_rs.decode24169(m_rxCall->LDULC); if (!ret) { LogError(LOG_MODEM, "V.24/DFSI LDU2, failed to decode RS (24,16,9) FEC"); + + m_rxCall->algoId = m_rxCall->lastLDU2.getAlgId(); + m_rxCall->kId = m_rxCall->lastLDU2.getKId(); + + // regenerate the MI using LFSR + uint8_t lastMI[MI_LENGTH_BYTES]; + ::memset(lastMI, 0x00U, MI_LENGTH_BYTES); + + uint8_t nextMI[MI_LENGTH_BYTES]; + ::memset(nextMI, 0x00U, MI_LENGTH_BYTES); + + getNextMI(m_rxCall->lastMI, m_rxCall->MI); + if (m_debug) { + Utils::dump(1U, "P25, V.24/LDU2, Previous P25 MI", lastMI, MI_LENGTH_BYTES); + Utils::dump(1U, "P25, V.24/LDU2, Calculated next P25 MI", nextMI, MI_LENGTH_BYTES); + } + } else { + valid = true; } } catch (...) { @@ -1794,6 +1869,26 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length) lc.setAlgId(m_rxCall->algoId); lc.setKId(m_rxCall->kId); + if (valid) { + m_rxCall->lastLDU2 = lc; + ::memcpy(m_rxCall->lastMI, m_rxCall->MI, MI_LENGTH_BYTES); + } + + if (m_debug) { + LogInfoEx(LOG_MODEM, "V.24/LDU2, audio, algo = $%02X, kid = $%04X, errs = %u/1233 (%.1f%%)", + lc.getAlgId(), lc.getKId(), m_rxCall->errors, float(m_rxCall->errors) / 12.33F); + + if (lc.getAlgId() != ALGO_UNENCRYPT) { + uint8_t mi[MI_LENGTH_BYTES]; + ::memset(mi, 0x00U, MI_LENGTH_BYTES); + + lc.getMI(mi); + + LogInfoEx(LOG_MODEM, "V.24/LDU2, Enc Sync, MI = %02X %02X %02X %02X %02X %02X %02X %02X %02X", + mi[0U], mi[1U], mi[2U], mi[3U], mi[4U], mi[5U], mi[6U], mi[7U], mi[8U]); + } + } + data::LowSpeedData lsd = data::LowSpeedData(); lsd.setLSD1(m_rxCall->lsd1); lsd.setLSD2(m_rxCall->lsd2); @@ -1826,7 +1921,11 @@ void ModemV24::convertToAirV24(const uint8_t *data, uint32_t length) buffer[0U] = modem::TAG_DATA; buffer[1U] = 0x01U; - storeConvertedRx(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U); + + buffer[217U] = (m_rxCall->errors >> 8) & 0xFFU; + buffer[218U] = (m_rxCall->errors >> 0) & 0xFFU; + + storeConvertedRx(buffer, P25_LDU_FRAME_LENGTH_BYTES + 4U); m_rxCall->resetLDU2State(); } @@ -2006,6 +2105,10 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) lc.setKId(m_rxCall->kId); lc.setMI(m_rxCall->MI); + m_rxCall->lastLDU1 = lc; + m_rxCall->lastLDU2 = lc; + ::memcpy(m_rxCall->lastMI, m_rxCall->MI, MI_LENGTH_BYTES); + // generate Sync Sync::addP25Sync(buffer + 2U); @@ -2279,13 +2382,54 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) // encode LDU1 if ready if (duid == DUID::LDU1) { + bool valid = false; + // decode RS (24,12,13) FEC - // bryanb: for now this won't abort the frame if RS fails, but maybe it should in the future, for now - // we'll just log the error try { bool ret = m_rs.decode241213(m_rxCall->LDULC); if (!ret) { LogError(LOG_MODEM, "TIA/DFSI LDU1, failed to decode RS (24,12,13) FEC"); + + // ensure our srcId and dstId are sane from the last LDU1 + if (m_rxCall->lastLDU1.getDstId() != 0U) { + if (m_rxCall->dstId != m_rxCall->lastLDU1.getDstId()) { + LogWarning(LOG_MODEM, "TIA/DFSI LDU1, dstId = %u doesn't match last LDU1 dstId = %u, fixing", + m_rxCall->dstId, m_rxCall->lastLDU1.getDstId()); + m_rxCall->dstId = m_rxCall->lastLDU1.getDstId(); + } + } + else { + LogWarning(LOG_MODEM, "TIA/DFSI LDU1, last LDU1 LC has bad data, dstId = 0"); + } + + if (m_rxCall->lastLDU1.getSrcId() != 0U) { + if (m_rxCall->srcId != m_rxCall->lastLDU1.getSrcId()) { + LogWarning(LOG_MODEM, "V.24/DFSI LDU1, srcId = %u doesn't match last LDU1 srcId = %u, fixing", + m_rxCall->srcId, m_rxCall->lastLDU1.getSrcId()); + m_rxCall->srcId = m_rxCall->lastLDU1.getSrcId(); + } + } + else { + LogWarning(LOG_MODEM, "TIA/DFSI LDU1, last LDU1 LC has bad data, srcId = 0"); + } + + // recover LC data using the last known good LDU1 + if (m_rxCall->lastLDU1.getSrcId() != 0U && m_rxCall->lastLDU1.getDstId() != 0U) { + m_rxCall->lco = m_rxCall->lastLDU1.getLCO(); + m_rxCall->mfId = m_rxCall->lastLDU1.getMFId(); + + bool emergency = m_rxCall->lastLDU1.getEmergency(); + bool encryption = m_rxCall->lastLDU1.getEncrypted(); + uint8_t priority = m_rxCall->lastLDU1.getPriority(); + m_rxCall->serviceOptions = (emergency ? 0x80U : 0x00U) + // Emergency Flag + (encryption ? 0x40U : 0x00U) + // Encrypted Flag + (priority & 0x07U); // Priority + + m_rxCall->srcId = m_rxCall->lastLDU1.getSrcId(); + m_rxCall->dstId = m_rxCall->lastLDU1.getDstId(); + } + } else { + valid = true; } } catch (...) { @@ -2339,6 +2483,14 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) lc.setEncrypted(encryption); lc.setPriority(priority); + if (valid) + m_rxCall->lastLDU1 = lc; + + if (m_debug) { + LogInfoEx(LOG_MODEM, "TIA/DFSI LDU1, audio, mfId = $%02X srcId = %u, dstId = %u, group = %u, emerg = %u, encrypt = %u, prio = %u, errs = %u/1233 (%.1f%%)", + lc.getMFId(), lc.getSrcId(), lc.getDstId(), lc.getGroup(), lc.getEmergency(), lc.getEncrypted(), lc.getPriority(), m_rxCall->errors, float(m_rxCall->errors) / 12.33F); + } + data::LowSpeedData lsd = data::LowSpeedData(); lsd.setLSD1(m_rxCall->lsd1); lsd.setLSD2(m_rxCall->lsd2); @@ -2371,6 +2523,10 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) buffer[0U] = modem::TAG_DATA; buffer[1U] = 0x01U; + + buffer[217U] = (m_rxCall->errors >> 8) & 0xFFU; + buffer[218U] = (m_rxCall->errors >> 0) & 0xFFU; + storeConvertedRx(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U); m_rxCall->resetLDU1State(); @@ -2378,13 +2534,31 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) // encode LDU2 if ready if (duid == DUID::LDU2) { + bool valid = false; + // decode RS (24,16,9) FEC - // bryanb: for now this won't abort the frame if RS fails, but maybe it should in the future, for now - // we'll just log the error try { bool ret = m_rs.decode24169(m_rxCall->LDULC); if (!ret) { LogError(LOG_MODEM, "TIA/DFSI LDU2, failed to decode RS (24,16,9) FEC"); + + m_rxCall->algoId = m_rxCall->lastLDU2.getAlgId(); + m_rxCall->kId = m_rxCall->lastLDU2.getKId(); + + // regenerate the MI using LFSR + uint8_t lastMI[MI_LENGTH_BYTES]; + ::memset(lastMI, 0x00U, MI_LENGTH_BYTES); + + uint8_t nextMI[MI_LENGTH_BYTES]; + ::memset(nextMI, 0x00U, MI_LENGTH_BYTES); + + getNextMI(m_rxCall->lastMI, m_rxCall->MI); + if (m_debug) { + Utils::dump(1U, "P25, TIA/LDU2, Previous P25 MI", lastMI, MI_LENGTH_BYTES); + Utils::dump(1U, "P25, TIA/LDU2, Calculated next P25 MI", nextMI, MI_LENGTH_BYTES); + } + } else { + valid = true; } } catch (...) { @@ -2403,6 +2577,26 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) lc.setAlgId(m_rxCall->algoId); lc.setKId(m_rxCall->kId); + if (valid) { + m_rxCall->lastLDU2 = lc; + ::memcpy(m_rxCall->lastMI, m_rxCall->MI, MI_LENGTH_BYTES); + } + + if (m_debug) { + LogInfoEx(LOG_MODEM, "TIA/LDU2, audio, algo = $%02X, kid = $%04X, errs = %u/1233 (%.1f%%)", + lc.getAlgId(), lc.getKId(), m_rxCall->errors, float(m_rxCall->errors) / 12.33F); + + if (lc.getAlgId() != ALGO_UNENCRYPT) { + uint8_t mi[MI_LENGTH_BYTES]; + ::memset(mi, 0x00U, MI_LENGTH_BYTES); + + lc.getMI(mi); + + LogInfoEx(LOG_MODEM, "TIA/LDU2, Enc Sync, MI = %02X %02X %02X %02X %02X %02X %02X %02X %02X", + mi[0U], mi[1U], mi[2U], mi[3U], mi[4U], mi[5U], mi[6U], mi[7U], mi[8U]); + } + } + data::LowSpeedData lsd = data::LowSpeedData(); lsd.setLSD1(m_rxCall->lsd1); lsd.setLSD2(m_rxCall->lsd2); @@ -2435,6 +2629,10 @@ void ModemV24::convertToAirTIA(const uint8_t *data, uint32_t length) buffer[0U] = modem::TAG_DATA; buffer[1U] = 0x01U; + + buffer[217U] = (m_rxCall->errors >> 8) & 0xFFU; + buffer[218U] = (m_rxCall->errors >> 0) & 0xFFU; + storeConvertedRx(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U); m_rxCall->resetLDU2State(); @@ -3818,3 +4016,27 @@ void ModemV24::convertFromAirTIA(uint8_t* data, uint32_t length, bool imm) } } } + +/* Given the last MI, generate the next MI using LFSR. */ + +void ModemV24::getNextMI(uint8_t lastMI[9U], uint8_t nextMI[9U]) +{ + uint8_t carry, i; + std::copy(lastMI, lastMI + 9, nextMI); + + for (uint8_t cycle = 0; cycle < 64; cycle++) { + // calculate bit 0 for the next cycle + carry = ((nextMI[0] >> 7) ^ (nextMI[0] >> 5) ^ (nextMI[2] >> 5) ^ + (nextMI[3] >> 5) ^ (nextMI[4] >> 2) ^ (nextMI[6] >> 6)) & + 0x01; + + // shift all the list elements, except the last one + for (i = 0; i < 7; i++) { + // grab high bit from the next element and use it as our low bit + nextMI[i] = ((nextMI[i] & 0x7F) << 1) | (nextMI[i + 1] >> 7); + } + + // shift last element, then copy the bit 0 we calculated in + nextMI[7] = ((nextMI[i] & 0x7F) << 1) | carry; + } +} diff --git a/src/host/modem/ModemV24.h b/src/host/modem/ModemV24.h index d632c989..6fab06bd 100644 --- a/src/host/modem/ModemV24.h +++ b/src/host/modem/ModemV24.h @@ -76,11 +76,14 @@ namespace modem lsd1(0U), lsd2(0U), MI(nullptr), + lastMI(nullptr), algoId(P25DEF::ALGO_UNENCRYPT), kId(0U), VHDR1(nullptr), VHDR2(nullptr), LDULC(nullptr), + lastLDU1(), + lastLDU2(), seqNo(0U), ldu1N(0U), ldu2N(0U), @@ -96,6 +99,7 @@ namespace modem errors(0U) { MI = new uint8_t[P25DEF::MI_LENGTH_BYTES]; + lastMI = new uint8_t[P25DEF::MI_LENGTH_BYTES]; VHDR1 = new uint8_t[P25DFSIDEF::DFSI_MOT_VHDR_1_LEN]; VHDR2 = new uint8_t[P25DFSIDEF::DFSI_MOT_VHDR_2_LEN]; LDULC = new uint8_t[P25DEF::P25_LDU_LC_FEC_LENGTH_BYTES]; @@ -120,6 +124,10 @@ namespace modem delete[] MI; MI = nullptr; } + if (lastMI != nullptr) { + delete[] lastMI; + lastMI = nullptr; + } if (VHDR1 != nullptr) { delete[] VHDR1; VHDR1 = nullptr; @@ -167,6 +175,8 @@ namespace modem if (MI != nullptr) ::memset(MI, 0x00U, P25DEF::MI_LENGTH_BYTES); + if (lastMI != nullptr) + ::memset(lastMI, 0x00U, P25DEF::MI_LENGTH_BYTES); algoId = P25DEF::ALGO_UNENCRYPT; kId = 0U; @@ -178,6 +188,9 @@ namespace modem if (LDULC != nullptr) ::memset(LDULC, 0x00U, P25DEF::P25_LDU_LC_FEC_LENGTH_BYTES); + lastLDU1 = p25::lc::LC(); + lastLDU2 = p25::lc::LC(); + if (netLDU1 != nullptr) ::memset(netLDU1, 0x00U, 9U * 25U); if (netLDU2 != nullptr) @@ -259,6 +272,10 @@ namespace modem * @brief Encryption Message Indicator. */ uint8_t* MI; + /** + * @brief Last Encryption Message Indicator. + */ + uint8_t* lastMI; /** * @brief Encryption Algorithm ID. */ @@ -281,6 +298,14 @@ namespace modem * @brief LDU LC. */ uint8_t* LDULC; + /** + * @brief Last LDU1 Link Control. + */ + p25::lc::LC lastLDU1; + /** + * @brief Last LDU2 Link Control. + */ + p25::lc::LC lastLDU2; /** * @brief Sequence Number. @@ -337,7 +362,7 @@ namespace modem /** * @brief Total errors for a given call sequence. */ - uint32_t errors; + uint16_t errors; /** @} */ }; @@ -752,6 +777,13 @@ namespace modem * @param imm Flag indicating whether the frame is immediate. */ void convertFromAirTIA(uint8_t* data, uint32_t length, bool imm); + + /** + * @brief Given the last MI, generate the next MI using LFSR. + * @param lastMI Last MI received. + * @param nextMI Next MI. + */ + void getNextMI(uint8_t lastMI[9U], uint8_t nextMI[9U]); }; } // namespace modem diff --git a/src/host/p25/Control.cpp b/src/host/p25/Control.cpp index f6c27e75..199b63d9 100644 --- a/src/host/p25/Control.cpp +++ b/src/host/p25/Control.cpp @@ -656,28 +656,36 @@ bool Control::processFrame(uint8_t* data, uint32_t len) DUID::E duid = m_nid.getDUID(); - // Have we got RSSI bytes on the end of a P25 LDU? - if (len == (P25_LDU_FRAME_LENGTH_BYTES + 4U)) { - uint16_t raw = 0U; - raw |= (data[218U] << 8) & 0xFF00U; - raw |= (data[219U] << 0) & 0x00FFU; - - // Convert the raw RSSI to dBm - int rssi = m_rssiMapper->interpolate(raw); - if (m_verbose) { - LogInfoEx(LOG_RF, "P25, raw RSSI = %u, reported RSSI = %d dBm", raw, rssi); - } + // have we got RSSI bytes (or error count for DFSI) on the end of a P25 LDU? + if ((duid == DUID::LDU1 || duid == DUID::LDU2) && len == (P25_LDU_FRAME_LENGTH_BYTES + 4U)) { + if (m_isModemDFSI) { + uint16_t raw = 0U; + raw |= (data[218U] << 8) & 0xFF00U; + raw |= (data[219U] << 0) & 0x00FFU; + + m_voice->m_dfsiReportedErrs = raw; + } else { + uint16_t raw = 0U; + raw |= (data[218U] << 8) & 0xFF00U; + raw |= (data[219U] << 0) & 0x00FFU; + + // Convert the raw RSSI to dBm + int rssi = m_rssiMapper->interpolate(raw); + if (m_verbose) { + LogInfoEx(LOG_RF, "P25, raw RSSI = %u, reported RSSI = %d dBm", raw, rssi); + } - // RSSI is always reported as positive - m_rssi = (rssi >= 0) ? rssi : -rssi; + // RSSI is always reported as positive + m_rssi = (rssi >= 0) ? rssi : -rssi; - if (m_rssi > m_minRSSI) - m_minRSSI = m_rssi; - if (m_rssi < m_maxRSSI) - m_maxRSSI = m_rssi; + if (m_rssi > m_minRSSI) + m_minRSSI = m_rssi; + if (m_rssi < m_maxRSSI) + m_maxRSSI = m_rssi; - m_aveRSSI += m_rssi; - m_rssiCount++; + m_aveRSSI += m_rssi; + m_rssiCount++; + } } if (m_debug) { diff --git a/src/host/p25/packet/Voice.cpp b/src/host/p25/packet/Voice.cpp index 93dbd795..965f2dd8 100644 --- a/src/host/p25/packet/Voice.cpp +++ b/src/host/p25/packet/Voice.cpp @@ -57,6 +57,7 @@ void Voice::resetRF() m_rfFrames = 0U; m_rfErrs = 0U; + m_dfsiReportedErrs = 0U; m_rfBits = 1U; m_rfUndecodableLC = 0U; m_pktLDU1Count = 0U; @@ -594,6 +595,7 @@ bool Voice::process(uint8_t* data, uint32_t len) m_rfFrames = 0U; m_rfErrs = 0U; + m_dfsiReportedErrs = 0U; m_rfBits = 1U; m_rfUndecodableLC = 0U; m_pktLDU1Count = 0U; @@ -646,24 +648,24 @@ bool Voice::process(uint8_t* data, uint32_t len) // ensure our srcId and dstId are sane from the last LDU1 if (m_rfLastLDU1.getDstId() != 0U) { if (m_rfLC.getDstId() != m_rfLastLDU1.getDstId()) { - LogWarning(LOG_RF, P25_LDU2_STR ", dstId = %u doesn't match last LDU1 dstId = %u, fixing", + LogWarning(LOG_RF, P25_LDU1_STR ", dstId = %u doesn't match last LDU1 dstId = %u, fixing", m_rfLC.getDstId(), m_rfLastLDU1.getDstId()); m_rfLC.setDstId(m_rfLastLDU1.getDstId()); } } else { - LogWarning(LOG_RF, P25_LDU2_STR ", last LDU1 LC has bad data, dstId = 0"); + LogWarning(LOG_RF, P25_LDU1_STR ", last LDU1 LC has bad data, dstId = 0"); } if (m_rfLastLDU1.getSrcId() != 0U) { if (m_rfLC.getSrcId() != m_rfLastLDU1.getSrcId()) { - LogWarning(LOG_RF, P25_LDU2_STR ", srcId = %u doesn't match last LDU1 srcId = %u, fixing", + LogWarning(LOG_RF, P25_LDU1_STR ", srcId = %u doesn't match last LDU1 srcId = %u, fixing", m_rfLC.getSrcId(), m_rfLastLDU1.getSrcId()); m_rfLC.setSrcId(m_rfLastLDU1.getSrcId()); } } else { - LogWarning(LOG_RF, P25_LDU2_STR ", last LDU1 LC has bad data, srcId = 0"); + LogWarning(LOG_RF, P25_LDU1_STR ", last LDU1 LC has bad data, srcId = 0"); } m_rfUndecodableLC++; @@ -741,6 +743,11 @@ bool Voice::process(uint8_t* data, uint32_t len) // regenerate audio uint32_t errors = m_audio.process(data + 2U); + if (m_p25->m_isModemDFSI) { + errors = m_dfsiReportedErrs; // because the errors will have been "corrected" by the encoders + // within ModemV24 we should use the reported errors from the modem + // and not the audio vectors detected errors + } // replace audio with silence in cases where the error rate // has exceeded the configured threshold @@ -858,6 +865,11 @@ bool Voice::process(uint8_t* data, uint32_t len) // regenerate audio uint32_t errors = m_audio.process(data + 2U); + if (m_p25->m_isModemDFSI) { + errors = m_dfsiReportedErrs; // because the errors will have been "corrected" by the encoders + // within ModemV24 we should use the reported errors from the modem + // and not the audio vectors detected errors + } // replace audio with silence in cases where the error rate // has exceeded the configured threshold @@ -1363,6 +1375,7 @@ Voice::Voice(Control* p25, bool debug, bool verbose) : m_rfFrames(0U), m_rfBits(0U), m_rfErrs(0U), + m_dfsiReportedErrs(0U), m_rfUndecodableLC(0U), m_netFrames(0U), m_netLost(0U), diff --git a/src/host/p25/packet/Voice.h b/src/host/p25/packet/Voice.h index c515e111..1346884a 100644 --- a/src/host/p25/packet/Voice.h +++ b/src/host/p25/packet/Voice.h @@ -86,6 +86,7 @@ namespace p25 uint32_t m_rfFrames; uint32_t m_rfBits; uint32_t m_rfErrs; + uint16_t m_dfsiReportedErrs; uint32_t m_rfUndecodableLC; uint32_t m_netFrames; uint32_t m_netLost;