Add detailed sender ACK RX diagnostics with reject context
This commit is contained in:
@@ -32,6 +32,7 @@ void lora_init();
|
|||||||
bool lora_send(const LoraPacket &pkt);
|
bool lora_send(const LoraPacket &pkt);
|
||||||
bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms);
|
bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms);
|
||||||
RxRejectReason lora_get_last_rx_reject_reason();
|
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_idle();
|
||||||
void lora_sleep();
|
void lora_sleep();
|
||||||
void lora_receive_continuous();
|
void lora_receive_continuous();
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
static RxRejectReason g_last_rx_reject_reason = RxRejectReason::None;
|
static RxRejectReason g_last_rx_reject_reason = RxRejectReason::None;
|
||||||
static uint32_t g_last_rx_reject_log_ms = 0;
|
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) {
|
static void note_reject(RxRejectReason reason) {
|
||||||
g_last_rx_reject_reason = reason;
|
g_last_rx_reject_reason = reason;
|
||||||
@@ -23,6 +26,15 @@ RxRejectReason lora_get_last_rx_reject_reason() {
|
|||||||
return 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) {
|
static uint16_t crc16_ccitt(const uint8_t *data, size_t len) {
|
||||||
uint16_t crc = 0xFFFF;
|
uint16_t crc = 0xFFFF;
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
@@ -109,6 +121,10 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) {
|
|||||||
while (true) {
|
while (true) {
|
||||||
int packet_size = LoRa.parsePacket();
|
int packet_size = LoRa.parsePacket();
|
||||||
if (packet_size > 0) {
|
if (packet_size > 0) {
|
||||||
|
g_last_rx_rssi_dbm = static_cast<int16_t>(LoRa.packetRssi());
|
||||||
|
g_last_rx_snr_db = LoRa.packetSnr();
|
||||||
|
g_last_rx_signal_valid = true;
|
||||||
|
|
||||||
if (packet_size < 5) {
|
if (packet_size < 5) {
|
||||||
while (LoRa.available()) {
|
while (LoRa.available()) {
|
||||||
LoRa.read();
|
LoRa.read();
|
||||||
@@ -148,8 +164,8 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(pkt.payload, &buffer[3], pkt.payload_len);
|
memcpy(pkt.payload, &buffer[3], pkt.payload_len);
|
||||||
pkt.rssi_dbm = static_cast<int16_t>(LoRa.packetRssi());
|
pkt.rssi_dbm = g_last_rx_rssi_dbm;
|
||||||
pkt.snr_db = LoRa.packetSnr();
|
pkt.snr_db = g_last_rx_snr_db;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
src/main.cpp
37
src/main.cpp
@@ -871,11 +871,40 @@ static void sender_loop() {
|
|||||||
g_sender_rx_window_ms += rx_elapsed;
|
g_sender_rx_window_ms += rx_elapsed;
|
||||||
}
|
}
|
||||||
if (!got_ack) {
|
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<int>(rssi_dbm),
|
||||||
|
static_cast<double>(snr_db));
|
||||||
|
} else {
|
||||||
|
serial_debug_printf("ack: rx miss reason=%s", reason_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (ack_pkt.msg_kind != LoraMsgKind::AckDown) {
|
} else if (ack_pkt.msg_kind != LoraMsgKind::AckDown) {
|
||||||
sender_note_rx_reject(RxRejectReason::InvalidMsgKind, "ack");
|
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<unsigned>(ack_pkt.msg_kind),
|
||||||
|
static_cast<unsigned>(ack_pkt.payload_len),
|
||||||
|
ack_id);
|
||||||
|
}
|
||||||
} else if (ack_pkt.payload_len < LORA_ACK_DOWN_PAYLOAD_LEN) {
|
} else if (ack_pkt.payload_len < LORA_ACK_DOWN_PAYLOAD_LEN) {
|
||||||
sender_note_rx_reject(RxRejectReason::LengthMismatch, "ack");
|
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<unsigned>(ack_pkt.msg_kind),
|
||||||
|
static_cast<unsigned>(ack_pkt.payload_len),
|
||||||
|
ack_id);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uint8_t time_valid = ack_pkt.payload[0] & 0x01;
|
uint8_t time_valid = ack_pkt.payload[0] & 0x01;
|
||||||
uint16_t ack_id = read_u16_be(&ack_pkt.payload[1]);
|
uint16_t ack_id = read_u16_be(&ack_pkt.payload[1]);
|
||||||
@@ -897,6 +926,12 @@ static void sender_loop() {
|
|||||||
} else {
|
} else {
|
||||||
if (ack_id != g_last_sent_batch_id) {
|
if (ack_id != g_last_sent_batch_id) {
|
||||||
sender_note_rx_reject(RxRejectReason::BatchIdMismatch, "ack");
|
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<unsigned>(ack_pkt.msg_kind),
|
||||||
|
static_cast<unsigned>(ack_pkt.payload_len),
|
||||||
|
ack_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user