AceTime  0.5
Date and time classes for Arduino that support timezones from the TZ Database, and a system clock that can synchronize from an NTP server or an RTC chip.
CrcEeprom.h
1 /*
2  * MIT License
3  * Copyright (c) 2018 Brian T. Park
4  */
5 
6 #ifndef ACE_TIME_HW_CRC_EEPROM_H
7 #define ACE_TIME_HW_CRC_EEPROM_H
8 
9 #if defined(ARDUINO)
10 
11 #include <EEPROM.h>
12 #include <FastCRC.h>
13 
14 #if !defined(AVR) && !defined(ESP8266) && !defined(ESP32) && \
15  !defined(TEENSYDUINO)
16  #error Unsupported board type
17 #endif
18 
19 namespace ace_time {
20 namespace hw {
21 
38 class CrcEeprom {
39  public:
40 
45 #if defined(ESP8266) || defined(ESP32)
46  void begin(uint16_t size) {
47  EEPROM.begin(size);
48  }
49 #else
50  void begin(uint16_t /*size*/) {
51  }
52 #endif
53 
57  uint16_t writeWithCrc(int address, const void* const data,
58  const uint16_t dataSize) const {
59  uint16_t byteCount = dataSize;
60  const uint8_t* d = (const uint8_t*) data;
61 
62  // write data blcok
63  while (byteCount-- > 0) {
64  write(address++, *d++);
65  }
66 
67  // write CRC at the end of the data block
68  uint32_t crc = FastCRC32().crc32((const uint8_t*) data, dataSize);
69  uint8_t buf[4];
70  memcpy(buf, &crc, 4);
71  write(address++, buf[0]);
72  write(address++, buf[1]);
73  write(address++, buf[2]);
74  write(address++, buf[3]);
75 
76  bool success = commit();
77  return (success) ? dataSize + sizeof(crc) : 0;
78  }
79 
84  bool readWithCrc(int address, void* const data,
85  const uint16_t dataSize) const {
86  uint16_t byteCount = dataSize;
87  uint8_t* d = (uint8_t*) data;
88 
89  // read data block
90  while (byteCount-- > 0) {
91  *d++ = read(address++);
92  }
93 
94  // read CRC at the end of the data block
95  uint8_t buf[4];
96  buf[0] = read(address++);
97  buf[1] = read(address++);
98  buf[2] = read(address++);
99  buf[3] = read(address++);
100  uint32_t crc;
101  memcpy(&crc, buf, 4);
102 
103  uint32_t dataCrc = FastCRC32().crc32((const uint8_t*) data, dataSize);
104  return crc == dataCrc;
105  }
106 
107  private:
108  void write(int address, uint8_t val) const {
109 #if defined(ESP8266) || defined(ESP32)
110  EEPROM.write(address, val);
111 #else
112  EEPROM.update(address, val);
113 #endif
114  }
115 
116  uint8_t read(int address) const {
117  return EEPROM.read(address);
118  }
119 
120  bool commit() const {
121 #if defined(ESP8266) || defined(ESP32)
122  return EEPROM.commit();
123 #else
124  return true;
125 #endif
126  }
127 };
128 
129 }
130 }
131 
132 #endif
133 
134 #endif