diff --git a/Config.h b/Config.h index b1affe3..aef43a2 100644 --- a/Config.h +++ b/Config.h @@ -289,17 +289,24 @@ // MCU independent configuration parameters const long serial_baudrate = 115200; - const int lora_rx_turnaround_ms = 50; - uint8_t csma_p = 0; - float csma_p_min = 0.1; - float csma_p_max = 0.8; - int csma_slot_ms = lora_rx_turnaround_ms; // SX1276 RSSI offset to get dBm value from // packet RSSI register const int rssi_offset = 157; // Default LoRa settings + const int lora_rx_turnaround_ms = 66; + const int lora_post_tx_yield_slots = 6; + uint32_t post_tx_yield_timeout = 0; + #define LORA_PREAMBLE_SYMBOLS_HW 4 + #define LORA_PREAMBLE_SYMBOLS_MIN 6 + #define LORA_PREAMBLE_TARGET_MS 15 + #define LORA_CAD_SYMBOLS 3 + int csma_slot_ms = 50; + float csma_p_min = 0.1; + float csma_p_max = 0.8; + uint8_t csma_p = 0; + int lora_sf = 0; int lora_cr = 5; int lora_txp = 0xFF; @@ -370,18 +377,19 @@ float lt_airtime_limit = 0.0; bool airtime_lock = false; - bool stat_signal_detected = false; - bool stat_signal_synced = false; - bool stat_rx_ongoing = false; - bool dcd = false; - bool dcd_led = false; - bool dcd_waiting = false; - long dcd_wait_until = 0; - uint16_t dcd_count = 0; - uint16_t dcd_threshold = 6; + bool stat_signal_detected = false; + bool stat_signal_synced = false; + bool stat_rx_ongoing = false; + bool dcd = false; + bool dcd_led = false; + bool dcd_waiting = false; + long dcd_wait_until = 0; + uint16_t dcd_count = 0; + uint16_t dcd_threshold = 2; uint32_t status_interval_ms = STATUS_INTERVAL_MS; uint32_t last_status_update = 0; + uint32_t last_dcd = 0; // Status flags const uint8_t SIG_DETECT = 0x01; diff --git a/Framing.h b/Framing.h index 79811b4..97dce7c 100644 --- a/Framing.h +++ b/Framing.h @@ -43,6 +43,7 @@ #define CMD_STAT_RSSI 0x23 #define CMD_STAT_SNR 0x24 #define CMD_STAT_CHTM 0x25 + #define CMD_STAT_PHYPRM 0x26 #define CMD_BLINK 0x30 #define CMD_RANDOM 0x40 diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 07a5cea..e5852ea 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -318,7 +318,6 @@ bool startRadio() { setBandwidth(); setSpreadingFactor(); setCodingRate(); - setPreamble(); getFrequency(); LoRa.enableCrc(); @@ -398,6 +397,7 @@ void flushQueue(void) { lora_receive(); led_tx_off(); + post_tx_yield_timeout = millis()+(lora_post_tx_yield_slots*csma_slot_ms); } queue_height = 0; @@ -925,20 +925,30 @@ void updateModemStatus() { if (status & RX_ONGOING == RX_ONGOING) { stat_rx_ongoing = true; } else { stat_rx_ongoing = false; } if (stat_signal_detected || stat_signal_synced || stat_rx_ongoing) { - if (dcd_count < dcd_threshold) { - dcd_count++; - dcd = true; - } else { - dcd = true; - dcd_led = true; + if (stat_rx_ongoing) { + if (dcd_count < dcd_threshold) { + dcd_count++; + } else { + last_dcd = last_status_update; + dcd_led = true; + dcd = true; + } } } else { - if (dcd_count > 0) { - dcd_count = 0; - } else { + #define DCD_LED_STEP_D 3 + if (dcd_count == 0) { dcd_led = false; + } else if (dcd_count > DCD_LED_STEP_D) { + dcd_count -= DCD_LED_STEP_D; + } else { + dcd_count = 0; + } + + if (last_status_update > last_dcd+csma_slot_ms) { + dcd = false; + dcd_led = false; + dcd_count = 0; } - dcd = false; } if (dcd_led) { @@ -1110,8 +1120,6 @@ void validate_status() { void loop() { if (radio_online) { - checkModemStatus(); - #if MCU_VARIANT == MCU_ESP32 if (packet_ready) { portENTER_CRITICAL(&update_lock); @@ -1128,22 +1136,26 @@ void loop() { if (lt_airtime_limit != 0.0 && longterm_airtime >= lt_airtime_limit) airtime_lock = true; #endif + checkModemStatus(); if (!airtime_lock) { if (queue_height > 0) { #if MCU_VARIANT == MCU_ESP32 + long check_time = millis(); + if (check_time > post_tx_yield_timeout) { + if (dcd_waiting && (check_time >= dcd_wait_until)) { dcd_waiting = false; } + if (!dcd_waiting) { + for (uint8_t dcd_i = 0; dcd_i < dcd_threshold*2; dcd_i++) { + delay(STATUS_INTERVAL_MS); updateModemStatus(); + } - if (dcd_waiting && (millis() >= dcd_wait_until)) { dcd_waiting = false; } - if (!dcd_waiting) { - updateModemStatus(); - long check_time = millis(); - - if (!dcd) { - uint8_t csma_r = (uint8_t)random(256); - if (csma_p >= csma_r) { - flushQueue(); - } else { - dcd_waiting = true; - dcd_wait_until = check_time+csma_slot_ms; + if (!dcd) { + uint8_t csma_r = (uint8_t)random(256); + if (csma_p >= csma_r) { + flushQueue(); + } else { + dcd_waiting = true; + dcd_wait_until = millis()+csma_slot_ms; + } } } } diff --git a/Utilities.h b/Utilities.h index 3c71618..97697b2 100644 --- a/Utilities.h +++ b/Utilities.h @@ -732,6 +732,29 @@ void kiss_indicate_channel_stats() { #endif } +void kiss_indicate_phy_stats() { + #if MCU_VARIANT == MCU_ESP32 + uint16_t lst = (uint16_t)(lora_symbol_time_ms*1000); + uint16_t lsr = (uint16_t)(lora_symbol_rate); + uint16_t prs = (uint16_t)(lora_preamble_symbols+4); + uint16_t prt = (uint16_t)((lora_preamble_symbols+4)*lora_symbol_time_ms); + uint16_t cst = (uint16_t)(csma_slot_ms); + serial_write(FEND); + serial_write(CMD_STAT_PHYPRM); + escaped_serial_write(lst>>8); + escaped_serial_write(lst); + escaped_serial_write(lsr>>8); + escaped_serial_write(lsr); + escaped_serial_write(prs>>8); + escaped_serial_write(prs); + escaped_serial_write(prt>>8); + escaped_serial_write(prt); + escaped_serial_write(cst>>8); + escaped_serial_write(cst); + serial_write(FEND); + #endif +} + void kiss_indicate_btpin() { #if HAS_BLUETOOTH serial_write(FEND); @@ -905,6 +928,11 @@ inline uint8_t packetSequence(uint8_t header) { return header >> 4; } +void setPreamble() { + if (radio_online) LoRa.setPreambleLength(lora_preamble_symbols); + kiss_indicate_phy_stats(); +} + void updateBitrate() { #if MCU_VARIANT == MCU_ESP32 if (radio_online) { @@ -912,7 +940,15 @@ void updateBitrate() { lora_symbol_time_ms = (1.0/lora_symbol_rate)*1000.0; lora_bitrate = (uint32_t)(lora_sf * ( (4.0/(float)lora_cr) / ((float)(pow(2, lora_sf))/((float)lora_bw/1000.0)) ) * 1000.0); lora_us_per_byte = 1000000.0/((float)lora_bitrate/8.0); - csma_slot_ms = lora_symbol_time_ms*10; + // csma_slot_ms = lora_symbol_time_ms*10; + float target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW; + if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) { + target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN; + } else { + target_preamble_symbols = ceil(target_preamble_symbols); + } + lora_preamble_symbols = (long)target_preamble_symbols; + setPreamble(); } else { lora_bitrate = 0; } @@ -929,11 +965,6 @@ void setCodingRate() { updateBitrate(); } -void setPreamble() { - if (radio_online) LoRa.setPreambleLength(lora_preamble_symbols); - updateBitrate(); -} - void set_implicit_length(uint8_t len) { implicit_l = len; if (implicit_l != 0) {