From 17aa33cdac19b7f85aba66c47afcb9d95bcca22e Mon Sep 17 00:00:00 2001 From: mmmorks Date: Tue, 8 Sep 2026 00:10:52 -0700 Subject: [PATCH] Log packet length, RSSI and SNR when readData() fails recvRaw()'s readData() error line prints only the error code, which says nothing about the cause: a packet at the edge of the demodulator and one lost to a collision both produce -7 (CRC mismatch). Both existing packet loggers sit inside the success branch, so a failed receive is invisible to `log start` and MESH_PACKET_LOGGING alike. The modem's packet-status registers are written whether or not the CRC passed, so reading them here costs no extra SPI traffic and reports the same values a successful receive would. SNR is scaled by 4 rather than truncated, because the threshold this is meant to resolve is a fraction of a dB wide and %f is not portable across every platform this file builds for -- the same quarter-dB convention as Packet::_snr. Measured on a live repeater at SF7/62.5 kHz (490 failures against 961 successes over 25 min), the failure rate resolves into a clean waterfall against SNR, with 20% of failures at positive SNR where marginality cannot be the explanation. Debug output only: the line is inside MESH_DEBUG_PRINTLN and costs nothing on a build without MESH_DEBUG. --- src/helpers/radiolib/RadioLibWrappers.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index e4d2ba1c27..94c149eb4a 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -133,7 +133,21 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) { if (len > sz) { len = sz; } int err = _radio->readData(bytes, len); if (err != RADIOLIB_ERR_NONE) { - MESH_DEBUG_PRINTLN("RadioLibWrapper: error: readData(%d)", err); + // Signal quality of the packet that just failed. A CRC mismatch (-7) is + // the common case and says nothing on its own about *why*: a packet at + // the edge of the demodulator and one lost to a collision both land + // here. The modem's packet-status registers are written whether or not + // the CRC passed, so this reads the same values a successful receive + // would report, at no extra SPI cost -- enough to tell a failure + // distribution sitting on the SF's SNR floor apart from one spread + // across strong signals. + // + // SNR is scaled by 4 rather than truncated because the threshold this + // is meant to resolve is a fraction of a dB wide, and %f is not + // portable across every platform this file builds for. Same quarter-dB + // convention as Packet::_snr. + MESH_DEBUG_PRINTLN("RadioLibWrapper: error: readData(%d) len=%d rssi=%d snr4=%d", + err, len, (int)getLastRSSI(), (int)(getLastSNR() * 4)); len = 0; n_recv_errors++; } else {