|
- // Copyright 2012 Olivier Gillet.
- //
- // Author: Olivier Gillet (ol.gillet@gmail.com)
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- #ifndef EDGES_STORAGE_H_
- #define EDGES_STORAGE_H_
-
- #include <avr/pgmspace.h>
-
- #include "avrlibx/avrlibx.h"
- #include "avrlibx/third_party/eeprom_driver/eeprom_driver.h"
-
- namespace edges {
-
- template<typename T>
- struct StorageLayout {
- // Crash-guard: these templates must be specialized.
- static uint16_t eeprom_address() { while(1); }
- static const prog_char* init_data() { while(1); }
- };
-
- class Storage {
- public:
- template<typename T>
- static void Save(const T& data) {
- Save(&data, StorageLayout<T>::eeprom_address(), sizeof(T));
- };
-
- template<typename T>
- static void Load(T* data) {
- Load(
- data,
- StorageLayout<T>::eeprom_address(),
- static_cast<uint16_t>(sizeof(T)),
- StorageLayout<T>::init_data(),
- false);
- };
-
- template<typename T>
- static void ResetToFactoryDefaults(T* data) {
- Load(
- data,
- StorageLayout<T>::eeprom_address(),
- static_cast<uint16_t>(sizeof(T)),
- StorageLayout<T>::init_data(),
- true);
- Save(*data);
- };
-
- static void Save(const void* data, uint16_t address, uint16_t size) {
- uint8_t checksum = Checksum(data, size);
- EEPROM_write_block(address, static_cast<const uint8_t*>(data), size);
- EEPROM_write_byte(address + size, checksum);
- };
-
- static void Load(
- void* data,
- uint16_t address,
- uint16_t size,
- const prog_char* default_data,
- bool force_reinitialization) {
- EEPROM_read_block(address, static_cast<uint8_t*>(data), size);
- uint16_t checksum = EEPROM_read_byte(address + size);
- if (checksum != Checksum(data, size) || force_reinitialization) {
- memcpy_P(data, default_data, size);
- }
- };
-
- private:
- static uint8_t Checksum(const void* data, uint16_t size) {
- uint8_t s = 0;
- const uint8_t* d = static_cast<const uint8_t*>(data);
- while (size--) {
- s += *d++;
- }
- return s;
- }
- };
-
- extern Storage storage;
-
- }; // namespace edges
-
- #endif // EDGES_STORAGE_H_
|