From f4cdd5ea4a185d046410cb89ff8f4fe2787bdbe5 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Tue, 12 Sep 2023 21:51:51 +0200 Subject: [PATCH] Added channel load and airtime stats to display --- Config.h | 4 +- Display.h | 105 ++++++++++++++++++++++++++++++++------------- Graphics.h | 8 ++++ RNode_Firmware.ino | 20 +++++++-- Utilities.h | 10 +++++ 5 files changed, 112 insertions(+), 35 deletions(-) diff --git a/Config.h b/Config.h index 3f3b8ba..dc653c7 100644 --- a/Config.h +++ b/Config.h @@ -19,7 +19,7 @@ #define CONFIG_H #define MAJ_VERS 0x01 - #define MIN_VERS 0x3F + #define MIN_VERS 0x40 #define PLATFORM_AVR 0x90 #define PLATFORM_ESP32 0x80 @@ -349,9 +349,11 @@ #define AIRTIME_BINS ((AIRTIME_LONGTERM*1000)/AIRTIME_BINLEN_MS) bool util_samples[DCD_SAMPLES]; uint16_t airtime_bins[AIRTIME_BINS]; + float longterm_bins[AIRTIME_BINS]; int dcd_sample = 0; float local_channel_util = 0.0; float total_channel_util = 0.0; + float longterm_channel_util = 0.0; float airtime = 0.0; float longterm_airtime = 0.0; float us_per_byte = 0.0; diff --git a/Display.h b/Display.h index 7673675..96dcb92 100644 --- a/Display.h +++ b/Display.h @@ -17,6 +17,7 @@ #include #include #include +#include "Fonts/Org_01.h" #define DISP_W 128 #define DISP_H 64 #if BOARD_MODEL == BOARD_RNODE_NG_20 || BOARD_MODEL == BOARD_LORA32_V2_0 @@ -36,6 +37,8 @@ #define DISP_ADDR 0x3C #endif +#define SMALL_FONT &Org_01 + Adafruit_SSD1306 display(DISP_W, DISP_H, &Wire, DISP_RST); #define DISP_MODE_UNKNOWN 0x00 @@ -359,12 +362,46 @@ void draw_disp_area() { if (firmware_update_mode) disp_area.drawBitmap(0, p_by, bm_fw_update, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); } else { if (!disp_ext_fb or bt_ssp_pin != 0) { - if (device_signatures_ok()) { - disp_area.drawBitmap(0, 0, bm_def_lc, disp_area.width(), 37, SSD1306_WHITE, SSD1306_BLACK); + if (radio_online && display_diagnostics) { + disp_area.fillRect(0,8,disp_area.width(),37, SSD1306_BLACK); + disp_area.setFont(SMALL_FONT); + disp_area.setTextColor(SSD1306_WHITE); + disp_area.setTextWrap(false); + + disp_area.setCursor(1, 14); + disp_area.print("On"); + disp_area.setCursor(1+12, 14); + disp_area.print("@"); + disp_area.setCursor(1+12+1+6, 14); + disp_area.printf("%.1fKbps", (float)lora_bitrate/1000.0); + + disp_area.setCursor(2, 23); + disp_area.print("Channel Load"); + + disp_area.setCursor(11, 33); + if (total_channel_util < 0.099) { + disp_area.printf("%.1f%%", total_channel_util*100.0); + } else { + disp_area.printf("%.0f%%", total_channel_util*100.0); + } + disp_area.drawBitmap(2, 26, bm_hg_low, 5, 9, SSD1306_WHITE, SSD1306_BLACK); + + disp_area.setCursor(32+11, 33); + if (longterm_channel_util < 0.099) { + disp_area.printf("%.1f%%", longterm_channel_util*100.0); + } else { + disp_area.printf("%.0f%%", longterm_channel_util*100.0); + } + disp_area.drawBitmap(32+2, 26, bm_hg_high, 5, 9, SSD1306_WHITE, SSD1306_BLACK); + } else { - disp_area.drawBitmap(0, 0, bm_def, disp_area.width(), 37, SSD1306_WHITE, SSD1306_BLACK); + if (device_signatures_ok()) { + disp_area.drawBitmap(0, 0, bm_def_lc, disp_area.width(), 37, SSD1306_WHITE, SSD1306_BLACK); + } else { + disp_area.drawBitmap(0, 0, bm_def, disp_area.width(), 37, SSD1306_WHITE, SSD1306_BLACK); + } } - + if (!hw_ready || radio_error || !device_firmware_ok()) { if (!device_firmware_ok()) { disp_area.drawBitmap(0, 37, bm_fw_corrupt, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); @@ -393,30 +430,49 @@ void draw_disp_area() { if (not community_fw and disp_page == 0) disp_page = 1; } - if (disp_page == 0) { - if (true || device_signatures_ok()) { - if (radio_online) { - disp_area.drawBitmap(0, 37, bm_online, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); + if (radio_online) { + if (display_diagnostics) { + disp_area.fillRect(0,37,disp_area.width(),27, SSD1306_WHITE); + disp_area.setFont(SMALL_FONT); + disp_area.setTextColor(SSD1306_BLACK); + disp_area.setTextWrap(false); + + disp_area.setCursor(1+20+10, 37+3+7-3+1+1); + disp_area.print("Airtime"); + + disp_area.setCursor(11, 37+13+10-4+1); + if (total_channel_util < 0.099) { + disp_area.printf("%.1f%%", airtime*100.0); } else { - disp_area.drawBitmap(0, 37, bm_checks, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); + disp_area.printf("%.0f%%", airtime*100.0); } + disp_area.drawBitmap(2, 37+6+10-4+1, bm_hg_low, 5, 9, SSD1306_BLACK, SSD1306_WHITE); + + disp_area.setCursor(32+11, 37+13+10-4+1); + if (longterm_channel_util < 0.099) { + disp_area.printf("%.1f%%", longterm_airtime*100.0); + } else { + disp_area.printf("%.0f%%", longterm_airtime*100.0); + } + disp_area.drawBitmap(32+2, 37+6+10-4+1, bm_hg_high, 5, 9, SSD1306_BLACK, SSD1306_WHITE); + } else { - disp_area.drawBitmap(0, 37, bm_nfr, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); - } - } else if (disp_page == 1) { - if (radio_online) { disp_area.drawBitmap(0, 37, bm_online, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); - } else{ + } + } else { + if (disp_page == 0) { + if (device_signatures_ok()) { + disp_area.drawBitmap(0, 37, bm_checks, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); + } else { + disp_area.drawBitmap(0, 37, bm_nfr, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); + } + } else if (disp_page == 1) { if (!console_active) { disp_area.drawBitmap(0, 37, bm_hwok, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); } else { disp_area.drawBitmap(0, 37, bm_console_active, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); } - } - } else if (disp_page == 2) { - if (radio_online) { - disp_area.drawBitmap(0, 37, bm_online, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); - } else{ + } else if (disp_page == 2) { disp_area.drawBitmap(0, 37, bm_version, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK); char *v_str = (char*)malloc(3+1); sprintf(v_str, "%01d%02d", MAJ_VERS, MIN_VERS); @@ -436,17 +492,6 @@ 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/Graphics.h b/Graphics.h index e2b032f..3f1daf5 100644 --- a/Graphics.h +++ b/Graphics.h @@ -406,4 +406,12 @@ const unsigned char bm_n_uh [] PROGMEM = { const unsigned char bm_plug [] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x7f, 0x80, 0x55, 0xfc, 0x00, 0xaa, 0xfc, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x1c, 0x00 +}; + +const unsigned char bm_hg_low [] PROGMEM = { + 0xf8, 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0xf8, 0xf8 +}; + +const unsigned char bm_hg_high [] PROGMEM = { + 0xf8, 0x88, 0xf8, 0x70, 0x20, 0x70, 0xf8, 0xf8, 0xf8 }; \ No newline at end of file diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 9788b9a..39a27ae 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -89,8 +89,7 @@ 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; } + init_channel_stats(); // Check installed transceiver chip and // probe boot parameters. @@ -402,14 +401,19 @@ void flushQueue(void) { 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; + uint16_t cb = current_airtime_bin(); + uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; } + airtime_bins[cb] += ms_cost; + airtime_bins[nb] = 0; #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; } + uint16_t pb = cb-1; if (pb < 0) { pb = AIRTIME_BINS-1; } + uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; } + airtime_bins[nb] = 0; airtime = (float)(airtime_bins[cb]+airtime_bins[pb])/(2.0*AIRTIME_BINLEN_MS); uint32_t longterm_airtime_sum = 0; @@ -417,6 +421,12 @@ void update_airtime() { longterm_airtime_sum += airtime_bins[bin]; } longterm_airtime = (float)longterm_airtime_sum/(float)AIRTIME_LONGTERM_MS; + + float longterm_channel_util_sum = 0.0; + for (uint16_t bin = 0; bin < AIRTIME_BINS; bin++) { + longterm_channel_util_sum += longterm_bins[bin]; + } + longterm_channel_util = (float)longterm_channel_util_sum/(float)AIRTIME_BINS; #endif } @@ -895,6 +905,8 @@ void checkModemStatus() { total_channel_util = local_channel_util + airtime; if (total_channel_util > 1.0) total_channel_util = 1.0; + longterm_bins[current_airtime_bin()] = total_channel_util; + update_airtime(); } #endif diff --git a/Utilities.h b/Utilities.h index 103738b..78afdd2 100644 --- a/Utilities.h +++ b/Utilities.h @@ -1181,6 +1181,16 @@ void unlock_rom() { eeprom_erase(); } +void init_channel_stats() { + 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; } + for (uint16_t ai = 0; ai < AIRTIME_BINS; ai++) { longterm_bins[ai] = 0.0; } + local_channel_util = 0.0; + total_channel_util = 0.0; + airtime = 0.0; + longterm_airtime = 0.0; +} + typedef struct FIFOBuffer { unsigned char *begin;