You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.6KB

  1. // Copyright 2012 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. #ifndef EDGES_STORAGE_H_
  16. #define EDGES_STORAGE_H_
  17. #include <avr/pgmspace.h>
  18. #include "avrlibx/avrlibx.h"
  19. #include "avrlibx/third_party/eeprom_driver/eeprom_driver.h"
  20. namespace edges {
  21. template<typename T>
  22. struct StorageLayout {
  23. // Crash-guard: these templates must be specialized.
  24. static uint16_t eeprom_address() { while(1); }
  25. static const prog_char* init_data() { while(1); }
  26. };
  27. class Storage {
  28. public:
  29. template<typename T>
  30. static void Save(const T& data) {
  31. Save(&data, StorageLayout<T>::eeprom_address(), sizeof(T));
  32. };
  33. template<typename T>
  34. static void Load(T* data) {
  35. Load(
  36. data,
  37. StorageLayout<T>::eeprom_address(),
  38. static_cast<uint16_t>(sizeof(T)),
  39. StorageLayout<T>::init_data(),
  40. false);
  41. };
  42. template<typename T>
  43. static void ResetToFactoryDefaults(T* data) {
  44. Load(
  45. data,
  46. StorageLayout<T>::eeprom_address(),
  47. static_cast<uint16_t>(sizeof(T)),
  48. StorageLayout<T>::init_data(),
  49. true);
  50. Save(*data);
  51. };
  52. static void Save(const void* data, uint16_t address, uint16_t size) {
  53. uint8_t checksum = Checksum(data, size);
  54. EEPROM_write_block(address, static_cast<const uint8_t*>(data), size);
  55. EEPROM_write_byte(address + size, checksum);
  56. };
  57. static void Load(
  58. void* data,
  59. uint16_t address,
  60. uint16_t size,
  61. const prog_char* default_data,
  62. bool force_reinitialization) {
  63. EEPROM_read_block(address, static_cast<uint8_t*>(data), size);
  64. uint16_t checksum = EEPROM_read_byte(address + size);
  65. if (checksum != Checksum(data, size) || force_reinitialization) {
  66. memcpy_P(data, default_data, size);
  67. }
  68. };
  69. private:
  70. static uint8_t Checksum(const void* data, uint16_t size) {
  71. uint8_t s = 0;
  72. const uint8_t* d = static_cast<const uint8_t*>(data);
  73. while (size--) {
  74. s += *d++;
  75. }
  76. return s;
  77. }
  78. };
  79. extern Storage storage;
  80. }; // namespace edges
  81. #endif // EDGES_STORAGE_H_