]> git.zerfleddert.de Git - fnordlicht-mini/blob - firmware/fnordlicht-firmware/storage.c
0ad522d9594ee6d969642896757828e12646721a
[fnordlicht-mini] / firmware / fnordlicht-firmware / storage.c
1 /* vim:ts=4 sts=4 et tw=80
2 *
3 * fnordlicht firmware
4 *
5 * for additional information please
6 * see http://lochraster.org/fnordlichtmini
7 *
8 * (c) by Alexander Neumann <alexander@bumpern.de>
9 *
10 * This program is free software: you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 3 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "storage.h"
24 #include "remote.h"
25 #include "../common/pt/pt.h"
26 #include <avr/eeprom.h>
27 #include <util/crc16.h>
28 #include <string.h>
29
30 /* global structures */
31 struct storage_config_t startup_config;
32 EEMEM struct storage_t eeprom_storage =
33 {
34 /* struct storage_config_t config */
35 {
36 /* uint8_t magic */
37 EEPROM_MAGIC_BYTE,
38 /* uint8_t startup_addr */
39 1u,
40 /* struct startup_parameters_t params */
41 {
42 /* enum startup_mode_t mode */
43 STARTUP_PROGRAM,
44 {
45 /* uint8_t program */
46 CONFIG_SCRIPT_DEFAULT, /* FIXME expected to be 0 atm */
47 /* uint8_t program_parameters[PROGRAM_PARAMETER_SIZE] */
48 /* FIXME: hardcoded parameters for colorwheel */
49 1u, 2u, 0, 0, 0, 0, 60u, 0, 255u, 255u
50 }
51 }
52 },
53 /* struct storage_color_t color[CONFIG_EEPROM_COLORS] */
54 {
55 0u,
56 },
57 /* uint16_t checksum */
58 0x2323u /* FIXME */
59 };
60
61 /* internal state */
62 struct storage_internal_t
63 {
64 bool eeprom_good;
65
66 /* buffer for nonblocking read/write */
67 uint8_t buf[STORAGE_BUFFER_SIZE];
68 uint8_t index;
69 uint8_t *address;
70 uint8_t bytes_remaining;
71 struct pt thread;
72
73 enum {
74 STORAGE_IDLE = 0,
75 STORAGE_WRITE = 1,
76 } state;
77 };
78
79 static struct storage_internal_t storage;
80
81 static uint16_t eeprom_checksum(void)
82 {
83 uint16_t checksum = 0;
84 uint8_t *start = NULL;
85
86 for (uint16_t i = 0; i < sizeof(struct storage_t)-2; i++)
87 checksum = _crc16_update(checksum, eeprom_read_byte(start++));
88
89 return checksum;
90 }
91
92 void storage_init(void)
93 {
94 /* compare checksum and eeprom configuration content */
95 uint16_t checksum1 = eeprom_checksum();
96 uint16_t checksum2 = eeprom_read_word(&eeprom_storage.checksum);
97 storage.eeprom_good = (checksum1 == checksum2);
98 storage_load_config();
99
100 #ifdef INIT_ZERO
101 /* initialize state structure */
102 storage.state = STORAGE_IDLE;
103 PT_INIT(&storage.thread);
104 #endif
105 }
106
107 static PT_THREAD(storage_thread(struct pt *thread))
108 {
109 PT_BEGIN(thread);
110
111 while (1) {
112 if (storage.state == STORAGE_WRITE) {
113 /* pull int line */
114 remote_pull_int();
115
116 /* write data */
117 while (storage.bytes_remaining--) {
118 eeprom_write_byte(storage.address++, storage.buf[storage.index++]);
119
120 while (!eeprom_is_ready())
121 PT_YIELD(thread);
122 }
123
124 /* update checksum */
125 eeprom_write_word(&eeprom_storage.checksum, eeprom_checksum());
126 while (!eeprom_is_ready())
127 PT_YIELD(thread);
128
129 /* release int line */
130 remote_release_int();
131
132 storage.state = STORAGE_IDLE;
133 }
134
135 PT_YIELD(thread);
136 }
137
138 PT_END(thread);
139 }
140
141 void storage_poll(void)
142 {
143 /* call storage thread */
144 if (storage.state != STORAGE_IDLE)
145 PT_SCHEDULE(storage_thread(&storage.thread));
146 }
147
148 void storage_save_config(void)
149 {
150 if (storage.state != STORAGE_IDLE)
151 return;
152
153 /* set magic byte and save startup_config to EEPROM */
154 startup_config.magic = EEPROM_MAGIC_BYTE;
155
156 /* copy data to buffer */
157 memcpy(&storage.buf[0], &startup_config, sizeof(struct storage_config_t));
158 /* set address and bytes_remaining */
159 storage.index = 0;
160 storage.bytes_remaining = sizeof(struct storage_config_t);
161 storage.address = (uint8_t *)&eeprom_storage.config;
162 /* start write */
163 storage.state = STORAGE_WRITE;
164
165 /* reset magic config and mark EEPROM as good */
166 startup_config.magic = 0;
167 storage.eeprom_good = true;
168 }
169
170 void storage_load_config(void)
171 {
172 if (!storage.eeprom_good)
173 return;
174
175 /* load config */
176 eeprom_read_block(&startup_config, &eeprom_storage.config, sizeof(struct storage_config_t));
177 }
178
179 void storage_save_color(uint8_t position, struct storage_color_t *color)
180 {
181 if (storage.state != STORAGE_IDLE)
182 return;
183
184 /* copy data to buffer */
185 memcpy(&storage.buf[0], color, sizeof(struct storage_color_t));
186 /* set address and bytes_remaining */
187 storage.index = 0;
188 storage.bytes_remaining = sizeof(struct storage_color_t);
189 storage.address = (uint8_t *)&eeprom_storage.color[position];
190 /* start write */
191 storage.state = STORAGE_WRITE;
192 }
193
194 void storage_load_color(uint8_t position, struct storage_color_t *color)
195 {
196 eeprom_read_block(color, &eeprom_storage.color[position], sizeof(struct storage_color_t));
197 }
198
199 bool storage_valid_config(void)
200 {
201 return (storage.eeprom_good && startup_config.magic == EEPROM_MAGIC_BYTE);
202 }
Impressum, Datenschutz