diff --git a/Config.h b/Config.h index 4c95b86..3f3b8ba 100644 --- a/Config.h +++ b/Config.h @@ -22,7 +22,7 @@ #define MIN_VERS 0x3F #define PLATFORM_AVR 0x90 - #define PLATFORM_ESP32 0x80 + #define PLATFORM_ESP32 0x80 #define MCU_1284P 0x91 #define MCU_2560 0x92 @@ -301,6 +301,7 @@ int lora_txp = 0xFF; uint32_t lora_bw = 0; uint32_t lora_freq = 0; + uint32_t lora_bitrate = 0; // Operational variables bool radio_locked = true; @@ -337,6 +338,26 @@ uint32_t stat_rx = 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_synced = false; bool stat_rx_ongoing = false; @@ -346,7 +367,7 @@ uint16_t dcd_count = 0; 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; // Status flags @@ -366,6 +387,7 @@ float battery_percent = 0.0; uint8_t battery_state = 0x00; uint8_t display_intensity = 0xFF; + bool display_diagnostics = true; bool device_init_done = false; bool eeprom_ok = false; bool firmware_update_mode = false; diff --git a/Display.h b/Display.h index 5ee4879..7673675 100644 --- a/Display.h +++ b/Display.h @@ -436,6 +436,17 @@ void draw_disp_area() { } else { 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()); + } } } diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index e12121e..9788b9a 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -89,6 +89,9 @@ void setup() { LoRa.setPins(pin_cs, pin_reset, pin_dio); #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 // probe boot parameters. if (LoRa.preInit()) { @@ -396,6 +399,27 @@ void flushQueue(void) { 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) { if (radio_online) { if (!promisc) { @@ -411,19 +435,19 @@ void transmit(uint16_t size) { LoRa.write(header); written++; for (uint16_t i=0; i < size; i++) { - LoRa.write(tbuf[i]); + LoRa.write(tbuf[i]); written++; if (written == 255) { - LoRa.endPacket(); + LoRa.endPacket(); add_airtime(written); LoRa.beginPacket(); LoRa.write(header); written = 1; } } - LoRa.endPacket(); + LoRa.endPacket(); add_airtime(written); led_tx_off(); lora_receive(); @@ -452,7 +476,7 @@ void transmit(uint16_t size) { written++; } - LoRa.endPacket(); + LoRa.endPacket(); add_airtime(written); led_tx_off(); lora_receive(); @@ -858,6 +882,22 @@ void updateModemStatus() { void checkModemStatus() { if (millis()-last_status_update >= status_interval_ms) { 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) { dcd_waiting = false; - flushQueue(); - } + } else { dcd_waiting = true; } diff --git a/Utilities.h b/Utilities.h index a114e06..103738b 100644 --- a/Utilities.h +++ b/Utilities.h @@ -860,12 +860,28 @@ inline uint8_t packetSequence(uint8_t header) { 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() { if (radio_online) LoRa.setSpreadingFactor(lora_sf); + updateBitrate(); } void setCodingRate() { if (radio_online) LoRa.setCodingRate4(lora_cr); + updateBitrate(); } void set_implicit_length(uint8_t len) { @@ -912,6 +928,7 @@ void getBandwidth() { if (radio_online) { lora_bw = LoRa.getSignalBandwidth(); } + updateBitrate(); } void setBandwidth() {