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
|
/*
* Xytronic LF-1600
* Settings handling
*
* Copyright (c) 2015 Michael Buesch <m@bues.ch>
*
* 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 2 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "settings.h"
#include "util.h"
#include "timer.h"
#include <string.h>
#include <avr/eeprom.h>
static struct timer settings_timer;
static bool settings_store_request;
static uint8_t settings_ee_index;
static struct settings settings_cache;
/* The permanent EEPROM storage. */
#define NR_EE_SETTINGS ((E2END + 1) / sizeof(struct settings))
static struct settings EEMEM ee_settings[NR_EE_SETTINGS] = {
[0 ... NR_EE_SETTINGS - 1] = {
.temp_setpoint = FLOAT_TO_FIXPT(330.0),
.serial = 0,
},
};
struct settings * get_settings(void)
{
return &settings_cache;
}
void store_settings(void)
{
settings_store_request = true;
timer_arm(&settings_timer, 1000);
}
void settings_work(void)
{
uint8_t index;
if (!settings_store_request)
return;
if (!timer_expired(&settings_timer))
return;
settings_store_request = false;
/* Increment the serial number. This might wrap. */
settings_cache.serial = (uint8_t)(settings_cache.serial + 1u);
/* Get the store index. */
index = settings_ee_index;
index = (uint8_t)(index + 1u);
if (index >= ARRAY_SIZE(ee_settings))
index = 0;
settings_ee_index = index;
/* Store the settings in eeprom. */
eeprom_update_block_wdtsafe(&settings_cache,
&ee_settings[index],
sizeof(settings_cache));
}
void settings_init(void)
{
uint8_t next_index, found_index;
uint8_t serial, next_serial;
/* Find the latest settings in the eeprom.
* The latest setting is the one with the largest
* index. However, wrap around must be considered. */
serial = eeprom_read_byte(&ee_settings[0].serial);
next_index = 0;
do {
found_index = next_index;
next_index = (uint8_t)(next_index + 1u);
if (next_index >= ARRAY_SIZE(ee_settings))
next_index = 0u;
next_serial = eeprom_read_byte(&ee_settings[next_index].serial);
if (next_serial != ((serial + 1u) & 0xFFu))
break;
serial = next_serial;
} while (next_index != 0);
settings_ee_index = found_index;
/* Read it from eeprom. */
eeprom_read_block_wdtsafe(&settings_cache,
&ee_settings[found_index],
sizeof(settings_cache));
}
|