// 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;
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;
#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
setBandwidth();
setSpreadingFactor();
setCodingRate();
- setPreamble();
getFrequency();
LoRa.enableCrc();
lora_receive();
led_tx_off();
+ post_tx_yield_timeout = millis()+(lora_post_tx_yield_slots*csma_slot_ms);
}
queue_height = 0;
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;
+ #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) {
void loop() {
if (radio_online) {
- checkModemStatus();
-
#if MCU_VARIANT == MCU_ESP32
if (packet_ready) {
portENTER_CRITICAL(&update_lock);
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;
+ }
}
}
}
#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);
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) {
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;
}
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) {