mirror of
https://github.com/g4klx/MMDVMHost
synced 2025-12-20 14:15:37 +08:00
Merge branch 'master' into P25Changes
This commit is contained in:
109
P25Control.cpp
109
P25Control.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016-2019,2021,2024 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com> N2PLL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -83,6 +83,7 @@ m_maxRSSI(0U),
|
||||
m_minRSSI(0U),
|
||||
m_aveRSSI(0U),
|
||||
m_rssiCount(0U),
|
||||
m_enabled(true),
|
||||
m_fp(NULL)
|
||||
{
|
||||
assert(display != NULL);
|
||||
@@ -118,13 +119,20 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (!m_enabled)
|
||||
return false;
|
||||
|
||||
bool sync = data[1U] == 0x01U;
|
||||
|
||||
if (data[0U] == TAG_LOST && m_rfState == RS_RF_AUDIO) {
|
||||
bool grp = m_rfData.getLCF() == P25_LCF_GROUP;
|
||||
unsigned int dstId = m_rfData.getDstId();
|
||||
std::string source = m_lookup->find(m_rfData.getSrcId());
|
||||
|
||||
if (m_rssi != 0U)
|
||||
LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
LogMessage("P25, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
else
|
||||
LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
LogMessage("P25, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
|
||||
LogMessage("P25, total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_rfFrames, m_rfBits, m_rfUndecodableLC, m_rfErrs, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
|
||||
@@ -315,7 +323,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
m_rfFrames++;
|
||||
m_lastDUID = duid;
|
||||
|
||||
// Add busy bits
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
#if defined(DUMP_P25)
|
||||
@@ -371,7 +379,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
m_rfFrames++;
|
||||
m_lastDUID = duid;
|
||||
|
||||
// Add busy bits
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
#if defined(DUMP_P25)
|
||||
@@ -404,14 +412,15 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int srcId = m_rfData.getSrcId();
|
||||
bool grp = m_rfData.getLCF() == P25_LCF_GROUP;
|
||||
unsigned int dstId = m_rfData.getDstId();
|
||||
|
||||
std::string source = m_lookup->find(m_rfData.getSrcId());
|
||||
|
||||
unsigned char data[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
|
||||
|
||||
switch (m_rfData.getLCF()) {
|
||||
case P25_LCF_TSBK_CALL_ALERT:
|
||||
LogMessage("P25, received RF TSDU transmission, CALL ALERT from %u to %u", srcId, dstId);
|
||||
LogMessage("P25, received RF TSDU transmission, CALL ALERT from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId);
|
||||
::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
|
||||
|
||||
// Regenerate Sync
|
||||
@@ -423,8 +432,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
// Regenerate TDULC Data
|
||||
m_rfData.encodeTSDU(data + 2U);
|
||||
|
||||
// Add busy bits
|
||||
addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, true, false);
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
// Set first busy bits to 1,1
|
||||
setBusyBits(data + 2U, P25_SS0_START, true, true);
|
||||
@@ -437,7 +446,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
}
|
||||
break;
|
||||
case P25_LCF_TSBK_ACK_RSP_FNE:
|
||||
LogMessage("P25, received RF TSDU transmission, ACK RESPONSE FNE from %u to %u", srcId, dstId);
|
||||
LogMessage("P25, received RF TSDU transmission, ACK RESPONSE FNE from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId);
|
||||
::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
|
||||
|
||||
// Regenerate Sync
|
||||
@@ -449,8 +458,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
// Regenerate TDULC Data
|
||||
m_rfData.encodeTSDU(data + 2U);
|
||||
|
||||
// Add busy bits
|
||||
addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, true, false);
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
// Set first busy bits to 1,1
|
||||
setBusyBits(data + 2U, P25_SS0_START, true, true);
|
||||
@@ -481,18 +490,22 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
// Regenerate NID
|
||||
m_nid.encode(data + 2U, P25_DUID_TERM);
|
||||
|
||||
// Add busy bits
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(data + 2U, P25_TERM_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
bool grp = m_rfData.getLCF() == P25_LCF_GROUP;
|
||||
unsigned int dstId = m_rfData.getDstId();
|
||||
std::string source = m_lookup->find(m_rfData.getSrcId());
|
||||
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
m_rfTimeout.stop();
|
||||
m_rfData.reset();
|
||||
m_lastDUID = duid;
|
||||
|
||||
if (m_rssi != 0U)
|
||||
LogMessage("P25, received RF end of voice transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
LogMessage("P25, received RF end of voice transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
else
|
||||
LogMessage("P25, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
LogMessage("P25, received RF end of voice transmission from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
|
||||
LogMessage("P25, total frames: %d, bits: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_rfFrames, m_rfBits, m_rfUndecodableLC, m_rfErrs, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
|
||||
@@ -594,7 +607,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||
// Regenerate NID
|
||||
m_nid.encode(pdu + 2U, P25_DUID_PDU);
|
||||
|
||||
// Add busy bits
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(pdu + 2U, newBitLength, false, true);
|
||||
|
||||
if (m_duplex) {
|
||||
@@ -645,6 +658,9 @@ void CP25Control::writeNetwork()
|
||||
if (length == 0U)
|
||||
return;
|
||||
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE)
|
||||
return;
|
||||
|
||||
@@ -948,7 +964,7 @@ void CP25Control::createRFHeader()
|
||||
// Add the dummy header
|
||||
m_rfData.encodeHeader(buffer + 2U);
|
||||
|
||||
// Add busy bits
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
m_rfFrames = 0U;
|
||||
@@ -1025,8 +1041,13 @@ void CP25Control::createNetHeader()
|
||||
|
||||
// Add busy bits
|
||||
if (m_remoteGateway)
|
||||
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, false, false);
|
||||
// Add busy bits, inbound/outbound
|
||||
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, true, false);
|
||||
else if (m_duplex)
|
||||
// Add busy bits, inbound idle
|
||||
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, true, true);
|
||||
else
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
writeQueueNet(buffer, P25_HDR_FRAME_LENGTH_BYTES + 2U);
|
||||
@@ -1069,8 +1090,13 @@ void CP25Control::createNetLDU1()
|
||||
|
||||
// Add busy bits
|
||||
if (m_remoteGateway)
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, false);
|
||||
// Add busy bits, inbound/outbound
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, true, false);
|
||||
else if (m_duplex)
|
||||
// Add busy bits, inbound idle
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, true, true);
|
||||
else
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
|
||||
@@ -1117,8 +1143,13 @@ void CP25Control::createNetLDU2()
|
||||
|
||||
// Add busy bits
|
||||
if (m_remoteGateway)
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, false);
|
||||
// Add busy bits, inbound/outbound
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, true, false);
|
||||
else if (m_duplex)
|
||||
// Add busy bits, inbound idle
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, true, true);
|
||||
else
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
|
||||
@@ -1144,13 +1175,20 @@ void CP25Control::createNetTerminator()
|
||||
|
||||
// Add busy bits
|
||||
if (m_remoteGateway)
|
||||
addBusyBits(buffer + 2U, P25_TERM_FRAME_LENGTH_BITS, false, false);
|
||||
// Add busy bits, inbound/outbound
|
||||
addBusyBits(buffer + 2U, P25_TERM_FRAME_LENGTH_BITS, true, false);
|
||||
else if (m_duplex)
|
||||
// Add busy bits, inbound idle
|
||||
addBusyBits(buffer + 2U, P25_TERM_FRAME_LENGTH_BITS, true, true);
|
||||
else
|
||||
// Add busy bits, inbound busy
|
||||
addBusyBits(buffer + 2U, P25_TERM_FRAME_LENGTH_BITS, false, true);
|
||||
|
||||
writeQueueNet(buffer, P25_TERM_FRAME_LENGTH_BYTES + 2U);
|
||||
|
||||
LogMessage("P25, network end of transmission, %.1f seconds, %u%% packet loss", float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames);
|
||||
std::string source = m_lookup->find(m_netData.getSrcId());
|
||||
|
||||
LogMessage("P25, network end of transmission from %s to %s%u, %.1f seconds, %u%% packet loss", source.c_str(), m_netData.getLCF() == P25_LCF_GROUP ? "TG " : "", m_netData.getDstId(), float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames);
|
||||
|
||||
m_display->clearP25();
|
||||
m_netTimeout.stop();
|
||||
@@ -1200,3 +1238,28 @@ void CP25Control::closeFile()
|
||||
m_fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CP25Control::isBusy() const
|
||||
{
|
||||
return m_rfState != RS_RF_LISTENING || m_netState != RS_NET_IDLE;
|
||||
}
|
||||
|
||||
void CP25Control::enable(bool enabled)
|
||||
{
|
||||
if (!enabled && m_enabled) {
|
||||
m_queue.clear();
|
||||
|
||||
// Reset the RF section
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
m_rfTimeout.stop();
|
||||
m_rfData.reset();
|
||||
|
||||
// Reset the networking section
|
||||
m_netTimeout.stop();
|
||||
m_networkWatchdog.stop();
|
||||
m_netData.reset();
|
||||
m_netState = RS_NET_IDLE;
|
||||
}
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user