Arduino Libraries
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
adv_eeprom.hpp
Go to the documentation of this file.
1 // Author: Mario S. Könz <mskoenz@gmx.net>
2 // Date: 11.06.2013 21:14:49 EDT
3 // File: adv_eeprom.hpp
4 
5 /* This program is free software. It comes without any warranty, to
6  * the extent permitted by applicable law. You can redistribute it
7  * and/or modify it under the terms of the Do What The Fuck You Want
8  * To Public License, Version 2, as published by Sam Hocevar. See
9  * http://www.wtfpl.net/ or COPYING for more details. */
10 
11 #ifndef __ADV_EEPROM_HEADER
12 #define __ADV_EEPROM_HEADER
13 
14 //DO NOT INCLUDE THIS FILE AND eeprom.hpp AT THE SAME TIME
15 
16 #include "serializer.hpp"
17 #include "../ustd/unordered_map.hpp"
18 #include "../ustd/pair.hpp"
19 #include "../util/reset.hpp"
20 #include "../util/checksum.hpp"
21 
22 #include <EEPROM.h>
23 
24 //vmv: virtual memory vector
25 
26 namespace com {
27  class version_class {
28  public:
29  version_class(): nr_(1) {
30  }
31  version_class & operator()(uint8_t const & nr) {
32  nr_ = nr;
33  return (*this);
34  }
35  uint8_t const & operator()() const {
36  return nr_;
37  }
38  private:
39  uint8_t nr_;
40  } version;
41 
42  //=================== eeprom wrapper ===================
43  template<typename EEPROM_concept, uint16_t EEPROM_size>
45  typedef uint16_t adress_type;
46  typedef uint8_t version_type;
47  typedef typename oss_class<EEPROM_concept, EEPROM_size>::size_type size_type;
48  enum{not_corrupt = 0, corrupt = 0xFF, not_set = 2};
49  public:
50  EEPROMV2_class(EEPROM_concept & eeprom): oes_(eeprom), ies_(eeprom), current_free_(1), corrupted_(not_set) {
51  }
52  //------------------- load from eeprom and reset if corrupted-------------------
53  void reset() { //force a reset without clear
54  corrupted_ = corrupt;
55  }
56  template<typename T>
58  if(corrupted_ != corrupt and corrupted_ != not_corrupt) {
59  corrupted_ = ies_.read();
60  oes_.write(not_corrupt);
61  }
62  if(corrupted_ == corrupt) {
63  adjust_pos(t, oes_.pos());
64  oes_ & t;
65  oes_.write(util::checksum(t));
66  init_vmv(t);
67  }
68  else {
69  adjust_pos(t, ies_.pos());
70  ies_ & t;
71  if(ies_.read() != util::checksum(t)) {
72  DEBUG_MSG("eeprom is corrupted! reset and fresh init incomming")
73  oes_.pos() = 0;
74  oes_.write(corrupt);
75  util::reset();
76  }
77  }
78  return (*this);
79  }
80  //------------------- write to eeprom -------------------
81  template<typename T>
83  version_type & v = map_[adress_type(&t)].second;
84  adress_type vmv_begin = map_[adress_type(&t)].first + v * (sizeof(t) + 1);
85  ASSERT_MSG(version() < v, "eeprom version overflow");
86 
87  //translate version to hardware_version
88  ies_.pos() = vmv_begin + version();
89  version_type hw_version;
90  ies_ & hw_version;
91 
92  oes_.pos() = map_.at(adress_type(&t)).first + (sizeof(t) + 1) * hw_version;
93  version(0);
94 
95  oes_ & t;
96  oes_.write(util::checksum(t));
97  return (*this);
98  }
99  //------------------- read from eeprom -------------------
100  template<typename T>
102  version_type & v = map_[adress_type(&t)].second;
103  adress_type vmv_begin = map_[adress_type(&t)].first + v * (sizeof(t) + 1);
104  ASSERT_MSG(version() < v, "eeprom version overflow");
105 
106  //translate version to hardware_version
107  ies_.pos() = vmv_begin + version();
108  version_type hw_version;
109  ies_ & hw_version;
110 
111  ies_.pos() = map_.at(adress_type(&t)).first + (sizeof(t) + 1) * hw_version;
112  version(0);
113 
114  ies_ & t;
115  ASSERT_MSG(ies_.read() == util::checksum(t), "cannot access uninitialized version");
116 
117  return (*this);
118  }
119  //------------------- jump to the right adress -------------------
120  template<typename T>
121  void adjust_pos(T & t, size_type & pos) {
122  if(!map_.contains(adress_type(&t))) {
123  map_[adress_type(&t)].first = current_free_;
124 
125  if(version() == 0)
126  version(1);
127  map_[adress_type(&t)].second = version();
128  current_free_ += (sizeof(t) + 1) * version() + version(); //+1 for checksum / + version() for vmv
129  version(0);
130 
131  ASSERT(current_free_ < EEPROM_size);
132  pos = map_[adress_type(&t)].first;
133  }
134  else {
135  pos = map_[adress_type(&t)].first;
136  }
137  }
138  //------------------- init virtual memory vector -------------------
139  template<typename T>
140  void init_vmv(T & t) {
141  version_type & v = map_[adress_type(&t)].second;
142  oes_.pos() = map_[adress_type(&t)].first + v * (sizeof(t) + 1);
143  for(version_type i = 0; i < v; ++i) {
144  oes_ & i;
145  }
146  }
147  //------------------- delete all eeprom -------------------
148  void clear(uint8_t const & arg = 0xFF) {
149  oes_.pos() = 0;
150  for(adress_type i = 0; i < EEPROM_size; ++i) {
151  oes_ & arg;
152  }
153  oes_.pos() = 0;
154  }
155  //------------------- just so version can be concatenated -------------------
157  return (*this);
158  }
160  return (*this);
161  }
163  return (*this);
164  }
165  //------------------- swap two versions -------------------
166  template<typename T>
167  void swap_versions(T & t, version_type const & v1, version_type const & v2) {
168  version_type & v = map_[adress_type(&t)].second;
169  adress_type vmv_begin = map_[adress_type(&t)].first + v * (sizeof(t) + 1);
170 
171  ASSERT(v1 < v and v2 < v);
172 
173  version_type s1, s2;
174  ies_.pos() = vmv_begin + v1;
175  ies_ & s1;
176  ies_.pos() = vmv_begin + v2;
177  ies_ & s2;
178 
179  oes_.pos() = vmv_begin + v1;
180  oes_ & s2;
181  oes_.pos() = vmv_begin + v2;
182  oes_ & s1;
183  }
184  template<typename T>
185  void move_version_to(T & t, version_type const & v1, version_type const & v2) {
186  version_type & v = map_[adress_type(&t)].second;
187  adress_type vmv_begin = map_[adress_type(&t)].first + v * (sizeof(t) + 1);
188 
189  ASSERT(v1 < v and v2 < v);
190  version_type hw_v1, temp;
191  oes_.pos() = vmv_begin + v1;
192  ies_.pos() = vmv_begin + v1;
193 
194  ies_ & hw_v1;
195 
196  for(version_type i = v1; i < v2; ++i) {
197  ies_ & temp;
198  oes_ & temp;
199  }
200  oes_ & hw_v1;
201  }
202  template<typename T>
203  void move_version_to_end(T & t, version_type const & v1) {
204  version_type & v = map_[adress_type(&t)].second;
205  move_version_to(t, v1, v - 1);
206  }
207  private:
208  oss_class<EEPROM_concept, EEPROM_size> oes_; //out eeprom stream
210  ustd::unordered_map<adress_type, ustd::pair<adress_type, version_type>> map_; //pair<adr_in_eeprom, nr_of_versions>
211  adress_type current_free_;
212  uint8_t corrupted_;
213  };
214 
215  EEPROMV2_class<EEPROMClass, 1024> eeprom(EEPROM);
216 }//end namespace com
217 #endif //__ADV_EEPROM_HEADER
size_type & pos()
Definition: serializer.hpp:203
void clear(uint8_t const &arg=0xFF)
Definition: adv_eeprom.hpp:148
Definition: serializer.hpp:111
void move_version_to(T &t, version_type const &v1, version_type const &v2)
Definition: adv_eeprom.hpp:185
uint8_t const & operator()() const
Definition: adv_eeprom.hpp:35
EEPROMV2_class< EEPROMClass, 1024 > eeprom(EEPROM)
size_type & pos()
Definition: serializer.hpp:149
#define ASSERT_MSG(exp, msg)
Definition: ard_assert.hpp:34
EEPROMV2_class & operator&(T &t)
Definition: adv_eeprom.hpp:57
EEPROMV2_class & operator<<(T &t)
Definition: adv_eeprom.hpp:82
Definition: adv_eeprom.hpp:44
#define DEBUG_MSG(x)
Definition: ard_assert.hpp:32
EEPROMV2_class & operator<<(version_class &v)
Definition: adv_eeprom.hpp:159
EEPROMV2_class & operator>>(T &t)
Definition: adv_eeprom.hpp:101
version_class()
Definition: adv_eeprom.hpp:29
void reset()
Definition: reset.hpp:15
void swap_versions(T &t, version_type const &v1, version_type const &v2)
Definition: adv_eeprom.hpp:167
class com::version_class version
Definition: unordered_map.hpp:20
bool contains(K const &key) const
Definition: unordered_map.hpp:64
void move_version_to_end(T &t, version_type const &v1)
Definition: adv_eeprom.hpp:203
void reset()
Definition: adv_eeprom.hpp:53
V & at(K const &key)
Definition: unordered_map.hpp:53
EEPROMV2_class & operator>>(version_class &v)
Definition: adv_eeprom.hpp:162
void write(uint8_t const &in)
Definition: serializer.hpp:144
void adjust_pos(T &t, size_type &pos)
Definition: adv_eeprom.hpp:121
uint8_t checksum(T const &t)
Definition: checksum.hpp:17
void init_vmv(T &t)
Definition: adv_eeprom.hpp:140
EEPROMV2_class & operator&(version_class &v)
Definition: adv_eeprom.hpp:156
Definition: adv_eeprom.hpp:27
#define ASSERT(exp)
Definition: ard_assert.hpp:33
first_type first
Definition: pair.hpp:27
version_class & operator()(uint8_t const &nr)
Definition: adv_eeprom.hpp:31
EEPROMV2_class(EEPROM_concept &eeprom)
Definition: adv_eeprom.hpp:50
uint8_t read()
Definition: serializer.hpp:199