diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 59d5a0a..39bd9b9 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -54,6 +54,12 @@ FLCO CDMRSlot::m_flco2; unsigned char CDMRSlot::m_id2 = 0U; bool CDMRSlot::m_voice2 = true; +const unsigned char TALKER_ID_NONE = 0x00U; +const unsigned char TALKER_ID_HEADER = 0x01U; +const unsigned char TALKER_ID_BLOCK1 = 0x02U; +const unsigned char TALKER_ID_BLOCK2 = 0x04U; +const unsigned char TALKER_ID_BLOCK3 = 0x08U; + // #define DUMP_DMR CDMRSlot::CDMRSlot(unsigned int slotNo, unsigned int timeout) : @@ -65,10 +71,12 @@ m_rfEmbeddedLC(), m_rfEmbeddedData(NULL), m_rfEmbeddedReadN(0U), m_rfEmbeddedWriteN(1U), +m_rfTalkerId(TALKER_ID_NONE), m_netEmbeddedLC(), m_netEmbeddedData(NULL), m_netEmbeddedReadN(0U), m_netEmbeddedWriteN(1U), +m_netTalkerId(TALKER_ID_NONE), m_rfLC(NULL), m_netLC(NULL), m_rfDataHeader(), @@ -222,8 +230,10 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_rfSeqNo = 0U; m_rfBits = 1U; m_rfErrs = 0U; + m_rfEmbeddedReadN = 0U; m_rfEmbeddedWriteN = 1U; + m_rfTalkerId = TALKER_ID_NONE; m_minRSSI = m_rssi; m_maxRSSI = m_rssi; @@ -452,7 +462,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (ret) { trellis.encode(payload, data + 2U); } else { - LogMessage("DMR Slot %u, unfixable RF rate 3/4 data", m_slotNo); + LogDebug("DMR Slot %u, unfixable rate 3/4 data", m_slotNo); CUtils::dump(1U, "Data", data + 2U, DMR_FRAME_LENGTH_BYTES); } } @@ -485,7 +495,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) unsigned char fid = m_rfLC->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) { errors = m_fec.regenerateDMR(data + 2U); - LogDebug("DMR Slot %u, audio sequence no. 0, errs: %u/141", m_slotNo, errors); + LogDebug("DMR Slot %u, audio sequence no. 0, errs: %u/141 (%.1f%%)", m_slotNo, errors, float(errors) / 1.41F); + m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); m_rfErrs += errors; } @@ -518,7 +529,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) unsigned char fid = m_rfLC->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) { errors = m_fec.regenerateDMR(data + 2U); - LogDebug("DMR Slot %u, audio sequence no. %u, errs: %u/141", m_slotNo, m_rfN, errors); + LogDebug("DMR Slot %u, audio sequence no. %u, errs: %u/141 (%.1f%%)", m_slotNo, m_rfN, errors, float(errors) / 1.41F); + m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); m_rfErrs += errors; } @@ -547,23 +559,35 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) break; case FLCO_GPS_INFO: ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); - CUtils::dump(1U, text, data, 9U); + CUtils::dump(2U, text, data, 9U); break; case FLCO_TALKER_ALIAS_HEADER: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_rfTalkerId & TALKER_ID_HEADER)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_rfTalkerId |= TALKER_ID_HEADER; + } break; case FLCO_TALKER_ALIAS_BLOCK1: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_rfTalkerId |= TALKER_ID_BLOCK1; + } break; case FLCO_TALKER_ALIAS_BLOCK2: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_rfTalkerId |= TALKER_ID_BLOCK2; + } break; case FLCO_TALKER_ALIAS_BLOCK3: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_rfTalkerId |= TALKER_ID_BLOCK3; + } break; default: ::sprintf(text, "DMR Slot %u, Unknown Embedded Data", m_slotNo); @@ -657,8 +681,10 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_rfSeqNo = 0U; m_rfBits = 1U; m_rfErrs = 0U; + m_rfEmbeddedReadN = 0U; m_rfEmbeddedWriteN = 1U; + m_rfTalkerId = TALKER_ID_NONE; m_minRSSI = m_rssi; m_maxRSSI = m_rssi; @@ -686,7 +712,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) unsigned char fid = m_rfLC->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) { errors = m_fec.regenerateDMR(data + 2U); - LogDebug("DMR Slot %u, audio sequence no. %u, errs: %u/141", m_slotNo, m_rfN, errors); + LogDebug("DMR Slot %u, audio sequence no. %u, errs: %u/141 (%.1f%%)", m_slotNo, m_rfN, errors, float(errors) / 1.41F); m_rfErrs += errors; } @@ -710,6 +736,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) setShortLC(m_slotNo, dstId, flco, true); m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R"); m_display->writeDMRRSSI(m_slotNo, m_rssi); + m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); } LogMessage("DMR Slot %u, received RF late entry from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str()); @@ -939,8 +966,10 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_netLost = 0U; m_netBits = 1U; m_netErrs = 0U; + m_netEmbeddedReadN = 0U; m_netEmbeddedWriteN = 1U; + m_netTalkerId = TALKER_ID_NONE; if (m_duplex) { m_queue.clear(); @@ -1195,8 +1224,10 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_netLost = 0U; m_netBits = 1U; m_netErrs = 0U; + m_netEmbeddedReadN = 0U; m_netEmbeddedWriteN = 1U; + m_netTalkerId = TALKER_ID_NONE; m_netState = RS_NET_AUDIO; @@ -1284,23 +1315,35 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) break; case FLCO_GPS_INFO: ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); - CUtils::dump(1U, text, data, 9U); + CUtils::dump(2U, text, data, 9U); break; case FLCO_TALKER_ALIAS_HEADER: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_netTalkerId & TALKER_ID_HEADER)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_netTalkerId |= TALKER_ID_HEADER; + } break; case FLCO_TALKER_ALIAS_BLOCK1: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_netTalkerId & TALKER_ID_BLOCK1)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_netTalkerId |= TALKER_ID_BLOCK1; + } break; case FLCO_TALKER_ALIAS_BLOCK2: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_netTalkerId & TALKER_ID_BLOCK2)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_netTalkerId |= TALKER_ID_BLOCK2; + } break; case FLCO_TALKER_ALIAS_BLOCK3: - ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); - CUtils::dump(1U, text, data, 9U); + if (!(m_netTalkerId & TALKER_ID_BLOCK3)) { + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); + CUtils::dump(2U, text, data, 9U); + m_netTalkerId |= TALKER_ID_BLOCK3; + } break; default: ::sprintf(text, "DMR Slot %u, Unknown Embedded Data", m_slotNo); @@ -1426,12 +1469,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) CDMRTrellis trellis; unsigned char payload[18U]; bool ret = trellis.decode(data + 2U, payload); - if (ret) { + if (ret) trellis.encode(payload, data + 2U); - } else { - LogMessage("DMR Slot %u, unfixable network rate 3/4 data", m_slotNo); - CUtils::dump(1U, "Data", data + 2U, DMR_FRAME_LENGTH_BYTES); - } } // Regenerate the Slot Type diff --git a/DMRSlot.h b/DMRSlot.h index ac5290e..a4f87ae 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -61,10 +61,12 @@ private: CDMREmbeddedData* m_rfEmbeddedData; unsigned int m_rfEmbeddedReadN; unsigned int m_rfEmbeddedWriteN; + unsigned char m_rfTalkerId; CDMREmbeddedData m_netEmbeddedLC; CDMREmbeddedData* m_netEmbeddedData; unsigned int m_netEmbeddedReadN; unsigned int m_netEmbeddedWriteN; + unsigned char m_netTalkerId; CDMRLC* m_rfLC; CDMRLC* m_netLC; CDMRDataHeader m_rfDataHeader; diff --git a/DStarControl.cpp b/DStarControl.cpp index c5288ab..f8d4e9c 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -300,12 +300,14 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) return false; } else if (m_rfState == RS_RF_AUDIO) { unsigned int errors = 0U; - if (!m_rfHeader.isDataPacket()) + if (!m_rfHeader.isDataPacket()) { errors = m_fec.regenerateDStar(data + 1U); + m_display->writeDStarBER(float(errors) / 0.48F); + LogDebug("D-Star, audio sequence no. %u, errs: %u/48 (%.1f%%)", m_rfN, errors, float(errors) / 0.48F); + m_rfErrs += errors; + } - m_rfErrs += errors; m_rfBits += 48U; - m_rfFrames++; // The sync is regenerated by the modem so can do exact match @@ -318,8 +320,6 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_display->writeDStarRSSI(m_rssi); } - // LogDebug("D-Star, audio sequence no. %u, errs: %u/48", m_rfN, errors); - if (m_net) writeNetworkDataRF(data, errors, false); @@ -428,14 +428,14 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) delete header; unsigned int errors = 0U; - if (!m_rfHeader.isDataPacket()) + if (!m_rfHeader.isDataPacket()) { errors = m_fec.regenerateDStar(data + 1U); + LogDebug("D-Star, audio sequence no. %u, errs: %u/48 (%.1f%%)", m_rfN, errors, float(errors) / 0.48F); + m_rfErrs += errors; + } - m_rfErrs += errors; m_rfBits += 48U; - // LogDebug("D-Star, audio sequence no. %u, errs: %u/48", m_rfN, errors); - if (m_net) writeNetworkDataRF(data, errors, false); @@ -451,6 +451,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (m_netState == RS_NET_IDLE) { m_display->writeDStar((char*)my1, (char*)my2, (char*)your, "R", " "); m_display->writeDStarRSSI(m_rssi); + m_display->writeDStarBER(float(errors) / 0.48F); } LogMessage("D-Star, received RF late entry from %8.8s/%4.4s to %8.8s", my1, my2, your); @@ -624,8 +625,6 @@ void CDStarControl::writeNetwork() m_netN = n; - // LogDebug("D-Star, audio sequence no. %u, errs: %u/48", m_netN, errors); - // Regenerate the sync if (n == 0U) CSync::addDStarSync(data + 2U); diff --git a/Display.cpp b/Display.cpp index 199351c..7959d69 100644 --- a/Display.cpp +++ b/Display.cpp @@ -90,6 +90,11 @@ void CDisplay::writeDStarRSSI(unsigned char rssi) writeDStarRSSIInt(rssi); } +void CDisplay::writeDStarBER(float ber) +{ + writeDStarBERInt(ber); +} + void CDisplay::clearDStar() { if (m_timer1.hasExpired()) { @@ -122,6 +127,11 @@ void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi) writeDMRRSSIInt(slotNo, rssi); } +void CDisplay::writeDMRBER(unsigned int slotNo, float ber) +{ + writeDMRBERInt(slotNo, ber); +} + void CDisplay::clearDMR(unsigned int slotNo) { if (slotNo == 1U) { @@ -162,6 +172,11 @@ void CDisplay::writeFusionRSSI(unsigned char rssi) writeFusionRSSIInt(rssi); } +void CDisplay::writeFusionBER(float ber) +{ + writeFusionBERInt(ber); +} + void CDisplay::clearFusion() { if (m_timer1.hasExpired()) { @@ -190,6 +205,11 @@ void CDisplay::writeP25RSSI(unsigned char rssi) writeP25RSSIInt(rssi); } +void CDisplay::writeP25BER(float ber) +{ + writeP25BERInt(ber); +} + void CDisplay::clearP25() { if (m_timer1.hasExpired()) { @@ -265,14 +285,30 @@ void CDisplay::writeDStarRSSIInt(unsigned char rssi) { } +void CDisplay::writeDStarBERInt(float ber) +{ +} + void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) { } +void CDisplay::writeDMRBERInt(unsigned int slotNo, float ber) +{ +} + void CDisplay::writeFusionRSSIInt(unsigned char rssi) { } +void CDisplay::writeFusionBERInt(float ber) +{ +} + void CDisplay::writeP25RSSIInt(unsigned char rssi) { } + +void CDisplay::writeP25BERInt(float ber) +{ +} diff --git a/Display.h b/Display.h index 3444a76..9e3d884 100644 --- a/Display.h +++ b/Display.h @@ -37,18 +37,22 @@ public: void writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); void writeDStarRSSI(unsigned char rssi); + void writeDStarBER(float ber); void clearDStar(); void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); void writeDMRRSSI(unsigned int slotNo, unsigned char rssi); + void writeDMRBER(unsigned int slotNo, float ber); void clearDMR(unsigned int slotNo); void writeFusion(const char* source, const char* dest, const char* type, const char* origin); void writeFusionRSSI(unsigned char rssi); + void writeFusionBER(float ber); void clearFusion(); void writeP25(const char* source, bool group, unsigned int dest, const char* type); void writeP25RSSI(unsigned char rssi); + void writeP25BER(float ber); void clearP25(); void writeCW(); @@ -65,18 +69,22 @@ protected: virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) = 0; virtual void writeDStarRSSIInt(unsigned char rssi); + virtual void writeDStarBERInt(float ber); virtual void clearDStarInt() = 0; virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0; virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi); + virtual void writeDMRBERInt(unsigned int slotNo, float ber); virtual void clearDMRInt(unsigned int slotNo) = 0; virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) = 0; virtual void writeFusionRSSIInt(unsigned char rssi); + virtual void writeFusionBERInt(float ber); virtual void clearFusionInt() = 0; virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type) = 0; virtual void writeP25RSSIInt(unsigned char rssi); + virtual void writeP25BERInt(float ber); virtual void clearP25Int() = 0; virtual void writeCWInt() = 0; diff --git a/Modem.cpp b/Modem.cpp index 4fab28d..2c0fe9b 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -465,7 +465,19 @@ void CModem::clock(unsigned int ms) LogWarning("Received a NAK from the MMDVM, command = 0x%02X, reason = %u", m_buffer[3U], m_buffer[4U]); break; - default: + case MMDVM_DEBUG1: + case MMDVM_DEBUG2: + case MMDVM_DEBUG3: + case MMDVM_DEBUG4: + case MMDVM_DEBUG5: + printDebug(); + break; + + case MMDVM_SAMPLES: + printSamples(); + break; + + default: LogMessage("Unknown message, type: %02X", m_buffer[2U]); CUtils::dump("Buffer dump", m_buffer, m_length); break; @@ -1112,39 +1124,6 @@ RESP_TYPE_MMDVM CModem::getResponse() if (ret == 0) return RTM_TIMEOUT; - switch (m_buffer[2U]) { - case MMDVM_DSTAR_HEADER: - case MMDVM_DSTAR_DATA: - case MMDVM_DSTAR_LOST: - case MMDVM_DSTAR_EOT: - case MMDVM_DMR_DATA1: - case MMDVM_DMR_DATA2: - case MMDVM_DMR_LOST1: - case MMDVM_DMR_LOST2: - case MMDVM_YSF_DATA: - case MMDVM_YSF_LOST: - case MMDVM_P25_HDR: - case MMDVM_P25_LDU: - case MMDVM_P25_LOST: - case MMDVM_GET_STATUS: - case MMDVM_GET_VERSION: - case MMDVM_ACK: - case MMDVM_NAK: - case MMDVM_SERIAL: - case MMDVM_SAMPLES: - case MMDVM_DEBUG1: - case MMDVM_DEBUG2: - case MMDVM_DEBUG3: - case MMDVM_DEBUG4: - case MMDVM_DEBUG5: - break; - - default: - LogError("Unknown message, type: %02X", m_buffer[2U]); - m_offset = 0U; - return RTM_ERROR; - } - m_offset = 3U; } @@ -1167,23 +1146,9 @@ RESP_TYPE_MMDVM CModem::getResponse() m_offset = 0U; - switch (m_buffer[2U]) { - case MMDVM_DEBUG1: - case MMDVM_DEBUG2: - case MMDVM_DEBUG3: - case MMDVM_DEBUG4: - case MMDVM_DEBUG5: - printDebug(); - return RTM_TIMEOUT; + // CUtils::dump(1U, "Received", m_buffer, m_length); - case MMDVM_SAMPLES: - printSamples(); - return RTM_TIMEOUT; - - default: - // CUtils::dump(1U, "Received", m_buffer, m_length); - return RTM_OK; - } + return RTM_OK; } HW_TYPE CModem::getHWType() const diff --git a/Nextion.cpp b/Nextion.cpp index a0635a5..f434c57 100644 --- a/Nextion.cpp +++ b/Nextion.cpp @@ -25,10 +25,14 @@ #include #include -const unsigned int DSTAR_RSSI_COUNT = 3U; // 3 * 420ms = 1260ms -const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms +const unsigned int DSTAR_RSSI_COUNT = 3U; // 3 * 420ms = 1260ms +const unsigned int DSTAR_BER_COUNT = 63U; // 63 * 20ms = 1260ms +const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms +const unsigned int DMR_BER_COUNT = 24U; // 24 * 60ms = 1440ms const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms -const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms +const unsigned int YSF_BER_COUNT = 13U; // 13 * 100ms = 1300ms +const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms +const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness) : CDisplay(), @@ -41,8 +45,14 @@ m_displayClock(displayClock), m_utc(utc), m_idleBrightness(idleBrightness), m_clockDisplayTimer(1000U, 0U, 400U), -m_rssiCount1(0U), -m_rssiCount2(0U) +m_rssiAccum1(0U), +m_rssiAccum2(0U), +m_berAccum1(0.0F), +m_berAccum2(0.0F), +m_rssiCount1(1U), +m_rssiCount2(1U), +m_berCount1(1U), +m_berCount2(1U) { assert(serial != NULL); assert(brightness >= 0U && brightness <= 100U); @@ -129,8 +139,8 @@ void CNextion::writeDStarInt(const char* my1, const char* my2, const char* your, assert(type != NULL); assert(reflector != NULL); - if (m_mode != MODE_DSTAR) - sendCommand("page DStar"); + if (m_mode != MODE_DSTAR) + sendCommand("page DStar"); char text[30U]; ::sprintf(text, "dim=%u", m_brightness); @@ -150,20 +160,38 @@ void CNextion::writeDStarInt(const char* my1, const char* my2, const char* your, m_clockDisplayTimer.stop(); m_mode = MODE_DSTAR; - m_rssiCount1 = 0U; + m_rssiAccum1 = 0U; + m_berAccum1 = 0.0F; + m_rssiCount1 = 1U; + m_berCount1 = 1U; } void CNextion::writeDStarRSSIInt(unsigned char rssi) { - if (m_rssiCount1 == 0U) { - char text[20U]; - ::sprintf(text, "t3.txt=\"-%udBm\"", rssi); - sendCommand(text); - } - + m_rssiAccum1 += rssi; m_rssiCount1++; - if (m_rssiCount1 >= DSTAR_RSSI_COUNT) - m_rssiCount1 = 0U; + + if (m_rssiCount1 == DSTAR_RSSI_COUNT) { + char text[20U]; + ::sprintf(text, "t3.txt=\"-%udBm\"", m_rssiAccum1 / DSTAR_RSSI_COUNT); + sendCommand(text); + m_rssiAccum1 = 0U; + m_rssiCount1 = 1U; + } +} + +void CNextion::writeDStarBERInt(float ber) +{ + m_berAccum1 += ber; + m_berCount1++; + + if (m_berCount1 == DSTAR_BER_COUNT) { + char text[20U]; + ::sprintf(text, "t4.txt=\"%.1f%%\"", m_berAccum1 / float(DSTAR_BER_COUNT)); + sendCommand(text); + m_berAccum1 = 0.0F; + m_berCount1 = 1U; + } } void CNextion::clearDStarInt() @@ -172,6 +200,7 @@ void CNextion::clearDStarInt() sendCommand("t1.txt=\"\""); sendCommand("t2.txt=\"\""); sendCommand("t3.txt=\"\""); + sendCommand("t4.txt=\"\""); } void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) @@ -208,32 +237,67 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro m_clockDisplayTimer.stop(); m_mode = MODE_DMR; - m_rssiCount1 = 0U; - m_rssiCount2 = 0U; + m_rssiAccum1 = 0U; + m_rssiAccum2 = 0U; + m_berAccum1 = 0.0F; + m_berAccum2 = 0.0F; + m_rssiCount1 = 1U; + m_rssiCount2 = 1U; + m_berCount1 = 1U; + m_berCount2 = 1U; } void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) { if (slotNo == 1U) { - if (m_rssiCount1 == 0U) { - char text[20U]; - ::sprintf(text, "t4.txt=\"-%udBm\"", rssi); - sendCommand(text); - } - + m_rssiAccum1 += rssi; m_rssiCount1++; - if (m_rssiCount1 >= DMR_RSSI_COUNT) - m_rssiCount1 = 0U; - } else { - if (m_rssiCount2 == 0U) { + + if (m_rssiCount1 == DMR_RSSI_COUNT) { char text[20U]; - ::sprintf(text, "t5.txt=\"-%udBm\"", rssi); + ::sprintf(text, "t4.txt=\"-%udBm\"", m_rssiAccum1 / DMR_RSSI_COUNT); sendCommand(text); + m_rssiAccum1 = 0U; + m_rssiCount1 = 1U; } - + } else { + m_rssiAccum2 += rssi; m_rssiCount2++; - if (m_rssiCount2 >= DMR_RSSI_COUNT) - m_rssiCount2 = 0U; + + if (m_rssiCount2 == DMR_RSSI_COUNT) { + char text[20U]; + ::sprintf(text, "t5.txt=\"-%udBm\"", m_rssiAccum2 / DMR_RSSI_COUNT); + sendCommand(text); + m_rssiAccum2 = 0U; + m_rssiCount2 = 1U; + } + } +} + +void CNextion::writeDMRBERInt(unsigned int slotNo, float ber) +{ + if (slotNo == 1U) { + m_berAccum1 += ber; + m_berCount1++; + + if (m_berCount1 == DMR_BER_COUNT) { + char text[20U]; + ::sprintf(text, "t6.txt=\"%.1f%%\"", m_berAccum1 / DMR_BER_COUNT); + sendCommand(text); + m_berAccum1 = 0U; + m_berCount1 = 1U; + } + } else { + m_berAccum2 += ber; + m_berCount2++; + + if (m_berCount2 == DMR_BER_COUNT) { + char text[20U]; + ::sprintf(text, "t7.txt=\"%.1f%%\"", m_berAccum2 / DMR_BER_COUNT); + sendCommand(text); + m_berAccum2 = 0U; + m_berCount2 = 1U; + } } } @@ -243,11 +307,13 @@ void CNextion::clearDMRInt(unsigned int slotNo) sendCommand("t0.txt=\"1 Listening\""); sendCommand("t1.txt=\"\""); sendCommand("t4.txt=\"\""); - } else { + sendCommand("t6.txt=\"\""); + } else { sendCommand("t2.txt=\"2 Listening\""); sendCommand("t3.txt=\"\""); sendCommand("t5.txt=\"\""); - } + sendCommand("t7.txt=\"\""); + } } void CNextion::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) @@ -277,20 +343,38 @@ void CNextion::writeFusionInt(const char* source, const char* dest, const char* m_clockDisplayTimer.stop(); m_mode = MODE_YSF; - m_rssiCount1 = 0U; + m_rssiAccum1 = 0U; + m_berAccum1 = 0.0F; + m_rssiCount1 = 1U; + m_berCount1 = 1U; } void CNextion::writeFusionRSSIInt(unsigned char rssi) { - if (m_rssiCount1 == 0U) { - char text[20U]; - ::sprintf(text, "t3.txt=\"-%udBm\"", rssi); - sendCommand(text); - } - + m_rssiAccum1 += rssi; m_rssiCount1++; - if (m_rssiCount1 >= YSF_RSSI_COUNT) - m_rssiCount1 = 0U; + + if (m_rssiCount1 == YSF_RSSI_COUNT) { + char text[20U]; + ::sprintf(text, "t3.txt=\"-%udBm\"", m_rssiAccum1 / YSF_RSSI_COUNT); + sendCommand(text); + m_rssiAccum1 = 0U; + m_rssiCount1 = 1U; + } +} + +void CNextion::writeFusionBERInt(float ber) +{ + m_berAccum1 += ber; + m_berCount1++; + + if (m_berCount1 == YSF_BER_COUNT) { + char text[20U]; + ::sprintf(text, "t4.txt=\"%.1f%%\"", m_berAccum1 / float(YSF_BER_COUNT)); + sendCommand(text); + m_berAccum1 = 0.0F; + m_berCount1 = 1U; + } } void CNextion::clearFusionInt() @@ -299,6 +383,7 @@ void CNextion::clearFusionInt() sendCommand("t1.txt=\"\""); sendCommand("t2.txt=\"\""); sendCommand("t3.txt=\"\""); + sendCommand("t4.txt=\"\""); } void CNextion::writeP25Int(const char* source, bool group, unsigned int dest, const char* type) @@ -322,20 +407,38 @@ void CNextion::writeP25Int(const char* source, bool group, unsigned int dest, co m_clockDisplayTimer.stop(); m_mode = MODE_P25; - m_rssiCount1 = 0U; + m_rssiAccum1 = 0U; + m_berAccum1 = 0.0F; + m_rssiCount1 = 1U; + m_berCount1 = 1U; } void CNextion::writeP25RSSIInt(unsigned char rssi) { - if (m_rssiCount1 == 0U) { - char text[20U]; - ::sprintf(text, "t2.txt=\"-%udBm\"", rssi); - sendCommand(text); - } - + m_rssiAccum1 += rssi; m_rssiCount1++; - if (m_rssiCount1 >= P25_RSSI_COUNT) - m_rssiCount1 = 0U; + + if (m_rssiCount1 == P25_RSSI_COUNT) { + char text[20U]; + ::sprintf(text, "t2.txt=\"-%udBm\"", m_rssiAccum1 / P25_RSSI_COUNT); + sendCommand(text); + m_rssiAccum1 = 0U; + m_rssiCount1 = 1U; + } +} + +void CNextion::writeP25BERInt(float ber) +{ + m_berAccum1 += ber; + m_berCount1++; + + if (m_berCount1 == P25_BER_COUNT) { + char text[20U]; + ::sprintf(text, "t3.txt=\"%.1f%%\"", m_berAccum1 / float(P25_BER_COUNT)); + sendCommand(text); + m_berAccum1 = 0.0F; + m_berCount1 = 1U; + } } void CNextion::clearP25Int() @@ -343,6 +446,7 @@ void CNextion::clearP25Int() sendCommand("t0.txt=\"Listening\""); sendCommand("t1.txt=\"\""); sendCommand("t2.txt=\"\""); + sendCommand("t3.txt=\"\""); } void CNextion::writeCWInt() diff --git a/Nextion.h b/Nextion.h index e1b8242..c5a931b 100644 --- a/Nextion.h +++ b/Nextion.h @@ -43,18 +43,22 @@ protected: virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); virtual void writeDStarRSSIInt(unsigned char rssi); + virtual void writeDStarBERInt(float ber); virtual void clearDStarInt(); virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi); + virtual void writeDMRBERInt(unsigned int slotNo, float ber); virtual void clearDMRInt(unsigned int slotNo); virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin); virtual void writeFusionRSSIInt(unsigned char rssi); + virtual void writeFusionBERInt(float ber); virtual void clearFusionInt(); virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type); virtual void writeP25RSSIInt(unsigned char rssi); + virtual void writeP25BERInt(float ber); virtual void clearP25Int(); virtual void writeCWInt(); @@ -72,8 +76,14 @@ private: bool m_utc; unsigned int m_idleBrightness; CTimer m_clockDisplayTimer; + unsigned int m_rssiAccum1; + unsigned int m_rssiAccum2; + float m_berAccum1; + float m_berAccum2; unsigned int m_rssiCount1; unsigned int m_rssiCount2; + unsigned int m_berCount1; + unsigned int m_berCount2; void sendCommand(const char* command); }; diff --git a/Nextion/NX3224T024.HMI b/Nextion/NX3224T024.HMI index 49cb092..9caff59 100644 Binary files a/Nextion/NX3224T024.HMI and b/Nextion/NX3224T024.HMI differ diff --git a/Nextion/NX3224T024.tft b/Nextion/NX3224T024.tft index 4e105af..0516005 100644 Binary files a/Nextion/NX3224T024.tft and b/Nextion/NX3224T024.tft differ diff --git a/P25Control.cpp b/P25Control.cpp index 26b139e..b457534 100644 --- a/P25Control.cpp +++ b/P25Control.cpp @@ -207,7 +207,9 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) // Regenerate Audio unsigned int errors = m_audio.process(data + 2U); - LogDebug("P25, LDU1 audio, errs: %u/1233", errors); + LogDebug("P25, LDU1 audio, errs: %u/1233 (%.1f%%)", errors, float(errors) / 12.33F); + + m_display->writeP25BER(float(errors) / 12.33F); m_rfBits += 1233U; m_rfErrs += errors; @@ -260,7 +262,9 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) // Regenerate Audio unsigned int errors = m_audio.process(data + 2U); - LogDebug("P25, LDU2 audio, errs: %u/1233", errors); + LogDebug("P25, LDU2 audio, errs: %u/1233 (%.1f%%)", errors, float(errors) / 12.33F); + + m_display->writeP25BER(float(errors) / 12.33F); m_rfBits += 1233U; m_rfErrs += errors; diff --git a/YSFControl.cpp b/YSFControl.cpp index 92fc796..233d284 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -273,6 +273,7 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) unsigned int errors = m_rfPayload.processVDMode1Audio(data + 2U); m_rfErrs += errors; m_rfBits += 235U; + m_display->writeFusionBER(float(errors) / 2.35F); LogDebug("YSF, V/D Mode 1, seq %u, AMBE FEC %u/235 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 2.35F); } break; @@ -282,6 +283,7 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) unsigned int errors = m_rfPayload.processVDMode2Audio(data + 2U); m_rfErrs += errors; m_rfBits += 135U; + m_display->writeFusionBER(float(errors) / 1.35F); LogDebug("YSF, V/D Mode 2, seq %u, Repetition FEC %u/135 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 1.35F); } break; @@ -297,6 +299,7 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) unsigned int errors = m_rfPayload.processVoiceFRModeAudio(data + 2U); m_rfErrs += errors; m_rfBits += 720U; + m_display->writeFusionBER(float(errors) / 7.2F); LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 7.2F); } valid = false; @@ -542,7 +545,6 @@ void CYSFControl::writeNetwork() // if (send) { m_netErrs += errors; m_netBits += 235U; - LogDebug("YSF, V/D Mode 1, seq %u, AMBE FEC %u/235 (%.1f%%)", n, errors, float(errors) / 2.35F); // } } break; @@ -554,13 +556,11 @@ void CYSFControl::writeNetwork() // if (send) { m_netErrs += errors; m_netBits += 135U; - LogDebug("YSF, V/D Mode 2, seq %u, Repetition FEC %u/135 (%.1f%%)", n, errors, float(errors) / 1.35F); // } } break; case YSF_DT_DATA_FR_MODE: - LogDebug("YSF, Network data FICH B=%u/%u F=%u/%u", bn, bt, fn, ft); m_netPayload.processDataFRModeData(data + 35U, fn, gateway); break; @@ -572,7 +572,6 @@ void CYSFControl::writeNetwork() // if (send) { m_netErrs += errors; m_netBits += 720U; - LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", n, errors, float(errors) / 7.2F); // } } break;