Added channel utilisation and airtime accounting

This commit is contained in:
Mark Qvist 2023-09-12 14:48:47 +02:00
parent 6393d3feab
commit 41a7abff57
4 changed files with 97 additions and 8 deletions

View File

@ -301,6 +301,7 @@
int lora_txp = 0xFF; int lora_txp = 0xFF;
uint32_t lora_bw = 0; uint32_t lora_bw = 0;
uint32_t lora_freq = 0; uint32_t lora_freq = 0;
uint32_t lora_bitrate = 0;
// Operational variables // Operational variables
bool radio_locked = true; bool radio_locked = true;
@ -337,6 +338,26 @@
uint32_t stat_rx = 0; uint32_t stat_rx = 0;
uint32_t stat_tx = 0; uint32_t stat_tx = 0;
#define STATUS_INTERVAL_MS 3
#if MCU_VARIANT == MCU_ESP32
#define DCD_SAMPLES 2500
#define UTIL_UPDATE_INTERVAL_MS 1000
#define UTIL_UPDATE_INTERVAL (UTIL_UPDATE_INTERVAL_MS/STATUS_INTERVAL_MS)
#define AIRTIME_LONGTERM 3600
#define AIRTIME_LONGTERM_MS (AIRTIME_LONGTERM*1000)
#define AIRTIME_BINLEN_MS (STATUS_INTERVAL_MS*DCD_SAMPLES)
#define AIRTIME_BINS ((AIRTIME_LONGTERM*1000)/AIRTIME_BINLEN_MS)
bool util_samples[DCD_SAMPLES];
uint16_t airtime_bins[AIRTIME_BINS];
int dcd_sample = 0;
float local_channel_util = 0.0;
float total_channel_util = 0.0;
float airtime = 0.0;
float longterm_airtime = 0.0;
float us_per_byte = 0.0;
#define current_airtime_bin(void) (millis()%AIRTIME_LONGTERM_MS)/AIRTIME_BINLEN_MS
#endif
bool stat_signal_detected = false; bool stat_signal_detected = false;
bool stat_signal_synced = false; bool stat_signal_synced = false;
bool stat_rx_ongoing = false; bool stat_rx_ongoing = false;
@ -346,7 +367,7 @@
uint16_t dcd_count = 0; uint16_t dcd_count = 0;
uint16_t dcd_threshold = 15; uint16_t dcd_threshold = 15;
uint32_t status_interval_ms = 3; uint32_t status_interval_ms = STATUS_INTERVAL_MS;
uint32_t last_status_update = 0; uint32_t last_status_update = 0;
// Status flags // Status flags
@ -366,6 +387,7 @@
float battery_percent = 0.0; float battery_percent = 0.0;
uint8_t battery_state = 0x00; uint8_t battery_state = 0x00;
uint8_t display_intensity = 0xFF; uint8_t display_intensity = 0xFF;
bool display_diagnostics = true;
bool device_init_done = false; bool device_init_done = false;
bool eeprom_ok = false; bool eeprom_ok = false;
bool firmware_update_mode = false; bool firmware_update_mode = false;

View File

@ -436,6 +436,17 @@ void draw_disp_area() {
} else { } else {
disp_area.drawBitmap(0, 0, fb, disp_area.width(), disp_area.height(), SSD1306_WHITE, SSD1306_BLACK); disp_area.drawBitmap(0, 0, fb, disp_area.width(), disp_area.height(), SSD1306_WHITE, SSD1306_BLACK);
} }
if (display_diagnostics) {
disp_area.setCursor(0, 0);
disp_area.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
disp_area.setTextSize(1);
disp_area.printf("B:%.1fK\r\n", (float)lora_bitrate/1000.0);
disp_area.printf("U:%.1f%%\r\n", total_channel_util*100.0);
disp_area.printf("L:%.1f%%\r\n", local_channel_util*100.0);
disp_area.printf("A:%.2f%%\r\n", airtime*100.0);
disp_area.printf("a:%.2f%%\r\n", longterm_airtime*100.0);
disp_area.printf("C:%d\r\n", current_airtime_bin());
}
} }
} }

View File

@ -89,6 +89,9 @@ void setup() {
LoRa.setPins(pin_cs, pin_reset, pin_dio); LoRa.setPins(pin_cs, pin_reset, pin_dio);
#if MCU_VARIANT == MCU_ESP32 #if MCU_VARIANT == MCU_ESP32
for (uint16_t ai = 0; ai < DCD_SAMPLES; ai++) { util_samples[ai] = false; }
for (uint16_t ai = 0; ai < AIRTIME_BINS; ai++) { airtime_bins[ai] = 0; }
// Check installed transceiver chip and // Check installed transceiver chip and
// probe boot parameters. // probe boot parameters.
if (LoRa.preInit()) { if (LoRa.preInit()) {
@ -396,6 +399,27 @@ void flushQueue(void) {
queue_flushing = false; queue_flushing = false;
} }
void add_airtime(uint16_t written) {
#if MCU_VARIANT == MCU_ESP32
float ms_cost = ((float)written * us_per_byte)/1000.0;
airtime_bins[current_airtime_bin()] += ms_cost;
#endif
}
void update_airtime() {
#if MCU_VARIANT == MCU_ESP32
uint16_t cb = current_airtime_bin();
uint16_t pb = cb-1; if (cb < 0) { cb = AIRTIME_BINS-1; }
airtime = (float)(airtime_bins[cb]+airtime_bins[pb])/(2.0*AIRTIME_BINLEN_MS);
uint32_t longterm_airtime_sum = 0;
for (uint16_t bin = 0; bin < AIRTIME_BINS; bin++) {
longterm_airtime_sum += airtime_bins[bin];
}
longterm_airtime = (float)longterm_airtime_sum/(float)AIRTIME_LONGTERM_MS;
#endif
}
void transmit(uint16_t size) { void transmit(uint16_t size) {
if (radio_online) { if (radio_online) {
if (!promisc) { if (!promisc) {
@ -416,14 +440,14 @@ void transmit(uint16_t size) {
written++; written++;
if (written == 255) { if (written == 255) {
LoRa.endPacket(); LoRa.endPacket(); add_airtime(written);
LoRa.beginPacket(); LoRa.beginPacket();
LoRa.write(header); LoRa.write(header);
written = 1; written = 1;
} }
} }
LoRa.endPacket(); LoRa.endPacket(); add_airtime(written);
led_tx_off(); led_tx_off();
lora_receive(); lora_receive();
@ -452,7 +476,7 @@ void transmit(uint16_t size) {
written++; written++;
} }
LoRa.endPacket(); LoRa.endPacket(); add_airtime(written);
led_tx_off(); led_tx_off();
lora_receive(); lora_receive();
@ -858,6 +882,22 @@ void updateModemStatus() {
void checkModemStatus() { void checkModemStatus() {
if (millis()-last_status_update >= status_interval_ms) { if (millis()-last_status_update >= status_interval_ms) {
updateModemStatus(); updateModemStatus();
#if MCU_VARIANT == MCU_ESP32
util_samples[dcd_sample] = dcd;
dcd_sample = (dcd_sample+1)%DCD_SAMPLES;
if (dcd_sample % UTIL_UPDATE_INTERVAL == 0) {
int util_count = 0;
for (int ui = 0; ui < DCD_SAMPLES; ui++) {
if (util_samples[ui]) util_count++;
}
local_channel_util = (float)util_count / (float)DCD_SAMPLES;
total_channel_util = local_channel_util + airtime;
if (total_channel_util > 1.0) total_channel_util = 1.0;
update_airtime();
}
#endif
} }
} }
@ -1007,10 +1047,9 @@ void loop() {
if (!dcd) { if (!dcd) {
dcd_waiting = false; dcd_waiting = false;
flushQueue(); flushQueue();
} }
} else { } else {
dcd_waiting = true; dcd_waiting = true;
} }

View File

@ -860,12 +860,28 @@ inline uint8_t packetSequence(uint8_t header) {
return header >> 4; return header >> 4;
} }
void updateBitrate() {
#if MCU_VARIANT == MCU_ESP32
if (radio_online) {
// self.bitrate = self.r_sf * ( (4.0/self.r_cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
// self.bitrate_kbps = round(self.bitrate/1000.0, 2)
lora_bitrate = (uint32_t)(lora_sf * ( (4.0/(float)lora_cr) / ((float)(pow(2, lora_sf))/((float)lora_bw/1000.0)) ) * 1000.0);
us_per_byte = 1000000.0/((float)lora_bitrate/8.0);
} else {
lora_bitrate = 0;
}
#endif
}
void setSpreadingFactor() { void setSpreadingFactor() {
if (radio_online) LoRa.setSpreadingFactor(lora_sf); if (radio_online) LoRa.setSpreadingFactor(lora_sf);
updateBitrate();
} }
void setCodingRate() { void setCodingRate() {
if (radio_online) LoRa.setCodingRate4(lora_cr); if (radio_online) LoRa.setCodingRate4(lora_cr);
updateBitrate();
} }
void set_implicit_length(uint8_t len) { void set_implicit_length(uint8_t len) {
@ -912,6 +928,7 @@ void getBandwidth() {
if (radio_online) { if (radio_online) {
lora_bw = LoRa.getSignalBandwidth(); lora_bw = LoRa.getSignalBandwidth();
} }
updateBitrate();
} }
void setBandwidth() { void setBandwidth() {