4 #define MIN(a,b) ((a) < (b) ? (a) : (b))
9 #include <avr/pgmspace.h>
10 #include <avr/eeprom.h>
14 #ifndef SETTINGS_TOP_ADDR
15 #define SETTINGS_TOP_ADDR (E2END-4)
18 #ifndef SETTINGS_MAX_SIZE
19 #define SETTINGS_MAX_SIZE (1024)
33 settings_is_item_valid_(eeprom_addr_t item_addr) {
34 item_header_t header = {};
36 if(item_addr==EEPROM_NULL)
43 item_addr+1-
sizeof(header),
44 (
unsigned char*)&header,
48 if((uint8_t)header.size_check!=(uint8_t)~header.size_low)
56 inline static settings_key_t
57 settings_get_key_(eeprom_addr_t item_addr) {
61 item_addr+1-
sizeof(header),
62 (
unsigned char*)&header,
66 if((uint8_t)header.size_check!=(uint8_t)~header.size_low)
67 return SETTINGS_INVALID_KEY;
73 settings_get_value_length_(eeprom_addr_t item_addr) {
78 item_addr+1-
sizeof(header),
79 (
unsigned char*)&header,
83 if((uint8_t)header.size_check!=(uint8_t)~header.size_low)
86 ret = header.size_low;
89 ret = ((ret&~(1<<7))<<8) | header.size_extra;
96 inline static eeprom_addr_t
97 settings_get_value_addr_(eeprom_addr_t item_addr) {
98 size_t len = settings_get_value_length_(item_addr);
101 return item_addr+1-
sizeof(item_header_t)-len;
103 return item_addr+1-
sizeof(item_header_t)+1-len;
106 inline static eeprom_addr_t
107 settings_next_item_(eeprom_addr_t item_addr) {
108 return settings_get_value_addr_(item_addr)-1;
116 settings_check(settings_key_t key,uint8_t index) {
118 eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
120 for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) {
121 if(settings_get_key_(current_item)==key) {
136 settings_get(settings_key_t key,uint8_t index,
unsigned char* value,
size_t* value_size) {
137 settings_status_t ret = SETTINGS_STATUS_NOT_FOUND;
138 eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
140 for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) {
141 if(settings_get_key_(current_item)==key) {
144 *value_size = MIN(*value_size,settings_get_value_length_(current_item));
146 settings_get_value_addr_(current_item),
150 ret = SETTINGS_STATUS_OK;
163 settings_add(settings_key_t key,
const unsigned char* value,
size_t value_size) {
164 settings_status_t ret = SETTINGS_STATUS_FAILURE;
165 eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
166 item_header_t header;
169 for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item));
171 if(current_item==EEPROM_NULL)
178 if(value_size<0x80) {
182 header.size_low = value_size;
183 }
else if(value_size<=SETTINGS_MAX_VALUE_SIZE) {
190 header.size_low = (value_size>>7) | 0x80;
191 header.size_extra = value_size & ~0x80;
197 header.size_check = ~header.size_low;
201 current_item+1-
sizeof(header),
202 (
unsigned char*)&header,
207 if(settings_get_value_length_(current_item)!=value_size) {
213 settings_get_value_addr_(current_item),
214 (
unsigned char*)value,
218 ret = SETTINGS_STATUS_OK;
225 settings_set(settings_key_t key,
const unsigned char* value,
size_t value_size) {
226 settings_status_t ret = SETTINGS_STATUS_FAILURE;
227 eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
229 for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) {
230 if(settings_get_key_(current_item)==key) {
235 if((current_item==EEPROM_NULL) || !settings_is_item_valid_(current_item)) {
236 ret = settings_add(key,value,value_size);
240 if(value_size!=settings_get_value_length_(current_item)) {
247 settings_get_value_addr_(current_item),
248 (
unsigned char*)value,
252 ret = SETTINGS_STATUS_OK;
259 settings_delete(settings_key_t key,uint8_t index) {
262 return SETTINGS_STATUS_UNIMPLEMENTED;
267 settings_wipe(
void) {
268 size_t i = SETTINGS_TOP_ADDR-SETTINGS_MAX_SIZE;
269 for(;i<=SETTINGS_TOP_ADDR;i++) {
270 eeprom_write_byte((uint8_t*)i,0xFF);