mirror of
https://github.com/markqvist/RNode_Firmware.git
synced 2025-05-05 08:05:18 -04:00
Reworked CSMA algorithm
This commit is contained in:
parent
08651f92f7
commit
5ec063c939
3 changed files with 144 additions and 57 deletions
9
Boards.h
9
Boards.h
|
@ -19,6 +19,15 @@
|
||||||
#define PIN_DCD 5
|
#define PIN_DCD 5
|
||||||
#define PIN_TXSIG 4
|
#define PIN_TXSIG 4
|
||||||
|
|
||||||
|
// #define PIN_DIFS 7
|
||||||
|
// #define PIN_CW 6
|
||||||
|
// #define PIN_FLUSH 5
|
||||||
|
|
||||||
|
#define PIN_DIFS 3
|
||||||
|
#define PIN_CW 3
|
||||||
|
#define PIN_FLUSH 3
|
||||||
|
///////////////////////////
|
||||||
|
|
||||||
#include "Modem.h"
|
#include "Modem.h"
|
||||||
|
|
||||||
#ifndef BOARDS_H
|
#ifndef BOARDS_H
|
||||||
|
|
26
Config.h
26
Config.h
|
@ -67,18 +67,11 @@
|
||||||
const int rssi_offset = 157;
|
const int rssi_offset = 157;
|
||||||
|
|
||||||
// Default LoRa settings
|
// 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 PHY_HEADER_LORA_SYMBOLS 20
|
#define PHY_HEADER_LORA_SYMBOLS 20
|
||||||
#define PHY_CRC_LORA_BITS 16
|
#define PHY_CRC_LORA_BITS 16
|
||||||
#define LORA_PREAMBLE_SYMBOLS_MIN 18
|
#define LORA_PREAMBLE_SYMBOLS_MIN 18
|
||||||
#define LORA_PREAMBLE_TARGET_MS 15
|
#define LORA_PREAMBLE_TARGET_MS 15
|
||||||
#define LORA_CAD_SYMBOLS 3
|
#define LORA_CAD_SYMBOLS 3
|
||||||
#define CSMA_SLOT_SYMBOLS 12
|
|
||||||
#define CSMA_SLOT_MAX_MS 100
|
|
||||||
#define CSMA_SLOT_MIN_MS 24
|
|
||||||
|
|
||||||
long lora_preamble_symbols = 12;
|
long lora_preamble_symbols = 12;
|
||||||
long lora_preamble_time_ms = 0;
|
long lora_preamble_time_ms = 0;
|
||||||
long lora_header_time_ms = 0;
|
long lora_header_time_ms = 0;
|
||||||
|
@ -87,11 +80,28 @@
|
||||||
float lora_us_per_byte = 0.0;
|
float lora_us_per_byte = 0.0;
|
||||||
bool lora_low_datarate = false;
|
bool lora_low_datarate = false;
|
||||||
|
|
||||||
int csma_slot_ms = 50;
|
// CSMA Parameters
|
||||||
|
#define CSMA_POST_TX_YIELD_SLOTS 3
|
||||||
|
#define CSMA_SLOT_MAX_MS 100
|
||||||
|
#define CSMA_SLOT_MIN_MS 24
|
||||||
|
#define CSMA_SLOT_SYMBOLS 12
|
||||||
|
#define CSMA_CW_MIN 0
|
||||||
|
#define CSMA_CW_MAX 15
|
||||||
|
#define CSMA_SIFS_MS 0
|
||||||
|
int csma_slot_ms = CSMA_SLOT_MIN_MS;
|
||||||
|
long difs_ms = CSMA_SIFS_MS + 2*csma_slot_ms; // Distributed interframe space
|
||||||
|
long difs_wait_start = -1;
|
||||||
|
long cw_wait_start = -1;
|
||||||
|
long cw_wait_target = -1;
|
||||||
|
long cw_wait_passed = 0;
|
||||||
|
int csma_cw = -1;
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
float csma_p_min = 0.15;
|
float csma_p_min = 0.15;
|
||||||
float csma_p_max = 0.333;
|
float csma_p_max = 0.333;
|
||||||
float csma_b_speed = 0.15;
|
float csma_b_speed = 0.15;
|
||||||
uint8_t csma_p = 85;
|
uint8_t csma_p = 85;
|
||||||
|
////////////////////////////////////////
|
||||||
|
|
||||||
int lora_sf = 0;
|
int lora_sf = 0;
|
||||||
int lora_cr = 5;
|
int lora_cr = 5;
|
||||||
|
|
|
@ -64,6 +64,9 @@ void setup() {
|
||||||
pinMode(PIN_HEADER, OUTPUT);
|
pinMode(PIN_HEADER, OUTPUT);
|
||||||
pinMode(PIN_DCD, OUTPUT);
|
pinMode(PIN_DCD, OUTPUT);
|
||||||
pinMode(PIN_TXSIG, OUTPUT);
|
pinMode(PIN_TXSIG, OUTPUT);
|
||||||
|
pinMode(PIN_DIFS, OUTPUT);
|
||||||
|
pinMode(PIN_CW, OUTPUT);
|
||||||
|
pinMode(PIN_FLUSH, OUTPUT);
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
|
|
||||||
#if MCU_VARIANT == MCU_ESP32
|
#if MCU_VARIANT == MCU_ESP32
|
||||||
|
@ -521,7 +524,7 @@ bool queueFull() {
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile bool queue_flushing = false;
|
volatile bool queue_flushing = false;
|
||||||
void flushQueue(void) {
|
void flush_queue(void) {
|
||||||
if (!queue_flushing) {
|
if (!queue_flushing) {
|
||||||
|
|
||||||
// TODO: Remove debug
|
// TODO: Remove debug
|
||||||
|
@ -554,7 +557,6 @@ void flushQueue(void) {
|
||||||
|
|
||||||
lora_receive();
|
lora_receive();
|
||||||
led_tx_off();
|
led_tx_off();
|
||||||
post_tx_yield_timeout = millis()+(lora_post_tx_yield_slots*csma_slot_ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_height = 0;
|
queue_height = 0;
|
||||||
|
@ -628,7 +630,7 @@ void update_airtime() {
|
||||||
longterm_channel_util = (float)longterm_channel_util_sum/(float)AIRTIME_BINS;
|
longterm_channel_util = (float)longterm_channel_util_sum/(float)AIRTIME_BINS;
|
||||||
|
|
||||||
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
||||||
update_csma_p();
|
update_csma_parameters();
|
||||||
#endif
|
#endif
|
||||||
kiss_indicate_channel_stats();
|
kiss_indicate_channel_stats();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1199,7 +1201,9 @@ void serialCallback(uint8_t sbyte) {
|
||||||
portMUX_TYPE update_lock = portMUX_INITIALIZER_UNLOCKED;
|
portMUX_TYPE update_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void updateModemStatus() {
|
bool medium_free() { update_modem_status(); return !dcd; }
|
||||||
|
|
||||||
|
void update_modem_status() {
|
||||||
#if MCU_VARIANT == MCU_ESP32
|
#if MCU_VARIANT == MCU_ESP32
|
||||||
portENTER_CRITICAL(&update_lock);
|
portENTER_CRITICAL(&update_lock);
|
||||||
#elif MCU_VARIANT == MCU_NRF52
|
#elif MCU_VARIANT == MCU_NRF52
|
||||||
|
@ -1225,9 +1229,9 @@ void updateModemStatus() {
|
||||||
else { led_rx_off(); } }
|
else { led_rx_off(); } }
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkModemStatus() {
|
void check_modem_status() {
|
||||||
if (millis()-last_status_update >= status_interval_ms) {
|
if (millis()-last_status_update >= status_interval_ms) {
|
||||||
updateModemStatus();
|
update_modem_status();
|
||||||
|
|
||||||
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
||||||
util_samples[dcd_sample] = dcd;
|
util_samples[dcd_sample] = dcd;
|
||||||
|
@ -1385,13 +1389,56 @@ void validate_status() {
|
||||||
#define _e 2.71828183
|
#define _e 2.71828183
|
||||||
#define _S 12.5
|
#define _S 12.5
|
||||||
float csma_slope(float u) { return (pow(_e,_S*u-_S/2.0))/(pow(_e,_S*u-_S/2.0)+1.0); }
|
float csma_slope(float u) { return (pow(_e,_S*u-_S/2.0))/(pow(_e,_S*u-_S/2.0)+1.0); }
|
||||||
void update_csma_p() {
|
void update_csma_parameters() {
|
||||||
csma_p = (uint8_t)((1.0-(csma_p_min+(csma_p_max-csma_p_min)*csma_slope(airtime+csma_b_speed)))*255.0);
|
csma_p = (uint8_t)((1.0-(csma_p_min+(csma_p_max-csma_p_min)*csma_slope(airtime+csma_b_speed)))*255.0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void tx_queue_handler() {
|
||||||
|
if (!airtime_lock && queue_height > 0) {
|
||||||
|
if (csma_cw == -1) {
|
||||||
|
csma_cw = random(CSMA_CW_MIN, CSMA_CW_MAX);
|
||||||
|
cw_wait_target = csma_cw * csma_slot_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove metering signallers
|
||||||
|
if (difs_wait_start == -1) { digitalWrite(PIN_DIFS, LOW); }
|
||||||
|
if (cw_wait_start == -1) { digitalWrite(PIN_CW, LOW); } else { digitalWrite(PIN_CW, HIGH); }
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
if (difs_wait_start == -1) { // DIFS wait not yet started
|
||||||
|
if (medium_free()) { difs_wait_start = millis(); digitalWrite(PIN_DIFS, HIGH); return; } // Set DIFS wait start time
|
||||||
|
else { return; } } // Medium not yet free, continue waiting
|
||||||
|
|
||||||
|
else { // We are waiting for DIFS or CW to pass
|
||||||
|
if (!medium_free()) { difs_wait_start = -1; cw_wait_start = -1; return; } // Medium became occupied while in DIFS wait, restart waiting when free again
|
||||||
|
else { // Medium is free, so continue waiting
|
||||||
|
if (millis() < difs_wait_start+difs_ms) { return; } // DIFS has not yet passed, continue waiting
|
||||||
|
else { // DIFS has passed, and we are now in CW wait
|
||||||
|
digitalWrite(PIN_DIFS, LOW);
|
||||||
|
if (cw_wait_start == -1) { cw_wait_start = millis(); digitalWrite(PIN_CW, HIGH); return; } // If we haven't started counting CW wait time, do it from now
|
||||||
|
else { // If we are already counting CW wait time, add it to the counter
|
||||||
|
cw_wait_passed += millis()-cw_wait_start; cw_wait_start = millis();
|
||||||
|
if (cw_wait_passed < cw_wait_target) { return; } // Contention window wait time has not yet passed, continue waiting
|
||||||
|
else { // Wait time has passed, flush the queue
|
||||||
|
digitalWrite(PIN_FLUSH, HIGH);
|
||||||
|
digitalWrite(PIN_CW, LOW);
|
||||||
|
flush_queue();
|
||||||
|
digitalWrite(PIN_FLUSH, LOW);
|
||||||
|
digitalWrite(PIN_DIFS, LOW);
|
||||||
|
cw_wait_passed = 0; csma_cw = -1; difs_wait_start = -1; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if (radio_online) {
|
if (radio_online) {
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
|
|
||||||
#if MCU_VARIANT == MCU_ESP32
|
#if MCU_VARIANT == MCU_ESP32
|
||||||
modem_packet_t *modem_packet = NULL;
|
modem_packet_t *modem_packet = NULL;
|
||||||
if(modem_packet_queue && xQueueReceive(modem_packet_queue, &modem_packet, 0) == pdTRUE && modem_packet) {
|
if(modem_packet_queue && xQueueReceive(modem_packet_queue, &modem_packet, 0) == pdTRUE && modem_packet) {
|
||||||
|
@ -1434,50 +1481,57 @@ void loop() {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
checkModemStatus();
|
update_modem_status(); // TODO: Remove debug
|
||||||
if (!airtime_lock) {
|
|
||||||
if (queue_height > 0) {
|
|
||||||
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
|
||||||
|
|
||||||
long check_time = millis();
|
tx_queue_handler();
|
||||||
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) {
|
update_modem_status(); // TODO: Remove debug
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
check_modem_status();
|
||||||
if (!dcd_waiting) updateModemStatus();
|
|
||||||
|
|
||||||
if (!dcd) {
|
update_modem_status(); // TODO: Remove debug
|
||||||
if (dcd_waiting) delay(lora_rx_turnaround_ms);
|
|
||||||
|
|
||||||
updateModemStatus();
|
// if (queue_height > 0) {
|
||||||
|
// #if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
||||||
|
|
||||||
if (!dcd) {
|
// long check_time = millis();
|
||||||
dcd_waiting = false;
|
// if (check_time > post_tx_yield_timeout) {
|
||||||
flushQueue();
|
// 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();
|
||||||
|
// }
|
||||||
|
|
||||||
} else {
|
// if (!dcd) {
|
||||||
dcd_waiting = true;
|
// uint8_t csma_r = (uint8_t)random(256);
|
||||||
}
|
// if (csma_p >= csma_r) {
|
||||||
#endif
|
// flushQueue();
|
||||||
}
|
// } else {
|
||||||
}
|
// dcd_waiting = true;
|
||||||
|
// dcd_wait_until = millis()+csma_slot_ms;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #else
|
||||||
|
// if (!dcd_waiting) updateModemStatus();
|
||||||
|
|
||||||
|
// if (!dcd) {
|
||||||
|
// if (dcd_waiting) delay(lora_rx_turnaround_ms);
|
||||||
|
|
||||||
|
// updateModemStatus();
|
||||||
|
|
||||||
|
// if (!dcd) {
|
||||||
|
// dcd_waiting = false;
|
||||||
|
// flushQueue();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// dcd_waiting = true;
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
// }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (hw_ready) {
|
if (hw_ready) {
|
||||||
|
@ -1497,27 +1551,41 @@ void loop() {
|
||||||
|
|
||||||
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
|
||||||
buffer_serial();
|
buffer_serial();
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
|
|
||||||
if (!fifo_isempty(&serialFIFO)) serial_poll();
|
if (!fifo_isempty(&serialFIFO)) serial_poll();
|
||||||
|
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
#else
|
#else
|
||||||
if (!fifo_isempty_locked(&serialFIFO)) serial_poll();
|
if (!fifo_isempty_locked(&serialFIFO)) serial_poll();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
|
|
||||||
#if HAS_DISPLAY
|
#if HAS_DISPLAY
|
||||||
if (disp_ready) update_display();
|
if (disp_ready) update_display();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
|
|
||||||
#if HAS_PMU
|
#if HAS_PMU
|
||||||
if (pmu_ready) update_pmu();
|
if (pmu_ready) update_pmu();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
|
|
||||||
#if HAS_BLUETOOTH || HAS_BLE == true
|
#if HAS_BLUETOOTH || HAS_BLE == true
|
||||||
if (!console_active && bt_ready) update_bt();
|
if (!console_active && bt_ready) update_bt();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
|
|
||||||
#if HAS_INPUT
|
#if HAS_INPUT
|
||||||
input_read();
|
input_read();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
update_modem_status(); // TODO: Remove debug
|
||||||
|
|
||||||
if (memory_low) {
|
if (memory_low) {
|
||||||
#if PLATFORM == PLATFORM_ESP32
|
#if PLATFORM == PLATFORM_ESP32
|
||||||
if (esp_get_free_heap_size() < 8192) {
|
if (esp_get_free_heap_size() < 8192) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue