]> git.tnoah.ca Git - lora-radio.git/commitdiff
EEPROM validation and config util compat
authorMark Qvist <mark@adepta.io>
Wed, 20 Jun 2018 06:45:11 +0000 (08:45 +0200)
committerMark Qvist <mark@adepta.io>
Wed, 20 Jun 2018 06:45:11 +0000 (08:45 +0200)
Config.h
EEPROM.cpp [deleted file]
Framing.h
RNode_Firmware.ino
Utilities.cpp

index a8aeca6cdcb3c49bc6587de3d7c15c2539dbcbe7..ec87d76177488068187bacdd34992195bae09e94 100644 (file)
--- a/Config.h
+++ b/Config.h
@@ -1,13 +1,14 @@
+#include "ROM.h"
+
 #ifndef CONFIG_H
        #define CONFIG_H
 
+       #define MAJ_VERS  0x01
+       #define MIN_VERS  0x03
+
        #define MCU_328P  0x90
        #define MCU_1284P 0x91
 
-       #define PRODUCT_RNODE 0x03
-       #define MODEL_A4 0xA4
-       #define MODEL_A9 0xA9
-
        #if defined(__AVR_ATmega328P__)
                #define MCU_VARIANT MCU_328P
                #warning "Firmware is being compiled for atmega328p based boards"
@@ -33,6 +34,9 @@
 
                #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
 
                #define FLOW_CONTROL_ENABLED true
                #define QUEUE_SIZE 24
+
+               #define EEPROM_SIZE 4096
+               #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
        #endif
 
+       #define eeprom_addr(a) (a+EEPROM_OFFSET)
+
        // MCU independent configuration parameters
        const long serial_baudrate  = 115200;
        const int  rssi_offset      = 164;
@@ -62,6 +71,9 @@
        // Operational variables
        bool radio_locked = true;
        bool radio_online = false;
+       bool hw_ready     = false;
+       uint8_t model     = 0x00;
+       uint8_t hwrev     = 0x00;
        
        int             last_rssi               = -164;
        size_t  read_len                = 0;
diff --git a/EEPROM.cpp b/EEPROM.cpp
deleted file mode 100644 (file)
index b1990c1..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <Arduino.h>
-#include <EEPROM.h>
-#include "Config.h"
-#include "Framing.h"
-
-#define ADDR_PRODUCT   0x00
-#define ADDR_MODEL     0x01
-#define ADDR_HW_REV    0x02
-#define ADDR_SERIAL    0x03
-#define ADDR_MADE         0x06
-#define ADDR_CHKSUM       0x0A
-#define ADDR_SIGNATURE 0x1A
-#define ADDR_INFO_LOCK 0x9A
-#define INFO_LOCK_BYTE 0x73
-
-#define ADDR_CONF_SF   0x74
-#define ADDR_CONF_CR   0x75
-#define ADDR_CONF_TXP  0x76
-#define ADDR_CONF_BW   0x77
-#define ADDR_CONF_FREQ 0x7B
-#define ADDR_CONF_OK   0x7F
-#define CONF_OK_BYTE   0x73
-
-void eeprom_dump_info() {
-       for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) {
-               uint8_t rom_byte = EEPROM.read(addr);
-               Serial.write(rom_byte);
-       }
-}
-
-void eeprom_dump_config() {
-       for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) {
-               uint8_t rom_byte = EEPROM.read(addr);
-               Serial.write(rom_byte);
-       }
-}
\ No newline at end of file
index af810421cf4ecfd5de9e627658e0e1e8953d399e..eeebdf50099afcd705c2d65265071796663697a7 100644 (file)
--- a/Framing.h
+++ b/Framing.h
        #define CMD_BANDWIDTH   0x02
        #define CMD_TXPOWER             0x03
        #define CMD_SF                  0x04
-       #define CMD_RADIO_STATE 0x05
-       #define CMD_RADIO_LOCK  0x06
+       #define CMD_CR                  0x05
+       #define CMD_RADIO_STATE 0x06
+       #define CMD_RADIO_LOCK  0x07
+       #define CMD_DETECT              0x08
        #define CMD_READY               0x0F
 
        #define CMD_STAT_RX             0x21
        #define CMD_BLINK               0x30
        #define CMD_RANDOM              0x40
 
-       #define CMD_INFO_READ   0x50
-       #define CMD_INFO_WRITE  0x51
-       #define CMD_CONF_READ   0x52
-       #define CMD_CONF_WRITE  0x53
+       #define CMD_FW_VERSION  0x50
+       #define CMD_ROM_READ    0x51
+       #define CMD_ROM_WRITE   0x52
+       #define CMD_CONF_SAVE   0x53
+       #define CMD_UNLOCK_ROM  0x59
+       #define ROM_UNLOCK_BYTE 0xF8
+
+       #define DETECT_REQ              0x73
+       #define DETECT_RESP             0x46
 
        #define RADIO_STATE_OFF 0x00
        #define RADIO_STATE_ON  0x01
 
-       #define CMD_ERROR               0x90
-       #define ERROR_INITRADIO 0x01
-       #define ERROR_TXFAILED  0x02
-
        #define NIBBLE_SEQ              0xF0
        #define NIBBLE_FLAGS    0x0F
        #define FLAG_SPLIT              0x01
        #define SEQ_UNSET               0xFF
 
+       #define CMD_ERROR                       0x90
+       #define ERROR_INITRADIO         0x01
+       #define ERROR_TXFAILED          0x02
+       #define ERROR_EEPROM_LOCKED 0x03
+
        // Serial framing variables
        size_t frame_len;
        bool IN_FRAME = false;
@@ -57,7 +65,7 @@ All:                                  0xc00119d21b80c00200005140c00308c00407c0
 
 Radio on                               0xc00501c0
 
-Config+on                              0xc00119d21b80c00200005140c00308c00407c00501c0
+Config+on                              0xc00119d21b80c00200005140c00301c00407c00601c0
 
 
                c1 = self.bandwidth >> 24
index 5d1c851b08364bcb854784dd13314bbed1de4db1..9a9e2a604ce7f5b7edecac587f9628f47cfd5a70 100644 (file)
@@ -2,7 +2,6 @@
 #include <LoRa.h>
 #include "Config.h"
 #include "Framing.h"
-#include "EEPROM.cpp"
 #include "Utilities.cpp"
 
 void setup() {
@@ -25,12 +24,15 @@ void setup() {
   // Set chip select, reset and interrupt
   // pins for the LoRa module
   LoRa.setPins(pin_cs, pin_reset, pin_dio);
+
+  // Validate board health, EEPROM and config
+  validateStatus();
 }
 
 bool startRadio() {
   update_radio_lock();
   if (!radio_online) {
-    if (!radio_locked) {
+    if (!radio_locked && hw_ready) {
       if (!LoRa.begin(lora_freq)) {
         // The radio could not be started.
         // Indicate this failure over both the
@@ -280,6 +282,18 @@ void serialCallback(uint8_t sbyte) {
         setSpreadingFactor();
         kiss_indicate_spreadingfactor();
       }
+    } else if (command == CMD_CR) {
+      if (sbyte == 0xFF) {
+        kiss_indicate_codingrate();
+      } else {
+        int cr = sbyte;
+        if (cr < 5) cr = 5;
+        if (cr > 8) cr = 8;
+
+        lora_cr = cr;
+        setCodingRate();
+        kiss_indicate_codingrate();
+      }
     } else if (command == CMD_RADIO_STATE) {
       if (sbyte == 0xFF) {
         kiss_indicate_radiostate();
@@ -303,6 +317,33 @@ void serialCallback(uint8_t sbyte) {
       led_indicate_info(sbyte);
     } else if (command == CMD_RANDOM) {
       kiss_indicate_random(getRandom());
+    } else if (command == CMD_DETECT) {
+      if (sbyte == DETECT_REQ) {
+        kiss_indicate_detect();
+      }
+    } else if (command == CMD_UNLOCK_ROM) {
+      if (sbyte == ROM_UNLOCK_BYTE) {
+        unlock_rom();
+      }
+    } else if (command == CMD_ROM_READ) {
+      kiss_dump_eeprom();
+    } else if (command == CMD_ROM_WRITE) {
+      if (sbyte == FESC) {
+            ESCAPE = true;
+        } else {
+            if (ESCAPE) {
+                if (sbyte == TFEND) sbyte = FEND;
+                if (sbyte == TFESC) sbyte = FESC;
+                ESCAPE = false;
+            }
+            cbuf[frame_len++] = sbyte;
+        }
+
+        if (frame_len == 2) {
+          eeprom_write(cbuf[0], cbuf[1]);
+        }
+    } else if (command == CMD_FW_VERSION) {
+      kiss_indicate_version();
     }
   }
 }
@@ -344,6 +385,20 @@ void checkModemStatus() {
   }
 }
 
+void validateStatus() {
+  if (eeprom_lock_set()) {
+    if (eeprom_product_valid() && eeprom_model_valid() && eeprom_hwrev_valid()) {
+      if (eeprom_checksum_valid()) {
+        hw_ready = true;
+      }
+    } else {
+      hw_ready = false;
+    }
+  } else {
+    hw_ready = false;
+  }
+}
+
 void loop() {
   if (radio_online) {
     checkModemStatus();
@@ -362,7 +417,12 @@ void loop() {
       }
     }
   } else {
-    led_indicate_standby();
+    if (hw_ready) {
+      led_indicate_standby();
+    } else {
+      led_indicate_not_ready();
+      stopRadio();
+    }
   }
 
   if (Serial.available()) {
index 29d9639ace2e9cb061395e608e4efff5d97dd707..74170869ae1c79d340cdc04884ea122860e3e36d 100644 (file)
@@ -1,7 +1,10 @@
 #include <Arduino.h>
+#include <EEPROM.h>
 #include <LoRa.h>
+#include "ROM.h"
 #include "Config.h"
 #include "Framing.h"
+#include "MD5.h"
 
 void led_rx_on()  { digitalWrite(pin_led_rx, HIGH); }
 void led_rx_off() {    digitalWrite(pin_led_rx, LOW); }
@@ -68,6 +71,22 @@ void led_indicate_standby() {
                }
                led_standby_value += led_standby_direction;
                analogWrite(pin_led_rx, led_standby_value);
+               digitalWrite(pin_led_tx, 0);
+       }
+}
+
+void led_indicate_not_ready() {
+       led_standby_ticks++;
+       if (led_standby_ticks > led_standby_wait) {
+               led_standby_ticks = 0;
+               if (led_standby_value <= led_standby_min) {
+                       led_standby_direction = 1;
+               } else if (led_standby_value >= led_standby_max) {
+                       led_standby_direction = -1;
+               }
+               led_standby_value += led_standby_direction;
+               analogWrite(pin_led_tx, led_standby_value);
+               digitalWrite(pin_led_rx, 0);
        }
 }
 
@@ -132,6 +151,13 @@ void kiss_indicate_spreadingfactor() {
        Serial.write(FEND);
 }
 
+void kiss_indicate_codingrate() {
+       Serial.write(FEND);
+       Serial.write(CMD_CR);
+       Serial.write((uint8_t)lora_cr);
+       Serial.write(FEND);
+}
+
 void kiss_indicate_txpower() {
        Serial.write(FEND);
        Serial.write(CMD_TXPOWER);
@@ -173,6 +199,21 @@ void kiss_indicate_ready() {
        Serial.write(FEND);
 }
 
+void kiss_indicate_detect() {
+       Serial.write(FEND);
+       Serial.write(CMD_DETECT);
+       Serial.write(DETECT_RESP);
+       Serial.write(FEND);
+}
+
+void kiss_indicate_version() {
+       Serial.write(FEND);
+       Serial.write(CMD_FW_VERSION);
+       Serial.write(MAJ_VERS);
+       Serial.write(MIN_VERS);
+       Serial.write(FEND);
+}
+
 bool isSplitPacket(uint8_t header) {
        return (header & FLAG_SPLIT);
 }
@@ -197,7 +238,10 @@ void setCodingRate() {
 }
 
 void setTXPower() {
-       if (radio_online) LoRa.setTxPower(lora_txp);
+       if (radio_online) {
+               if (model == MODEL_A4) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
+               if (model == MODEL_A9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
+       }
 }
 
 
@@ -235,3 +279,116 @@ uint8_t getRandom() {
        }
 }
 
+bool eeprom_info_locked() {
+       uint8_t lock_byte = EEPROM.read(eeprom_addr(ADDR_INFO_LOCK));
+       if (lock_byte == INFO_LOCK_BYTE) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+void eeprom_dump_info() {
+       for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) {
+               uint8_t byte = EEPROM.read(eeprom_addr(addr));
+               escapedSerialWrite(byte);
+       }
+}
+
+void eeprom_dump_config() {
+       for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) {
+               uint8_t byte = EEPROM.read(eeprom_addr(addr));
+               escapedSerialWrite(byte);
+       }
+}
+
+void eeprom_dump_all() {
+       for (int addr = 0; addr < EEPROM_RESERVED; addr++) {
+               uint8_t byte = EEPROM.read(eeprom_addr(addr));
+               escapedSerialWrite(byte);
+       }
+}
+
+void kiss_dump_eeprom() {
+       Serial.write(FEND);
+       Serial.write(CMD_ROM_READ);
+       eeprom_dump_all();
+       Serial.write(FEND);
+}
+
+void eeprom_write(uint8_t addr, uint8_t byte) {
+       if (!eeprom_info_locked() && addr >= 0 && addr < EEPROM_RESERVED) {
+               EEPROM.update(eeprom_addr(addr), byte);
+       } else {
+               kiss_indicate_error(ERROR_EEPROM_LOCKED);
+       }
+}
+
+void eeprom_erase() {
+       for (int addr = 0; addr < EEPROM_RESERVED; addr++) {
+               EEPROM.update(eeprom_addr(addr), 0xFF);
+       }
+       while (true) { led_tx_on(); led_rx_off(); }
+}
+
+bool eeprom_lock_set() {
+       if (EEPROM.read(eeprom_addr(ADDR_INFO_LOCK)) == INFO_LOCK_BYTE) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+bool eeprom_product_valid() {
+       if (EEPROM.read(eeprom_addr(ADDR_PRODUCT)) == PRODUCT_RNODE) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+bool eeprom_model_valid() {
+       model = EEPROM.read(eeprom_addr(ADDR_MODEL));
+       if (model == MODEL_A4 || model == MODEL_A9) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+bool eeprom_hwrev_valid() {
+       hwrev = EEPROM.read(eeprom_addr(ADDR_HW_REV));
+       if (hwrev != 0x00 && hwrev != 0xFF) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+bool eeprom_checksum_valid() {
+       char *data = (char*)malloc(CHECKSUMMED_SIZE);
+       for (uint8_t  i = 0; i < CHECKSUMMED_SIZE; i++) {
+               char byte = EEPROM.read(eeprom_addr(i));
+               data[i] = byte;
+       }
+       
+       unsigned char *hash = MD5::make_hash(data, CHECKSUMMED_SIZE);
+       bool checksum_valid = true;
+       for (uint8_t i = 0; i < 16; i++) {
+               uint8_t stored_chk_byte = EEPROM.read(eeprom_addr(ADDR_CHKSUM+i));
+               uint8_t calced_chk_byte = (uint8_t)hash[i];
+               if (stored_chk_byte != calced_chk_byte) {
+                       checksum_valid = false;
+               }
+       }
+
+       free(hash);
+       free(data);
+       return checksum_valid;
+}
+
+void unlock_rom() {
+       led_indicate_error(50);
+       eeprom_erase();
+}
+