]> git.tnoah.ca Git - lora-radio.git/commitdiff
Reworked queue and buffering
authorMark Qvist <mark@adepta.io>
Thu, 28 May 2020 20:18:19 +0000 (22:18 +0200)
committerMark Qvist <mark@adepta.io>
Thu, 28 May 2020 20:18:19 +0000 (22:18 +0200)
Config.h
Framing.h
RNode_Firmware.ino
Utilities.h

index 3d76536c50cf655bf7dc4fc728aeb187e0a3e2b1..144d78b4e27bddca21969834ce3d0d2182d8b804 100644 (file)
--- a/Config.h
+++ b/Config.h
@@ -4,18 +4,14 @@
        #define CONFIG_H
 
        #define MAJ_VERS  0x01
-       #define MIN_VERS  0x0D
+       #define MIN_VERS  0x0E
 
-       #define MCU_328P  0x90
        #define MCU_1284P 0x91
 
        #define MODE_HOST 0x11
        #define MODE_TNC  0x12
 
-       #if defined(__AVR_ATmega328P__)
-               #define MCU_VARIANT MCU_328P
-               #warning "Firmware is being compiled for atmega328p based boards"
-       #elif defined(__AVR_ATmega1284P__)
+       #if defined(__AVR_ATmega1284P__)
                #define MCU_VARIANT MCU_1284P
                #warning "Firmware is being compiled for atmega1284p based boards"
        #else
        #define MTU        500
        #define SINGLE_MTU 255
        #define HEADER_L   1
+       #define MIN_L      1
+
        #define CMD_L      4
 
        // MCU dependent configuration parameters
-       #if MCU_VARIANT == MCU_328P
-               const int pin_cs = 7;
-               const int pin_reset = 6;
-               const int pin_dio = 2;
-               const int pin_led_rx = 5;
-               const int pin_led_tx = 4;
-
-               #define FLOW_CONTROL_ENABLED true
-               #define QUEUE_SIZE 0
-
-               #define EEPROM_SIZE 512
-               #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
-       #endif
 
        #if MCU_VARIANT == MCU_1284P
                const int pin_cs = 4;
                const int pin_led_rx = 12;
                const int pin_led_tx = 13;
 
-               #define FLOW_CONTROL_ENABLED true
-               #define QUEUE_SIZE 24
-               #define QUEUE_BUF_SIZE (QUEUE_SIZE+1)
-               #define QUEUE_MEM QUEUE_BUF_SIZE * MTU
+               #define CONFIG_UART_BUFFER_SIZE 6750
+               #define CONFIG_QUEUE_SIZE 6750
+               #define CONFIG_QUEUE_MAX_LENGTH 70
 
                #define EEPROM_SIZE 4096
                #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
@@ -67,7 +51,6 @@
        // SX1276 RSSI offset to get dBm value from
        // packet RSSI register
        const int  rssi_offset      = 157;
-       const int  snr_offset       = 128;
 
        // Default LoRa settings
        int  lora_sf       = 0;
        uint8_t last_snr_raw    = 0x00;
        size_t  read_len                = 0;
        uint8_t seq                             = 0xFF;
+       
+       // Incoming packet buffer
        uint8_t pbuf[MTU];
-       uint8_t sbuf[MTU];
+
+       // KISS command buffer
        uint8_t cbuf[CMD_L];
 
-       #if QUEUE_SIZE > 0
-               uint8_t tbuf[MTU];
-               uint8_t qbuf[QUEUE_MEM];
-               size_t  queued_lengths[QUEUE_BUF_SIZE];
-       #endif
+       // LoRa transmit buffer
+       uint8_t tbuf[MTU];
 
        uint32_t stat_rx                = 0;
        uint32_t stat_tx                = 0;
 
-       bool outbound_ready       = false;
-       size_t queue_head        = 0;
-       size_t queue_tail                 = 0;
-
        bool stat_signal_detected = false;
        bool stat_signal_synced   = false;
        bool stat_rx_ongoing      = false;
index 10b380ca36a12626524c41a0ac4fd80e58267cd6..80ec1cd279fcb14c2677447e7e49f2735d333265 100644 (file)
--- a/Framing.h
+++ b/Framing.h
@@ -55,9 +55,6 @@
        size_t frame_len;
        bool IN_FRAME = false;
        bool ESCAPE = false;
-       bool SERIAL_READING = false;
        uint8_t command = CMD_UNKNOWN;
-       uint32_t last_serial_read = 0;
-       uint32_t serial_read_timeout_ms = 60;
 
 #endif
\ No newline at end of file
index b961f11bf4a20357ac0874d3c19ae2fd2d636c49..4eeb49b3f195298eb1bcb6b5a43fc6598365924c 100644 (file)
@@ -2,27 +2,49 @@
 #include <SPI.h>
 #include "Utilities.h"
 
+FIFOBuffer serialFIFO;
+uint8_t serialBuffer[CONFIG_UART_BUFFER_SIZE];
+
+FIFOBuffer16 packet_starts;
+size_t packet_starts_buf[CONFIG_QUEUE_MAX_LENGTH+1];
+
+FIFOBuffer16 packet_lengths;
+size_t packet_lengths_buf[CONFIG_QUEUE_MAX_LENGTH+1];
+
+uint8_t packet_queue[CONFIG_QUEUE_SIZE];
+
+volatile uint8_t queue_height = 0;
+volatile size_t queued_bytes = 0;
+volatile size_t queue_cursor = 0;
+volatile size_t current_packet_start = 0;
+
 void setup() {
   // Seed the PRNG
   randomSeed(analogRead(0));
 
   // Initialise serial communication
+  memset(serialBuffer, 0, sizeof(serialBuffer));
+  fifo_init(&serialFIFO, serialBuffer, sizeof(serialBuffer));
+
   Serial.begin(serial_baudrate);
   while (!Serial);
 
+  serial_timer_init();
+
   // Configure input and output pins
   pinMode(pin_led_rx, OUTPUT);
   pinMode(pin_led_tx, OUTPUT);
 
   // Initialise buffers
   memset(pbuf, 0, sizeof(pbuf));
-  memset(sbuf, 0, sizeof(sbuf));
   memset(cbuf, 0, sizeof(cbuf));
   
-  #if QUEUE_SIZE > 0
-    memset(qbuf, 0, sizeof(qbuf));
-    memset(queued_lengths, 0, sizeof(queued_lengths));
-  #endif
+  memset(packet_queue, 0, sizeof(packet_queue));
+  memset(packet_starts_buf, 0, sizeof(packet_starts));
+  memset(packet_lengths_buf, 0, sizeof(packet_lengths));
+
+  fifo16_init(&packet_starts, packet_starts_buf, sizeof(packet_starts_buf));
+  fifo16_init(&packet_lengths, packet_lengths_buf, sizeof(packet_lengths_buf));
 
   // Set chip select, reset and interrupt
   // pins for the LoRa module
@@ -188,66 +210,37 @@ void receiveCallback(int packet_size) {
   }
 }
 
-
-bool outboundReady() {
-  #if QUEUE_SIZE > 0
-    if (queue_head != queue_tail) {
-      return true;
-    } else {
-      return false;
-    }
-  #else
-    return outbound_ready;
-  #endif
-}
-
 bool queueFull() {
-  size_t new_queue_head = (queue_head+1)%QUEUE_BUF_SIZE;
-  if (new_queue_head == queue_tail) {
-    return true;
-  } else {
-    return false;
-  }
+  return (queue_height < CONFIG_QUEUE_MAX_LENGTH && queued_bytes < CONFIG_QUEUE_SIZE);
 }
 
-void enqueuePacket(size_t length) {
-  size_t new_queue_head = (queue_head+1)%QUEUE_BUF_SIZE;
-  if (new_queue_head != queue_tail) {
-    queued_lengths[queue_head] = length;
-    size_t insert_addr = queue_head * MTU;
-    for (int i = 0; i < length; i++) {
-      qbuf[insert_addr+i] = sbuf[i];
-    }
-    queue_head = new_queue_head;
-    if (!queueFull()) {
-      kiss_indicate_ready();
-    }
-  } else {
-    kiss_indicate_error(ERROR_QUEUE_FULL);
-  }
-}
-
-#if QUEUE_SIZE > 0
-void processQueue() {
-  size_t fetch_address = queue_tail*MTU;
-  size_t fetch_length  = queued_lengths[queue_tail];
-
-  for (int i = 0; i < fetch_length; i++) {
-    tbuf[i] = qbuf[fetch_address+i];
-    qbuf[fetch_address+i] = 0x00;
-  }
-
-  queued_lengths[queue_tail] = 0;
+volatile bool queue_flushing = false;
+void flushQueue(void) {
+  if (!queue_flushing) {
+    queue_flushing = true;
 
-  queue_tail = ++queue_tail%QUEUE_BUF_SIZE;
+    size_t processed = 0;
+    for (size_t n = 0; n < queue_height; n++) {
+      size_t start = fifo16_pop_locked(&packet_starts);
+      size_t length = fifo16_pop_locked(&packet_lengths);
 
-  transmit(fetch_length);
+      if (length >= MIN_L) {
+        for (size_t i = 0; i < length; i++) {
+          size_t pos = (start+i)%CONFIG_QUEUE_SIZE;
+          tbuf[i] = packet_queue[pos];
+        }
 
-  if (!queueFull()) {
-    kiss_indicate_ready();
+        transmit(length);
+        processed++;
+      }
+    }
   }
+
+  queue_height = 0;
+  queued_bytes = 0;
+  queue_flushing = false;
+  kiss_indicate_ready();
 }
-#endif
 
 void transmit(size_t size) {
   if (radio_online) {
@@ -264,11 +257,7 @@ void transmit(size_t size) {
       LoRa.write(header); written++;
 
       for (size_t i; i < size; i++) {
-        #if QUEUE_SIZE > 0
-          LoRa.write(tbuf[i]);
-        #else
-          LoRa.write(sbuf[i]);
-        #endif
+        LoRa.write(tbuf[i]);  
 
         written++;
 
@@ -298,11 +287,7 @@ void transmit(size_t size) {
 
       LoRa.beginPacket();
       for (size_t i; i < size; i++) {
-        #if QUEUE_SIZE > 0
-          LoRa.write(tbuf[i]);
-        #else
-          LoRa.write(sbuf[i]);
-        #endif
+        LoRa.write(tbuf[i]);
 
         written++;
       }
@@ -315,26 +300,35 @@ void transmit(size_t size) {
     kiss_indicate_error(ERROR_TXFAILED);
     led_indicate_error(5);
   }
-
-  #if QUEUE_SIZE == 0
-    if (FLOW_CONTROL_ENABLED)
-        kiss_indicate_ready();
-  #endif
 }
 
 void serialCallback(uint8_t sbyte) {
   if (IN_FRAME && sbyte == FEND && command == CMD_DATA) {
     IN_FRAME = false;
 
-    if (QUEUE_SIZE == 0) {
-      if (outbound_ready) {
-        kiss_indicate_error(ERROR_QUEUE_FULL);
-      } else {
-        outbound_ready = true;
-      }
-    } else {
-      enqueuePacket(frame_len);
+    if (queue_height < CONFIG_QUEUE_MAX_LENGTH && queued_bytes < CONFIG_QUEUE_SIZE) {
+        size_t s = current_packet_start;
+        size_t e = queue_cursor-1; if (e == -1) e = CONFIG_QUEUE_SIZE-1;
+        size_t l;
+
+        if (s != e) {
+            l = (s < e) ? e - s + 1 : CONFIG_QUEUE_SIZE - s + e + 1;
+        } else {
+            l = 1;
+        }
+
+        if (l >= MIN_L) {
+            queue_height++;
+
+            fifo16_push_locked(&packet_starts, s);
+            fifo16_push_locked(&packet_lengths, l);
+
+            current_packet_start = queue_cursor;
+        }
     }
+    
+    if (!queueFull()) kiss_indicate_ready();   
+
   } else if (sbyte == FEND) {
     IN_FRAME = true;
     command = CMD_UNKNOWN;
@@ -352,7 +346,11 @@ void serialCallback(uint8_t sbyte) {
                 if (sbyte == TFESC) sbyte = FESC;
                 ESCAPE = false;
             }
-            sbuf[frame_len++] = sbyte;
+            if (queue_height < CONFIG_QUEUE_MAX_LENGTH && queued_bytes < CONFIG_QUEUE_SIZE) {
+              queued_bytes++;
+              packet_queue[queue_cursor++] = sbyte;
+              if (queue_cursor == CONFIG_QUEUE_SIZE) queue_cursor = 0;
+            }
         }
     } else if (command == CMD_FREQUENCY) {
       if (sbyte == FESC) {
@@ -566,19 +564,20 @@ void validateStatus() {
 void loop() {
   if (radio_online) {
     checkModemStatus();
-    if (outboundReady() && !SERIAL_READING) {
+
+    if (queue_height > 0) {
       if (!dcd_waiting) updateModemStatus();
+
       if (!dcd && !dcd_led) {
         if (dcd_waiting) delay(lora_rx_turnaround_ms);
+
         updateModemStatus();
+
         if (!dcd) {
           dcd_waiting = false;
-          #if QUEUE_SIZE > 0
-            processQueue();
-          #else
-            outbound_ready = false;
-            transmit(frame_len);
-          #endif
+
+          flushQueue();
+          
         }
       } else {
         dcd_waiting = true;
@@ -594,14 +593,36 @@ void loop() {
     }
   }
 
-  if (Serial.available()) {
-    SERIAL_READING = true;
-    char sbyte = Serial.read();
+  serial_poll();
+}
+
+void serial_poll() {
+  while (!fifo_isempty_locked(&serialFIFO)) {
+    char sbyte = fifo_pop_locked(&serialFIFO);
     serialCallback(sbyte);
-    last_serial_read = millis();
-  } else {
-    if (SERIAL_READING && millis()-last_serial_read >= serial_read_timeout_ms) {
-      SERIAL_READING = false;
+  }
+}
+
+void buffer_serial() {
+  while (Serial.available()) {
+    char c = Serial.read();
+    if (!fifo_isfull_locked(&serialFIFO)) {
+      fifo_push_locked(&serialFIFO, c);
     }
   }
 }
+
+void serial_timer_init() {
+  TCCR3A = 0;
+  TCCR3B = _BV(CS10) |
+           _BV(WGM33)|
+           _BV(WGM32);
+
+  ICR3 = 23704; // Approximation of 16Mhz / 675
+
+  TIMSK3 = _BV(ICIE3);
+}
+
+ISR(TIMER3_CAPT_vect) {
+    buffer_serial();
+}
\ No newline at end of file
index 2753fad804944bd20f8e2c7a02ca89a71c410815..9aae3f61665137347166591c676706affc69dfdd 100644 (file)
@@ -1,4 +1,6 @@
 #include <EEPROM.h>
+#include <stddef.h>
+#include <util/atomic.h>
 #include "LoRa.h"
 #include "ROM.h"
 #include "Config.h"
@@ -468,3 +470,160 @@ void unlock_rom() {
        led_indicate_error(50);
        eeprom_erase();
 }
+
+typedef struct FIFOBuffer
+{
+  unsigned char *begin;
+  unsigned char *end;
+  unsigned char * volatile head;
+  unsigned char * volatile tail;
+} FIFOBuffer;
+
+inline bool fifo_isempty(const FIFOBuffer *f) {
+  return f->head == f->tail;
+}
+
+inline bool fifo_isfull(const FIFOBuffer *f) {
+  return ((f->head == f->begin) && (f->tail == f->end)) || (f->tail == f->head - 1);
+}
+
+inline void fifo_push(FIFOBuffer *f, unsigned char c) {
+  *(f->tail) = c;
+  
+  if (f->tail == f->end) {
+    f->tail = f->begin;
+  } else {
+    f->tail++;
+  }
+}
+
+inline unsigned char fifo_pop(FIFOBuffer *f) {
+  if(f->head == f->end) {
+    f->head = f->begin;
+    return *(f->end);
+  } else {
+    return *(f->head++);
+  }
+}
+
+inline void fifo_flush(FIFOBuffer *f) {
+  f->head = f->tail;
+}
+
+static inline bool fifo_isempty_locked(const FIFOBuffer *f) {
+  bool result;
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    result = fifo_isempty(f);
+  }
+  return result;
+}
+
+static inline bool fifo_isfull_locked(const FIFOBuffer *f) {
+  bool result;
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    result = fifo_isfull(f);
+  }
+  return result;
+}
+
+static inline void fifo_push_locked(FIFOBuffer *f, unsigned char c) {
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    fifo_push(f, c);
+  }
+}
+
+static inline unsigned char fifo_pop_locked(FIFOBuffer *f) {
+  unsigned char c;
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    c = fifo_pop(f);
+  }
+  return c;
+}
+
+inline void fifo_init(FIFOBuffer *f, unsigned char *buffer, size_t size) {
+  f->head = f->tail = f->begin = buffer;
+  f->end = buffer + size -1;
+}
+
+inline size_t fifo_len(FIFOBuffer *f) {
+  return f->end - f->begin;
+}
+
+typedef struct FIFOBuffer16
+{
+  size_t *begin;
+  size_t *end;
+  size_t * volatile head;
+  size_t * volatile tail;
+} FIFOBuffer16;
+
+inline bool fifo16_isempty(const FIFOBuffer16 *f) {
+  return f->head == f->tail;
+}
+
+inline bool fifo16_isfull(const FIFOBuffer16 *f) {
+  return ((f->head == f->begin) && (f->tail == f->end)) || (f->tail == f->head - 1);
+}
+
+inline void fifo16_push(FIFOBuffer16 *f, size_t c) {
+  *(f->tail) = c;
+
+  if (f->tail == f->end) {
+    f->tail = f->begin;
+  } else {
+    f->tail++;
+  }
+}
+
+inline size_t fifo16_pop(FIFOBuffer16 *f) {
+  if(f->head == f->end) {
+    f->head = f->begin;
+    return *(f->end);
+  } else {
+    return *(f->head++);
+  }
+}
+
+inline void fifo16_flush(FIFOBuffer16 *f) {
+  f->head = f->tail;
+}
+
+static inline bool fifo16_isempty_locked(const FIFOBuffer16 *f) {
+  bool result;
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    result = fifo16_isempty(f);
+  }
+  return result;
+}
+
+static inline bool fifo16_isfull_locked(const FIFOBuffer16 *f) {
+  bool result;
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    result = fifo16_isfull(f);
+  }
+  return result;
+}
+
+static inline void fifo16_push_locked(FIFOBuffer16 *f, size_t c) {
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    fifo16_push(f, c);
+  }
+}
+
+static inline size_t fifo16_pop_locked(FIFOBuffer16 *f) {
+  size_t c;
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+    c = fifo16_pop(f);
+  }
+  return c;
+}
+
+inline void fifo16_init(FIFOBuffer16 *f, size_t *buffer, size_t size) {
+  f->head = f->tail = f->begin = buffer;
+  f->end = buffer + (size/sizeof(size_t)) - 2;
+}
+
+inline size_t fifo16_len(FIFOBuffer16 *f) {
+  return ((f->end - f->begin))/sizeof(size_t);
+}
+