AceTime  0.1
Date and time classes for Arduino that supports the TZ DAtabase, and a system clock synchronized from an NTP server or an RTC chip.
CrcEeprom.h
1 #ifndef ACE_TIME_HW_CRC_EEPROM_H
2 #define ACE_TIME_HW_CRC_EEPROM_H
3 
4 #if defined(ARDUINO)
5 
6 #include <EEPROM.h>
7 #include <FastCRC.h>
8 
9 #if !defined(AVR) && !defined(ESP8266) && !defined(ESP32) && \
10  !defined(TEENSYDUINO)
11  #error Unsupported board type
12 #endif
13 
14 namespace ace_time {
15 namespace hw {
16 
33 class CrcEeprom {
34  public:
35 
40 #if defined(ESP8266) || defined(ESP32)
41  void begin(uint16_t size) {
42  EEPROM.begin(size);
43  }
44 #else
45  void begin(uint16_t /*size*/) {
46  }
47 #endif
48 
52  uint16_t writeWithCrc(int address, const void* const data,
53  const uint16_t dataSize) const {
54  uint16_t byteCount = dataSize;
55  const uint8_t* d = (const uint8_t*) data;
56 
57  // write data blcok
58  while (byteCount-- > 0) {
59  write(address++, *d++);
60  }
61 
62  // write CRC at the end of the data block
63  uint32_t crc = FastCRC32().crc32((const uint8_t*) data, dataSize);
64  uint8_t buf[4];
65  memcpy(buf, &crc, 4);
66  write(address++, buf[0]);
67  write(address++, buf[1]);
68  write(address++, buf[2]);
69  write(address++, buf[3]);
70 
71  bool success = commit();
72  return (success) ? dataSize + sizeof(crc) : 0;
73  }
74 
79  bool readWithCrc(int address, void* const data,
80  const uint16_t dataSize) const {
81  uint16_t byteCount = dataSize;
82  uint8_t* d = (uint8_t*) data;
83 
84  // read data block
85  while (byteCount-- > 0) {
86  *d++ = read(address++);
87  }
88 
89  // read CRC at the end of the data block
90  uint8_t buf[4];
91  buf[0] = read(address++);
92  buf[1] = read(address++);
93  buf[2] = read(address++);
94  buf[3] = read(address++);
95  uint32_t crc;
96  memcpy(&crc, buf, 4);
97 
98  uint32_t dataCrc = FastCRC32().crc32((const uint8_t*) data, dataSize);
99  return crc == dataCrc;
100  }
101 
102  private:
103  void write(int address, uint8_t val) const {
104 #if defined(ESP8266) || defined(ESP32)
105  EEPROM.write(address, val);
106 #else
107  EEPROM.update(address, val);
108 #endif
109  }
110 
111  uint8_t read(int address) const {
112  return EEPROM.read(address);
113  }
114 
115  bool commit() const {
116 #if defined(ESP8266) || defined(ESP32)
117  return EEPROM.commit();
118 #else
119  return true;
120 #endif
121  }
122 };
123 
124 }
125 }
126 
127 #endif
128 
129 #endif