RSeries astromech firmware
PersistentStorage.h
Go to the documentation of this file.
1 #ifndef PERSISTENT_STORAGE_H
2 #define PERSISTENT_STORAGE_H
3 
4 #if defined(__SAMD21G18A__)
5 #include <FlashAsEEPROM.h>
6 #else
7 #include <EEPROM.h>
8 #endif
9 
11 class PersistentStorage
12 {
13 public:
14  static unsigned reserveSpace(unsigned numBytes)
15  {
16  static unsigned sSize;
17  unsigned offset = sSize;
18  if (sSize + numBytes >= EEPROM.length())
19  return ~0;
20  sSize += numBytes;
21  return offset;
22  }
23 };
24 
34 template <typename T, uint16_t kSignature>
35 class Persistent : protected PersistentStorage
36 {
37 public:
39  {
40  fByteIndex = PersistentStorage::reserveSpace(sizeof(T) + sizeof(uint16_t));
41  }
42 
43  constexpr uint16_t signature()
44  {
45  return kSignature + (sizeof(T) + sizeof(uint16_t));
46  }
47 
48  bool isValid()
49  {
50  return (fByteIndex != ~0 && readSignature() == signature());
51  }
52 
53  T &get( T &t )
54  {
55  uint8_t *dst = (uint8_t*) &t;
56  if (isValid())
57  {
58  DEBUG_PRINT(F("Loaded: "));
60  // Signature is valid return data from EEPROM
61  uint8_t index = fByteIndex + sizeof(uint16_t);
62  for (unsigned count = sizeof(T); count; count--)
63  *dst++ = EEPROM.read(index++);
64  }
65  else
66  {
67  DEBUG_PRINT(F("INVALID: "));
69  // Signature is invalid return 0 data
70  memset(dst, '\0', sizeof(T));
71  }
72  return t;
73  }
74 
75  const T &put(const T &t)
76  {
77  bool needsCommit = false;
78  if (fByteIndex == ~0)
79  {
80  /* Insufficent space */
81  return t;
82  }
83  // Update the signature if necessary
84  uint8_t index = fByteIndex;
85  uint8_t hisig = (signature() >> 8);
86  uint8_t losig = (signature() & 0xFF);
87  if (EEPROM.read(index) != hisig)
88  {
89  EEPROM.write(index, hisig);
90  needsCommit = true;
91  }
92  index++;
93  if (EEPROM.read(index) != losig)
94  {
95  EEPROM.write(index, losig);
96  needsCommit = true;
97  }
98  index++;
99  // Update the data if necessary
100  const uint8_t *ptr = (const uint8_t*) &t;
101  for (int count = sizeof(T); count; count--, index++, ptr++)
102  {
103  if (EEPROM.read(index) != *ptr)
104  {
105  EEPROM.write(index, *ptr);
106  needsCommit = true;
107  }
108  }
109  // Flash based devices need a call to commit()
110  if (needsCommit)
111  {
112  DEBUG_PRINT(F("Saved: "));
114  }
115  #ifdef EEPROM_EMULATION_SIZE
116  if (needsCommit)
117  {
118  DEBUG_PRINT(F("Saved: "));
120  EEPROM.commit();
121  }
122  #endif
123  return t;
124  }
125 
126 private:
127  uint16_t readSignature()
128  {
129  return ((uint16_t(EEPROM.read(fByteIndex)) << 8) | (EEPROM.read(fByteIndex+1)));
130  }
131 
132  unsigned fByteIndex;
133 };
134 
135 #define PERSIST(T) Persistent<T,WSID16(#T)>
136 
137 #endif
DEBUG_PRINT
#define DEBUG_PRINT(s)
Definition: ReelTwo.h:189
DEBUG_PRINTLN
#define DEBUG_PRINTLN(s)
Definition: ReelTwo.h:188
Persistent::put
const T & put(const T &t)
Definition: PersistentStorage.h:75
Persistent::Persistent
Persistent()
Definition: PersistentStorage.h:38
Persistent::isValid
bool isValid()
Definition: PersistentStorage.h:48
TYPETOSTR
#define TYPETOSTR(T)
Definition: ReelTwo.h:196
Persistent
Template manages persistance of specific type.
Definition: PersistentStorage.h:35
Persistent::get
T & get(T &t)
Definition: PersistentStorage.h:53
Persistent::signature
constexpr uint16_t signature()
Definition: PersistentStorage.h:43