]> git.tnoah.ca Git - lora-radio.git/commitdiff
Added airtime limiting and channel timing stat reporting over serial/USB/bluetooth
authorMark Qvist <mark@unsigned.io>
Wed, 13 Sep 2023 18:05:05 +0000 (20:05 +0200)
committerMark Qvist <mark@unsigned.io>
Wed, 13 Sep 2023 18:05:05 +0000 (20:05 +0200)
Config.h
Framing.h
RNode_Firmware.ino
Release/console_image.bin
Utilities.h

index dc653c7e151afeddddbfbaddb3d82f6e7ad73b18..16b38fbb62e780b2caafaaf7f4c0be7621297f34 100644 (file)
--- a/Config.h
+++ b/Config.h
                float us_per_byte = 0.0;
                #define current_airtime_bin(void) (millis()%AIRTIME_LONGTERM_MS)/AIRTIME_BINLEN_MS
        #endif
+       float st_airtime_limit = 0.0;
+       float lt_airtime_limit = 0.0;
+       bool airtime_lock = false;
 
        bool stat_signal_detected = false;
        bool stat_signal_synced   = false;
index 00732b4b69bcf4a256b7e6d401e543146d186ada..79811b4b58c0559da64ca4dfaa60a2b972139484 100644 (file)
--- a/Framing.h
+++ b/Framing.h
@@ -33,6 +33,8 @@
   #define CMD_DETECT      0x08
   #define CMD_IMPLICIT    0x09
   #define CMD_LEAVE       0x0A
+  #define CMD_ST_ALOCK    0x0B
+  #define CMD_LT_ALOCK    0x0C
   #define CMD_PROMISC     0x0E
   #define CMD_READY       0x0F
 
@@ -40,6 +42,7 @@
   #define CMD_STAT_TX     0x22
   #define CMD_STAT_RSSI   0x23
   #define CMD_STAT_SNR    0x24
+  #define CMD_STAT_CHTM   0x25
   #define CMD_BLINK       0x30
   #define CMD_RANDOM      0x40
 
index 39a27aef923e399a77cfd0081d85accb0a58db47..4b316af0d0711645e1427576cdda2a7ce6ca2de5 100644 (file)
@@ -312,6 +312,8 @@ bool startRadio() {
       } else {
         radio_online = true;
 
+        init_channel_stats();
+
         setTXPower();
         setBandwidth();
         setSpreadingFactor();
@@ -395,6 +397,9 @@ void flushQueue(void) {
 
   queue_height = 0;
   queued_bytes = 0;
+  #if MCU_VARIANT == MCU_ESP32
+    update_airtime();
+  #endif
   queue_flushing = false;
 }
 
@@ -427,6 +432,8 @@ void update_airtime() {
       longterm_channel_util_sum += longterm_bins[bin];
     }
     longterm_channel_util = (float)longterm_channel_util_sum/(float)AIRTIME_BINS;
+
+    kiss_indicate_channel_stats();
   #endif
 }
 
@@ -650,6 +657,52 @@ void serialCallback(uint8_t sbyte) {
         startRadio();
         kiss_indicate_radiostate();
       }
+    } else if (command == CMD_ST_ALOCK) {
+      if (sbyte == FESC) {
+            ESCAPE = true;
+        } else {
+            if (ESCAPE) {
+                if (sbyte == TFEND) sbyte = FEND;
+                if (sbyte == TFESC) sbyte = FESC;
+                ESCAPE = false;
+            }
+            if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte;
+        }
+
+        if (frame_len == 2) {
+          uint16_t at = (uint16_t)cmdbuf[0] << 8 | (uint16_t)cmdbuf[1];
+
+          if (at == 0) {
+            st_airtime_limit = 0.0;
+          } else {
+            st_airtime_limit = (float)at/(100.0*100.0);
+            if (st_airtime_limit >= 1.0) { st_airtime_limit = 0.0; }
+          }
+          kiss_indicate_st_alock();
+        }
+    } else if (command == CMD_LT_ALOCK) {
+      if (sbyte == FESC) {
+            ESCAPE = true;
+        } else {
+            if (ESCAPE) {
+                if (sbyte == TFEND) sbyte = FEND;
+                if (sbyte == TFESC) sbyte = FESC;
+                ESCAPE = false;
+            }
+            if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte;
+        }
+
+        if (frame_len == 2) {
+          uint16_t at = (uint16_t)cmdbuf[0] << 8 | (uint16_t)cmdbuf[1];
+
+          if (at == 0) {
+            lt_airtime_limit = 0.0;
+          } else {
+            lt_airtime_limit = (float)at/(100.0*100.0);
+            if (lt_airtime_limit >= 1.0) { lt_airtime_limit = 0.0; }
+          }
+          kiss_indicate_lt_alock();
+        }
     } else if (command == CMD_STAT_RX) {
       kiss_indicate_stat_rx();
     } else if (command == CMD_STAT_TX) {
@@ -885,7 +938,11 @@ void updateModemStatus() {
   if (dcd_led) {
     led_rx_on();
   } else {
-    led_rx_off();
+    if (airtime_lock) {
+      led_indicate_airtime_lock();
+    } else {
+      led_rx_off();
+    }
   }
 }
 
@@ -905,7 +962,10 @@ 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;
+        int16_t cb = current_airtime_bin();
+        uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
+        if (total_channel_util > longterm_bins[cb]) longterm_bins[cb] = total_channel_util;
+        longterm_bins[nb] = 0.0;
 
         update_airtime();
       }
@@ -1047,23 +1107,29 @@ void loop() {
         kiss_indicate_stat_snr();
         kiss_write_packet();
       }
+
+      airtime_lock = false;
+      if (st_airtime_limit != 0.0 && airtime >= st_airtime_limit) airtime_lock = true;
+      if (lt_airtime_limit != 0.0 && longterm_airtime >= lt_airtime_limit) airtime_lock = true;
     #endif
 
-    if (queue_height > 0) {
-      if (!dcd_waiting) updateModemStatus();
+    if (!airtime_lock) {
+      if (queue_height > 0) {
+        if (!dcd_waiting) updateModemStatus();
 
-      if (!dcd && !dcd_led) {
-        if (dcd_waiting) delay(lora_rx_turnaround_ms);
+        if (!dcd && !dcd_led) {
+          if (dcd_waiting) delay(lora_rx_turnaround_ms);
 
-        updateModemStatus();
+          updateModemStatus();
 
-        if (!dcd) {
-          dcd_waiting = false;
-          flushQueue();
-        }
+          if (!dcd) {
+            dcd_waiting = false;
+            flushQueue();
+          }
 
-      } else {
-        dcd_waiting = true;
+        } else {
+          dcd_waiting = true;
+        }
       }
     }
   
index fda0764a89b9d8ffe73169cfe2c71bb7b1b49ab6..9321c0ea185259860712b5c7b11a8c2570e8e6c2 100644 (file)
Binary files a/Release/console_image.bin and b/Release/console_image.bin differ
index 78afdd29c52826bc8aae989cd3e93dad96128c7d..5c564bd07b7f19fedfbf94265344f2e0564f37e9 100644 (file)
@@ -218,6 +218,13 @@ void led_indicate_error(int cycles) {
        #endif
 }
 
+// LED Indication: Airtime Lock
+void led_indicate_airtime_lock() {
+       #if HAS_NP == true
+               npset(32,0,2);
+       #endif
+}
+
 // LED Indication: Boot Error
 void led_indicate_boot_error() {
        #if HAS_NP == true
@@ -687,6 +694,44 @@ void kiss_indicate_frequency() {
        serial_write(FEND);
 }
 
+void kiss_indicate_st_alock() {
+       uint16_t at = (uint16_t)(st_airtime_limit*100*100);
+       serial_write(FEND);
+       serial_write(CMD_ST_ALOCK);
+       escaped_serial_write(at>>8);
+       escaped_serial_write(at);
+       serial_write(FEND);
+}
+
+void kiss_indicate_lt_alock() {
+       uint16_t at = (uint16_t)(lt_airtime_limit*100*100);
+       serial_write(FEND);
+       serial_write(CMD_LT_ALOCK);
+       escaped_serial_write(at>>8);
+       escaped_serial_write(at);
+       serial_write(FEND);
+}
+
+void kiss_indicate_channel_stats() {
+       #if MCU_VARIANT == MCU_ESP32
+               uint16_t ats = (uint16_t)(airtime*100*100);
+               uint16_t atl = (uint16_t)(longterm_airtime*100*100);
+               uint16_t cls = (uint16_t)(total_channel_util*100*100);
+               uint16_t cll = (uint16_t)(longterm_channel_util*100*100);
+               serial_write(FEND);
+               serial_write(CMD_STAT_CHTM);
+               escaped_serial_write(ats>>8);
+               escaped_serial_write(ats);
+               escaped_serial_write(atl>>8);
+               escaped_serial_write(atl);
+               escaped_serial_write(cls>>8);
+               escaped_serial_write(cls);
+               escaped_serial_write(cll>>8);
+               escaped_serial_write(cll);
+               serial_write(FEND);
+       #endif
+}
+
 void kiss_indicate_btpin() {
        #if HAS_BLUETOOTH
                serial_write(FEND);
@@ -1182,13 +1227,15 @@ void unlock_rom() {
 }
 
 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;
+       #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; }
+               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;
+       #endif
 }
 
 typedef struct FIFOBuffer