From c7012c621dbe83b2cd389e1a3756ea16c1abada6 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Tue, 2 Jul 2019 12:58:55 +0100
Subject: [PATCH] Persist the frame counters in EEPROM

....but we don't initialise it to a value if it hasn't been written to
yet.
---
 iot/main/storage.cpp      | 13 ++++++++++++-
 iot/main/storage.h        | 29 +++++++++++++++++++++++++++--
 iot/main/transmission.cpp | 29 +++++++++++++++++++----------
 3 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/iot/main/storage.cpp b/iot/main/storage.cpp
index b636e21..d155304 100644
--- a/iot/main/storage.cpp
+++ b/iot/main/storage.cpp
@@ -1,5 +1,6 @@
 #include <Arduino.h>
 #include <SdFat.h>
+#include <EEPROM.h>
 // #include <ArduinoFiles.h>
 
 #include "settings.h"
@@ -40,9 +41,19 @@ void store_debug(char* buffer, int size) {
 
 /*
 void store_end() {
-	// Apparently we'ree fine so long as we don't have any open file handles - there's no end() method on the SdFat class
+	// Apparently we're fine so long as we don't have any open file handles - there's no end() method on the SdFat class
 	// card->end();
 	delete card;
 	card = nullptr;
 }
 */
+
+void store_eeprom_uint32_save(uint8_t offset, uint32_t value) {
+	EEPROM.put(offset, value);
+}
+
+uint32_t store_eeprom_uint32_retrieve(uint8_t offset) {
+	uint32_t result;
+	EEPROM.get(offset, result);
+	return result;
+}
diff --git a/iot/main/storage.h b/iot/main/storage.h
index bb0a476..a21fe4c 100644
--- a/iot/main/storage.h
+++ b/iot/main/storage.h
@@ -5,10 +5,35 @@
 
 #include "gps.h"
 
+/**
+ * Initialise the microSD card storage subsystem.
+ */
 void store_init();
-
+/**
+ * Store a measurement on the microSD card.
+ * @param	id			The unique random id of the reading.
+ * @param	location	The GPS location information.
+ */
 void store_reading(uint32_t id, GPSLocation location);
-
+/**
+ * Write a debug message to the debug log.
+ * @param	buffer	The message to write.
+ * @param	size	The length of the message.
+ */
 void store_debug(char* buffer, int size);
 
+/**
+ * Store a 32-bit unsigned integer to EEPROM.
+ * @param	offset	The offset in the EEPROM unit to write the value to.
+ * @param	value	The value to write.
+ */
+void store_eeprom_uint32_save(uint8_t offset, uint32_t value);
+/**
+ * Retrieve a 32-bit unsigned integer from EEPROM.
+ * @param	offset	The offset to retreive it from.
+ * @return	The value retrieved from EEPROM.
+ */
+uint32_t store_eeprom_uint32_retrieve(uint8_t offset);
+
+
 // void store_end();
diff --git a/iot/main/transmission.cpp b/iot/main/transmission.cpp
index ad32f50..8bc1aef 100644
--- a/iot/main/transmission.cpp
+++ b/iot/main/transmission.cpp
@@ -3,6 +3,7 @@
 #include <SPI.h>
 
 #include "settings.h"
+#include "storage.h"
 
 // Global static variable that's used to detect when LMIC has finished doing it's thing
 bool is_sending_complete = false;
@@ -57,6 +58,10 @@ void transmit_init() {
 
 	// Set data rate and transmit power (note: txpow seems to be ignored by the library)
 	LMIC_setDrTxpow(DR_SF7,14);
+	
+	// Restore the frame counters
+	LMIC.seqnoUp = store_eeprom_uint32_retrieve(0);
+	LMIC.seqnoDn = store_eeprom_uint32_retrieve(sizeof(uint32_t));
 }
 
 /**
@@ -67,7 +72,7 @@ void transmit_init() {
 bool transmit_send(uint8_t* data, int length) {
 	// Check if there is not a current TX/RX job running
 	if (LMIC.opmode & OP_TXRXPEND) {
-		Serial.println(F("OP_TXRXPEND: Job running, can't send"));
+		// Serial.println(F("OP_TXRXPEND: Job running, can't send"));
 		return false;
 	}
 	// Prepare upstream data transmission at the next possible time.
@@ -79,6 +84,10 @@ bool transmit_send(uint8_t* data, int length) {
 		os_runloop_once();
 	}
 	
+	// Persist the frame counters
+	store_eeprom_uint32_save(0, LMIC.seqnoUp);
+	store_eeprom_uint32_save(sizeof(uint32_t), LMIC.seqnoDn);
+	
 	// Reset it for next time (just in case)
 	is_sending_complete = false;
 	
@@ -89,7 +98,7 @@ void onEvent (ev_t ev) {
 	Serial.print(millis());
 	Serial.print(" ");
 	switch(ev) {
-		case EV_SCAN_TIMEOUT:
+		/*case EV_SCAN_TIMEOUT:
 			Serial.println(F("EV_SCAN_TIMEOUT"));
 			break;
 		case EV_BEACON_FOUND:
@@ -101,16 +110,16 @@ void onEvent (ev_t ev) {
 		case EV_BEACON_TRACKED:
 			Serial.println(F("EV_BEACON_TRACKED"));
 			break;
-		/*case EV_JOINING:
+		case EV_JOINING:
 			Serial.println(F("EV_JOINING"));
 			break;
 		case EV_JOINED:
 			Serial.println(F("EV_JOINED"));
-			break;*/
+			break;
 		case EV_RFU1:
 			Serial.println(F("EV_RFU1"));
 			break;
-		/*case EV_JOIN_FAILED:
+		case EV_JOIN_FAILED:
 			Serial.println(F("EV_JOIN_FAILED"));
 			break;
 		case EV_REJOIN_FAILED:
@@ -127,23 +136,23 @@ void onEvent (ev_t ev) {
 			// We're done!
 			is_sending_complete = true;
 			break;
-		case EV_LOST_TSYNC:
+		/*case EV_LOST_TSYNC:
 			Serial.println(F("EV_LOST_TSYNC"));
 			break;
 		case EV_RESET:
 			Serial.println(F("EV_RESET"));
-			break;
+			break;*/
 		case EV_RXCOMPLETE:
 			// data received in ping slot
 			Serial.println(F("EV_RXCOMPLETE"));
 			break;
-		case EV_LINK_DEAD:
+		/*case EV_LINK_DEAD:
 			Serial.println(F("EV_LINK_DEAD"));
 			break;
 		case EV_LINK_ALIVE:
 			Serial.println(F("EV_LINK_ALIVE"));
-			break;
-		 default:
+			break;*/
+		default:
 			Serial.println(F("Unknown event"));
 			break;
 	}
