-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathe_Eeprom.ino
290 lines (289 loc) · 7.27 KB
/
e_Eeprom.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/**
* This file contains functions to write, read and delete
* callerIds from eeprom.
* The callerIds are stored randomly in eeprom
* to create a basic wear-leveling algorithm.
*/
/*
* Only compile this file
* if the eeprom-functions are being tested
* or the main-program is being run.
*/
#if ((TEST == TEST_EEPROM) || (!TEST))
/*
* Generate a file specific warning during compilation,
* so that it is possible to identify
* which files are being compiled.
*/
#warning Eeprom
/*
* Needed for eeprom-storage.
*/
#include <EEPROM.h>
/*
* The type which is used
* to read and write data to eeprom.
*/
#define eeprom_t uint8_t
/*
* The size of the array which is used
* to read and write eeprom. 8 / 1 = 8.
*/
#define EEPROM_ARRAY_SIZE sizeof(callerid_t) / sizeof(eeprom_t)
/*
* The size of the eeprom-type in bits.
* This is used by the bitshifting-process
* used by reading and writing to eeprom.
*/
#define EEPROM_SIZE_IN_BITS sizeof(eeprom_t) * 8
/*
* The maximum number of callerIds
* that can be stored in eeprom.
*/
#define EEPROM_MAX_POSITION (E2END + 1) / EEPROM_ARRAY_SIZE
/**
* Determines if a given callerId is a valid callerId.
* 0 (for not having a callerId) and ~0 (for unwritten eeprom)
* are invalid callerIds.
* @param cid the callerId to be checked
* @return true if it is a valid callerId,
* false if it is not a valid callerId.
*/
boolean isValidCallerId(const callerid_t cid)
{
return (cid != 0) && (cid != (~(callerid_t) 0));
}
/**
* Store a given callerId in eeprom.
* @param cid the callerId to be stored.
* @return true if the callerId is successfully stored,
* false if the callerId is invalid,
* false if the callerId is already stored,
* false if there is no eeprom available.
*/
boolean storeCallerIdInEeprom(const callerid_t cid)
{
boolean stored = false;
if (isValidCallerId(cid) && !isCallerIdInEeprom(cid))
{
uint16_t pos = getAvailableEepromPosition();
if (isValidEepromPosition(pos))
{
stored = writeCallerIdToEeprom(pos, cid);
}
}
return stored;
}
/**
* Determines if a callerId is stored in eeprom.
* @return true if the callerId is stored in eeprom,
* false if the callerId is invalid,
* false if the callerId is not stored in eeprom.
*/
boolean isCallerIdInEeprom(const callerid_t cid)
{
boolean found = false;
if (isValidCallerId(cid))
{
for(uint16_t pos = 0; (pos < EEPROM_MAX_POSITION) && !found; pos++)
{
if (readCallerIdFromEeprom(pos) == cid)
{
found = true;
}
}
}
return found;
}
/**
* Remove a given callerId from eeprom.
* @param cid the callerId to be removed.
* @return true if the callerId is successfully removed,
* false if the callerId is invalid,
* false if the callerId was not stored in eeprom.
*/
boolean removeCallerIdFromEeprom(const callerid_t cid)
{
boolean removed = false;
if (isValidCallerId(cid) && isCallerIdInEeprom(cid))
{
for(uint16_t pos = 0; pos < EEPROM_MAX_POSITION; pos++)
{
if (readCallerIdFromEeprom(pos) == cid)
{
/*
* Fill the current eepromPosition with 1's
* because that is the default state for
* uninitialised eeprom.
*/
removed = writeCallerIdToEeprom(pos, ~0);
}
}
}
return removed;
}
/**
* Returns how much callerIds are stored in eeprom.
* @return the number of callerIds stored in eeprom.
*/
uint16_t getNumberOfCallerIdsInEeprom()
{
uint16_t numberOfCallerIds = 0;
for(uint16_t pos = 0; pos < EEPROM_MAX_POSITION; pos++)
{
if (isValidCallerId(readCallerIdFromEeprom(pos)))
{
numberOfCallerIds++;
}
}
return numberOfCallerIds;
}
/**
* Print all callerIds in eeprom to serial.
*/
void showAllCallerIdsInEeprom()
{
for(uint16_t pos = 0; pos < EEPROM_MAX_POSITION; pos++)
{
callerid_t cid = readCallerIdFromEeprom(pos);
if (isValidCallerId(cid))
{
printCallerId(cid);
}
}
}
/**
* Clears eeprom.
* This function is kept simple
* and independant from other functions
* on purpose.
*/
void clearEeprom()
{
for(uint16_t i = 0; i <= E2END; i++)
{
/*
* Write ~0 (0xFF) to eeprom
* because that is the default value.
*/
EEPROM.write(i, ~0);
}
}
/**
* Determines if an eepromPosition is a valid one.
* @param eepromPosition the eepromPosition.
* @return true if it is a valid eepromPosition, false otherwise.
*/
boolean isValidEepromPosition(const uint16_t eepromPosition)
{
return (eepromPosition >= 0) && (eepromPosition < EEPROM_MAX_POSITION);
}
/**
* Read a callerId from eeprom.
* @param eepromPosition the position at which the callerId begins.
* @return the callerId at the given eepromPosition.
*/
callerid_t readCallerIdFromEeprom(const uint16_t eepromPosition)
{
callerid_t cid = 0;
if (isValidEepromPosition(eepromPosition))
{
/*
* Read the bytes located on eepromPosition
* which represent the callerId and put these into an array.
*/
eeprom_t eepromArray[EEPROM_ARRAY_SIZE];
uint16_t beginEepromAddress = eepromPosition * EEPROM_ARRAY_SIZE;
for(uint16_t i = 0; i < EEPROM_ARRAY_SIZE; i++)
{
eepromArray[i] = EEPROM.read(beginEepromAddress + i);
}
/*
* Convert the array to a callerId using bitshifting.
*/
for(uint16_t i = 0; i < EEPROM_ARRAY_SIZE; i++)
{
cid = cid | ((callerid_t) eepromArray[i]) << (EEPROM_SIZE_IN_BITS * i);
}
}
return cid;
}
/**
* Write a callerId to eeprom.
* @param eepromPosition the position at which the callerId begins.
* @param cid the callerId to be written.
* @return true if the writing succeeded, false otherwise.
*/
boolean writeCallerIdToEeprom(const uint16_t eepromPosition, const callerid_t cid)
{
boolean written = false;
if (isValidEepromPosition(eepromPosition))
{
/*
* Convert the callerId to an array using bitshitfing.
*/
eeprom_t eepromArray[EEPROM_ARRAY_SIZE];
for(uint16_t i = 0; i < EEPROM_ARRAY_SIZE; i++)
{
eepromArray[i] = (eeprom_t) (cid >> (EEPROM_SIZE_IN_BITS * i));
}
/*
* Write the array to eeprom.
*/
uint16_t beginEepromAddress = eepromPosition * EEPROM_ARRAY_SIZE;
for(uint16_t i = 0; i < EEPROM_ARRAY_SIZE; i++)
{
/*
* Only write to the eeprom if the value which is to be written
* is different from the value which is already there.
*/
if (EEPROM.read(beginEepromAddress + i) != eepromArray[i])
{
EEPROM.write(beginEepromAddress + i, eepromArray[i]);
}
}
written = true;
}
return written;
}
/**
* Get a random available eepromPosition.
* @return an available eepromPosition
* or EEPROM_MAX_POSITION if there is
* no eepromPosition available.
*/
uint16_t getAvailableEepromPosition()
{
uint16_t pos = getAvailableEepromPosition(random(0, EEPROM_MAX_POSITION));
if (!isValidEepromPosition(pos))
{
pos = getAvailableEepromPosition(0);
}
return pos;
}
/**
* Get the first eepromPosition available
* starting from startEepromPosition.
* @param startEepromPosition the eepromPosition
* which will be the start for the search
* for an available eepromPosition.
* @return an available eepromPosition
* or EEPROM_MAX_POSITION if there is
* no eepromPosition available.
*/
uint16_t getAvailableEepromPosition(const uint16_t startEepromPosition)
{
uint16_t pos = EEPROM_MAX_POSITION;
if (isValidEepromPosition(startEepromPosition))
{
for(uint16_t p = startEepromPosition; (p < EEPROM_MAX_POSITION) && !isValidEepromPosition(pos); p++)
{
if (!isValidCallerId(readCallerIdFromEeprom(p)))
{
pos = p;
}
}
}
return pos;
}
#endif