From c52ae588162dca70bc93fd416261291efcbface9 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 11 Jun 2023 14:58:29 +0100 Subject: [PATCH] Add JSON RSSI and BER to P25. --- P25Control.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++---- P25Control.h | 7 +++++ YSFControl.cpp | 60 +++++++++++++++++++++---------------------- 3 files changed, 102 insertions(+), 35 deletions(-) diff --git a/P25Control.cpp b/P25Control.cpp index 0e69298..e7689ad 100644 --- a/P25Control.cpp +++ b/P25Control.cpp @@ -31,6 +31,9 @@ #include #include +const unsigned int RSSI_COUNT = 7U; // 7 * 180ms = 1260ms +const unsigned int BER_COUNT = 7U * 1233U; // 7 * 180ms = 1260ms + // #define DUMP_P25 const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -79,7 +82,11 @@ m_rssi(0U), m_maxRSSI(0U), m_minRSSI(0U), m_aveRSSI(0U), +m_rssiCountTotal(0U), +m_rssiAccum(0U), m_rssiCount(0U), +m_bitsCount(0U), +m_bitErrsAccum(0U), m_enabled(true), m_fp(NULL) { @@ -128,8 +135,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) std::string source = m_lookup->find(srcId); if (m_rssi != 0U) { - 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); - writeJSONRF("lost", 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_rssiCountTotal); + writeJSONRF("lost", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { 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)); writeJSONRF("lost", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -217,7 +224,9 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } if (duid == P25_DUID_LDU1) { @@ -266,8 +275,14 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + createRFHeader(); writeNetwork(data + 2U, P25_DUID_HEADER, false); } else if (m_rfState == RS_RF_AUDIO) { @@ -298,6 +313,10 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_rfFrames++; m_lastDUID = duid; + m_bitsCount += 1233U; + m_bitErrsAccum += errors; + writeJSONBER(); + // Add busy bits addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); @@ -344,6 +363,10 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_rfFrames++; m_lastDUID = duid; + m_bitsCount += 1233U; + m_bitErrsAccum += errors; + writeJSONBER(); + // Add busy bits addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); @@ -469,8 +492,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_lastDUID = duid; if (m_rssi != 0U) { - 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); - writeJSONRF("end", 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_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { 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)); writeJSONRF("end", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -1213,6 +1236,43 @@ void CP25Control::enable(bool enabled) m_enabled = enabled; } +void CP25Control::writeJSONRSSI() +{ + m_rssiAccum += m_rssi; + m_rssiCount++; + + if (m_rssiCount >= RSSI_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "P25"; + + json["value"] = -int(m_rssiAccum / m_rssiCount); + + WriteJSON("RSSI", json); + + m_rssiAccum = 0U; + m_rssiCount = 0U; + } +} + +void CP25Control::writeJSONBER() +{ + if (m_bitsCount >= BER_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "P25"; + + json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); + + WriteJSON("BER", json); + + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + } +} + void CP25Control::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); diff --git a/P25Control.h b/P25Control.h index de4d917..7d4814e 100644 --- a/P25Control.h +++ b/P25Control.h @@ -93,7 +93,11 @@ private: unsigned char m_maxRSSI; unsigned char m_minRSSI; unsigned int m_aveRSSI; + unsigned int m_rssiCountTotal; + unsigned int m_rssiAccum; unsigned int m_rssiCount; + unsigned int m_bitsCount; + unsigned int m_bitErrsAccum; bool m_enabled; FILE* m_fp; @@ -121,6 +125,9 @@ private: bool writeFile(const unsigned char* data, unsigned char length); void closeFile(); + void writeJSONRSSI(); + void writeJSONBER(); + void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); void writeJSONRF(const char* action, float duration, float ber); void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); diff --git a/YSFControl.cpp b/YSFControl.cpp index c8f4fed..5816e62 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -265,7 +265,7 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; m_rssiCountTotal = 1U; - + m_rssiAccum = m_rssi; m_rssiCount = 1U; @@ -1286,35 +1286,6 @@ void CYSFControl::enable(bool enabled) m_enabled = enabled; } -void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid) -{ - assert(action != NULL); - assert(mode != NULL); - assert(source != NULL); - - nlohmann::json json; - - writeJSONRF(json, action, source, dgid); - - json["mode"] = mode; - - WriteJSON("YSF", json); -} - -void CYSFControl::writeJSONRF(const char* action, float duration, float ber) -{ - assert(action != NULL); - - nlohmann::json json; - - writeJSONRF(json, action); - - json["duration"] = duration; - json["ber"] = ber; - - WriteJSON("YSF", json); -} - void CYSFControl::writeJSONRSSI() { m_rssiAccum += m_rssi; @@ -1355,6 +1326,35 @@ void CYSFControl::writeJSONBER(unsigned int bits, unsigned int errs) } } +void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid) +{ + assert(action != NULL); + assert(mode != NULL); + assert(source != NULL); + + nlohmann::json json; + + writeJSONRF(json, action, source, dgid); + + json["mode"] = mode; + + WriteJSON("YSF", json); +} + +void CYSFControl::writeJSONRF(const char* action, float duration, float ber) +{ + assert(action != NULL); + + nlohmann::json json; + + writeJSONRF(json, action); + + json["duration"] = duration; + json["ber"] = ber; + + WriteJSON("YSF", json); +} + void CYSFControl::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL);