more work on frame loss counting;

pull/32/head
Bryan Biedenkapp 3 years ago
parent 3d7f04f523
commit 702293b416

@ -49,7 +49,7 @@ using namespace dmr::packet;
// Constants // Constants
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const uint8_t MAX_LOST_FRAMES = 4U; const uint8_t MAX_LOST_FRAMES = 2U;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Static Class Members // Static Class Members
@ -206,51 +206,7 @@ bool Slot::processFrame(uint8_t *data, uint32_t len)
if (m_frameLossCnt > MAX_LOST_FRAMES) { if (m_frameLossCnt > MAX_LOST_FRAMES) {
m_frameLossCnt = 0U; m_frameLossCnt = 0U;
if (m_rfState == RS_RF_AUDIO) { processFrameLoss();
if (m_rssi != 0U) {
::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm",
m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
}
else {
::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%",
m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
}
LogMessage(LOG_RF, "DMR Slot %u, total frames: %d, total bits: %d, errors: %d, BER: %.4f%%",
m_slotNo, m_rfFrames, m_rfBits, m_rfErrs, float(m_rfErrs * 100U) / float(m_rfBits));
// release trunked grant (if necessary)
Slot *m_tscc = m_dmr->getTSCCSlot();
if (m_tscc != nullptr) {
if (m_tscc->m_enableTSCC && m_rfLC != nullptr) {
m_tscc->m_affiliations->releaseGrant(m_rfLC->getDstId(), false);
}
}
if (!m_tscc->m_enableTSCC) {
notifyCC_ReleaseGrant(m_rfLC->getDstId());
}
if (m_rfTimeout) {
writeEndRF();
return false;
}
else {
writeEndRF(true);
return true;
}
}
if (m_rfState == RS_RF_DATA) {
::ActivityLog("DMR", true, "Slot %u, RF data transmission lost", m_slotNo);
writeEndRF();
return false;
}
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
m_rfTGHang.stop();
return false; return false;
} }
@ -341,6 +297,7 @@ bool Slot::processFrame(uint8_t *data, uint32_t len)
case DT_VOICE_PI_HEADER: case DT_VOICE_PI_HEADER:
return m_voice->process(data, len); return m_voice->process(data, len);
case DT_TERMINATOR_WITH_LC: case DT_TERMINATOR_WITH_LC:
m_frameLossCnt = 0U;
case DT_DATA_HEADER: case DT_DATA_HEADER:
case DT_RATE_12_DATA: case DT_RATE_12_DATA:
case DT_RATE_34_DATA: case DT_RATE_34_DATA:
@ -603,6 +560,12 @@ void Slot::clock()
m_rfState = RS_RF_LISTENING; m_rfState = RS_RF_LISTENING;
} }
if (m_frameLossCnt > 0U && m_rfState == RS_RF_LISTENING)
m_frameLossCnt = 0U;
if (m_frameLossCnt >= MAX_LOST_FRAMES && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) {
processFrameLoss();
}
} }
/// <summary> /// <summary>
@ -938,6 +901,55 @@ void Slot::addFrame(const uint8_t *data, bool net, bool imm)
m_txQueue.addData(data, len); m_txQueue.addData(data, len);
} }
/// <summary>
/// Helper to process loss of frame stream from modem.
/// </summary>
void Slot::processFrameLoss()
{
if (m_rfState == RS_RF_AUDIO) {
if (m_rssi != 0U) {
::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm, loss count: %u",
m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount, m_frameLossCnt);
}
else {
::ActivityLog("DMR", true, "Slot %u RF voice transmission lost, %.1f seconds, BER: %.1f%%, loss count: %u",
m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_frameLossCnt);
}
LogMessage(LOG_RF, "DMR Slot %u, total frames: %d, total bits: %d, errors: %d, BER: %.4f%%",
m_slotNo, m_rfFrames, m_rfBits, m_rfErrs, float(m_rfErrs * 100U) / float(m_rfBits));
// release trunked grant (if necessary)
Slot *m_tscc = m_dmr->getTSCCSlot();
if (m_tscc != nullptr) {
if (m_tscc->m_enableTSCC && m_rfLC != nullptr) {
m_tscc->m_affiliations->releaseGrant(m_rfLC->getDstId(), false);
}
}
if (!m_tscc->m_enableTSCC) {
notifyCC_ReleaseGrant(m_rfLC->getDstId());
}
if (m_rfTimeout) {
writeEndRF();
}
else {
writeEndRF(true);
}
}
if (m_rfState == RS_RF_DATA) {
::ActivityLog("DMR", true, "Slot %u, RF data transmission lost", m_slotNo);
writeEndRF();
}
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
m_rfTGHang.stop();
}
/// <summary> /// <summary>
/// Helper to send a REST API request to the CC to release a channel grant at the end of a call. /// Helper to send a REST API request to the CC to release a channel grant at the end of a call.
/// </summary> /// </summary>

@ -268,6 +268,9 @@ namespace dmr
/// <summary>Add data frame to the data ring buffer.</summary> /// <summary>Add data frame to the data ring buffer.</summary>
void addFrame(const uint8_t* data, bool net = false, bool imm = false); void addFrame(const uint8_t* data, bool net = false, bool imm = false);
/// <summary>Helper to process loss of frame stream from modem.</summary>
void processFrameLoss();
/// <summary>Helper to send a REST API request to the CC to release a channel grant at the end of a call.</summary> /// <summary>Helper to send a REST API request to the CC to release a channel grant at the end of a call.</summary>
void notifyCC_ReleaseGrant(uint32_t dstId); void notifyCC_ReleaseGrant(uint32_t dstId);
/// <summary>Helper to send a REST API request to the CC to "touch" a channel grant to refresh grant timers.</summary> /// <summary>Helper to send a REST API request to the CC to "touch" a channel grant to refresh grant timers.</summary>

@ -365,37 +365,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len)
if (m_frameLossCnt > MAX_LOST_FRAMES) { if (m_frameLossCnt > MAX_LOST_FRAMES) {
m_frameLossCnt = 0U; m_frameLossCnt = 0U;
if (m_rfState == RS_RF_AUDIO) { processFrameLoss();
if (m_rssi != 0U) {
::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm",
float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
}
else {
::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%",
float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits));
}
LogMessage(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_TX_REL ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%",
m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits));
m_affiliations.releaseGrant(m_rfLC.getDstId(), false);
if (!m_control) {
notifyCC_ReleaseGrant(m_rfLC.getDstId());
}
writeEndRF();
return false;
}
if (m_rfState == RS_RF_DATA) {
writeEndRF();
return false;
}
m_rfState = RS_RF_LISTENING;
m_rfMask = 0x00U;
m_rfLC.reset();
return false; return false;
} }
@ -676,6 +646,12 @@ void Control::clock(uint32_t ms)
m_rfState = RS_RF_LISTENING; m_rfState = RS_RF_LISTENING;
} }
if (m_frameLossCnt > 0U && m_rfState == RS_RF_LISTENING)
m_frameLossCnt = 0U;
if (m_frameLossCnt >= MAX_LOST_FRAMES && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) {
processFrameLoss();
}
// clock data and trunking // clock data and trunking
if (m_trunk != nullptr) { if (m_trunk != nullptr) {
m_trunk->clock(ms); m_trunk->clock(ms);
@ -915,6 +891,42 @@ void Control::processNetwork()
} }
} }
/// <summary>
/// Helper to process loss of frame stream from modem.
/// </summary>
void Control::processFrameLoss()
{
if (m_rfState == RS_RF_AUDIO) {
if (m_rssi != 0U) {
::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm, loss count: %u",
float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount, m_frameLossCnt);
}
else {
::ActivityLog("NXDN", true, "transmission lost, %.1f seconds, BER: %.1f%%, loss count: %u",
float(m_voice->m_rfFrames) / 12.5F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_frameLossCnt);
}
LogMessage(LOG_RF, "NXDN, " NXDN_RTCH_MSG_TYPE_TX_REL ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%",
m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits));
m_affiliations.releaseGrant(m_rfLC.getDstId(), false);
if (!m_control) {
notifyCC_ReleaseGrant(m_rfLC.getDstId());
}
writeEndRF();
}
if (m_rfState == RS_RF_DATA) {
writeEndRF();
}
m_rfState = RS_RF_LISTENING;
m_rfMask = 0x00U;
m_rfLC.reset();
}
/// <summary> /// <summary>
/// Helper to send a REST API request to the CC to release a channel grant at the end of a call. /// Helper to send a REST API request to the CC to release a channel grant at the end of a call.
/// </summary> /// </summary>

@ -214,6 +214,8 @@ namespace nxdn
/// <summary>Process a data frames from the network.</summary> /// <summary>Process a data frames from the network.</summary>
void processNetwork(); void processNetwork();
/// <summary>Helper to process loss of frame stream from modem.</summary>
void processFrameLoss();
/// <summary>Helper to send a REST API request to the CC to release a channel grant at the end of a call.</summary> /// <summary>Helper to send a REST API request to the CC to release a channel grant at the end of a call.</summary>
void notifyCC_ReleaseGrant(uint32_t dstId); void notifyCC_ReleaseGrant(uint32_t dstId);

@ -235,6 +235,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
m_nxdn->m_rfState = RS_RF_LISTENING; m_nxdn->m_rfState = RS_RF_LISTENING;
m_nxdn->m_rfMask = 0x00U; m_nxdn->m_rfMask = 0x00U;
m_nxdn->m_rfLC.reset(); m_nxdn->m_rfLC.reset();
m_nxdn->m_frameLossCnt = 0U;
return false; return false;
} }
} else if (type == RTCH_MESSAGE_TYPE_VCALL) { } else if (type == RTCH_MESSAGE_TYPE_VCALL) {

@ -58,7 +58,7 @@ const uint8_t MAX_SYNC_BYTES_ERRS = 4U;
const uint32_t TSBK_PCH_CCH_CNT = 6U; const uint32_t TSBK_PCH_CCH_CNT = 6U;
const uint32_t MAX_PREAMBLE_TDU_CNT = 64U; const uint32_t MAX_PREAMBLE_TDU_CNT = 64U;
const uint8_t MAX_LOST_FRAMES = 4U; const uint8_t MAX_LOST_FRAMES = 6U;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Public Class Members // Public Class Members
@ -448,63 +448,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len)
if (m_frameLossCnt > MAX_LOST_FRAMES) { if (m_frameLossCnt > MAX_LOST_FRAMES) {
m_frameLossCnt = 0U; m_frameLossCnt = 0U;
if (m_rfState == RS_RF_AUDIO) { processFrameLoss();
if (m_rssi != 0U) {
::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm",
float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
}
else {
::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%",
float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits));
}
LogMessage(LOG_RF, P25_TDU_STR ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%",
m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits));
m_affiliations.releaseGrant(m_voice->m_rfLC.getDstId(), false);
if (!m_control) {
notifyCC_ReleaseGrant(m_voice->m_rfLC.getDstId());
}
m_trunk->writeNet_TSDU_Call_Term(m_voice->m_rfLC.getSrcId(), m_voice->m_rfLC.getDstId());
writeRF_TDU(false);
m_voice->m_lastDUID = P25_DUID_TDU;
m_voice->writeNetwork(data + 2U, P25_DUID_TDU);
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
m_rfTGHang.stop();
m_tailOnIdle = true;
m_rfTimeout.stop();
m_txQueue.clear();
if (m_network != nullptr)
m_network->resetP25();
return false;
}
if (m_rfState == RS_RF_DATA) {
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
m_rfTGHang.stop();
m_tailOnIdle = true;
m_data->resetRF();
m_rfTimeout.stop();
m_txQueue.clear();
return false;
}
m_rfState = RS_RF_LISTENING;
m_voice->resetRF();
m_data->resetRF();
return false; return false;
} }
@ -613,6 +557,7 @@ bool Control::processFrame(uint8_t* data, uint32_t len)
case P25_DUID_TDU: case P25_DUID_TDU:
case P25_DUID_TDULC: case P25_DUID_TDULC:
m_frameLossCnt = 0U;
ret = m_voice->process(data, len); ret = m_voice->process(data, len);
break; break;
@ -849,6 +794,12 @@ void Control::clock(uint32_t ms)
m_rfState = RS_RF_LISTENING; m_rfState = RS_RF_LISTENING;
} }
if (m_frameLossCnt > 0U && m_rfState == RS_RF_LISTENING)
m_frameLossCnt = 0U;
if (m_frameLossCnt >= MAX_LOST_FRAMES && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA)) {
processFrameLoss();
}
// clock data and trunking // clock data and trunking
if (m_data != nullptr) { if (m_data != nullptr) {
m_data->clock(ms); m_data->clock(ms);
@ -1294,6 +1245,65 @@ void Control::processNetwork()
} }
} }
/// <summary>
/// Helper to process loss of frame stream from modem.
/// </summary>
void Control::processFrameLoss()
{
if (m_rfState == RS_RF_AUDIO) {
if (m_rssi != 0U) {
::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm, loss count: %u",
float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount, m_frameLossCnt);
}
else {
::ActivityLog("P25", true, "transmission lost, %.1f seconds, BER: %.1f%%, loss count: %u",
float(m_voice->m_rfFrames) / 5.56F, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits), m_frameLossCnt);
}
LogMessage(LOG_RF, P25_TDU_STR ", total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%",
m_voice->m_rfFrames, m_voice->m_rfBits, m_voice->m_rfUndecodableLC, m_voice->m_rfErrs, float(m_voice->m_rfErrs * 100U) / float(m_voice->m_rfBits));
m_affiliations.releaseGrant(m_voice->m_rfLC.getDstId(), false);
if (!m_control) {
notifyCC_ReleaseGrant(m_voice->m_rfLC.getDstId());
}
m_trunk->writeNet_TSDU_Call_Term(m_voice->m_rfLC.getSrcId(), m_voice->m_rfLC.getDstId());
writeRF_TDU(false);
m_voice->m_lastDUID = P25_DUID_TDU;
//m_voice->writeNetwork(data + 2U, P25_DUID_TDU);
m_voice->writeNet_TDU();
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
m_rfTGHang.stop();
m_tailOnIdle = true;
m_rfTimeout.stop();
m_txQueue.clear();
if (m_network != nullptr)
m_network->resetP25();
}
if (m_rfState == RS_RF_DATA) {
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
m_rfTGHang.stop();
m_tailOnIdle = true;
m_data->resetRF();
m_rfTimeout.stop();
m_txQueue.clear();
}
m_voice->resetRF();
m_data->resetRF();
}
/// <summary> /// <summary>
/// Helper to send a REST API request to the CC to release a channel grant at the end of a call. /// Helper to send a REST API request to the CC to release a channel grant at the end of a call.
/// </summary> /// </summary>

@ -237,6 +237,8 @@ namespace p25
/// <summary>Process a data frames from the network.</summary> /// <summary>Process a data frames from the network.</summary>
void processNetwork(); void processNetwork();
/// <summary>Helper to process loss of frame stream from modem.</summary>
void processFrameLoss();
/// <summary>Helper to send a REST API request to the CC to release a channel grant at the end of a call.</summary> /// <summary>Helper to send a REST API request to the CC to release a channel grant at the end of a call.</summary>
void notifyCC_ReleaseGrant(uint32_t dstId); void notifyCC_ReleaseGrant(uint32_t dstId);

Loading…
Cancel
Save

Powered by TurnKey Linux.