From cb6929bdc13246ad2ac123a47cda902a4ba755c7 Mon Sep 17 00:00:00 2001 From: acidburns Date: Wed, 4 Feb 2026 14:42:44 +0100 Subject: [PATCH] Add detailed sender ACK RX diagnostics with reject context --- include/lora_transport.h | 1 + src/lora_transport.cpp | 20 ++++++++++++++++++-- src/main.cpp | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/include/lora_transport.h b/include/lora_transport.h index af02ba5..1d11c2e 100644 --- a/include/lora_transport.h +++ b/include/lora_transport.h @@ -32,6 +32,7 @@ void lora_init(); bool lora_send(const LoraPacket &pkt); bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms); RxRejectReason lora_get_last_rx_reject_reason(); +bool lora_get_last_rx_signal(int16_t &rssi_dbm, float &snr_db); void lora_idle(); void lora_sleep(); void lora_receive_continuous(); diff --git a/src/lora_transport.cpp b/src/lora_transport.cpp index db5a7e6..34562ab 100644 --- a/src/lora_transport.cpp +++ b/src/lora_transport.cpp @@ -5,6 +5,9 @@ static RxRejectReason g_last_rx_reject_reason = RxRejectReason::None; static uint32_t g_last_rx_reject_log_ms = 0; +static bool g_last_rx_signal_valid = false; +static int16_t g_last_rx_rssi_dbm = 0; +static float g_last_rx_snr_db = 0.0f; static void note_reject(RxRejectReason reason) { g_last_rx_reject_reason = reason; @@ -23,6 +26,15 @@ RxRejectReason lora_get_last_rx_reject_reason() { return reason; } +bool lora_get_last_rx_signal(int16_t &rssi_dbm, float &snr_db) { + if (!g_last_rx_signal_valid) { + return false; + } + rssi_dbm = g_last_rx_rssi_dbm; + snr_db = g_last_rx_snr_db; + return true; +} + static uint16_t crc16_ccitt(const uint8_t *data, size_t len) { uint16_t crc = 0xFFFF; for (size_t i = 0; i < len; ++i) { @@ -109,6 +121,10 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) { while (true) { int packet_size = LoRa.parsePacket(); if (packet_size > 0) { + g_last_rx_rssi_dbm = static_cast(LoRa.packetRssi()); + g_last_rx_snr_db = LoRa.packetSnr(); + g_last_rx_signal_valid = true; + if (packet_size < 5) { while (LoRa.available()) { LoRa.read(); @@ -148,8 +164,8 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) { return false; } memcpy(pkt.payload, &buffer[3], pkt.payload_len); - pkt.rssi_dbm = static_cast(LoRa.packetRssi()); - pkt.snr_db = LoRa.packetSnr(); + pkt.rssi_dbm = g_last_rx_rssi_dbm; + pkt.snr_db = g_last_rx_snr_db; return true; } diff --git a/src/main.cpp b/src/main.cpp index 8261f1c..b65dd26 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -871,11 +871,40 @@ static void sender_loop() { g_sender_rx_window_ms += rx_elapsed; } if (!got_ack) { - sender_note_rx_reject(lora_get_last_rx_reject_reason(), "ack"); + RxRejectReason reason = lora_get_last_rx_reject_reason(); + sender_note_rx_reject(reason, "ack"); + if (SERIAL_DEBUG_MODE) { + int16_t rssi_dbm = 0; + float snr_db = 0.0f; + bool has_signal = lora_get_last_rx_signal(rssi_dbm, snr_db); + const char *reason_text = reason == RxRejectReason::None ? "timeout" : rx_reject_reason_text(reason); + if (has_signal) { + serial_debug_printf("ack: rx miss reason=%s rssi=%d snr=%.1f", + reason_text, + static_cast(rssi_dbm), + static_cast(snr_db)); + } else { + serial_debug_printf("ack: rx miss reason=%s", reason_text); + } + } } else if (ack_pkt.msg_kind != LoraMsgKind::AckDown) { sender_note_rx_reject(RxRejectReason::InvalidMsgKind, "ack"); + if (SERIAL_DEBUG_MODE) { + uint16_t ack_id = ack_pkt.payload_len >= 3 ? read_u16_be(&ack_pkt.payload[1]) : 0; + serial_debug_printf("ack: reject msg_kind=%u payload_len=%u ack_id=%u", + static_cast(ack_pkt.msg_kind), + static_cast(ack_pkt.payload_len), + ack_id); + } } else if (ack_pkt.payload_len < LORA_ACK_DOWN_PAYLOAD_LEN) { sender_note_rx_reject(RxRejectReason::LengthMismatch, "ack"); + if (SERIAL_DEBUG_MODE) { + uint16_t ack_id = ack_pkt.payload_len >= 3 ? read_u16_be(&ack_pkt.payload[1]) : 0; + serial_debug_printf("ack: reject msg_kind=%u payload_len=%u ack_id=%u", + static_cast(ack_pkt.msg_kind), + static_cast(ack_pkt.payload_len), + ack_id); + } } else { uint8_t time_valid = ack_pkt.payload[0] & 0x01; uint16_t ack_id = read_u16_be(&ack_pkt.payload[1]); @@ -897,6 +926,12 @@ static void sender_loop() { } else { if (ack_id != g_last_sent_batch_id) { sender_note_rx_reject(RxRejectReason::BatchIdMismatch, "ack"); + if (SERIAL_DEBUG_MODE) { + serial_debug_printf("ack: reject msg_kind=%u payload_len=%u ack_id=%u", + static_cast(ack_pkt.msg_kind), + static_cast(ack_pkt.payload_len), + ack_id); + } } } }