]> git.zerfleddert.de Git - fnordlicht-mini/blob - firmware/fnordlicht-firmware/storage.c
637ad699edbfc8304460394b5ad8b672adcd1710
[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 /* internal state */
35 struct storage_internal_t
36 {
37 bool eeprom_good;
38
39 /* buffer for nonblocking read/write */
40 uint8_t buf[STORAGE_BUFFER_SIZE];
41 uint8_t index;
42 uint8_t *address;
43 uint8_t bytes_remaining;
44 struct pt thread;
45
46 enum {
47 STORAGE_IDLE = 0,
48 STORAGE_WRITE = 1,
49 } state;
50 };
51
52 static struct storage_internal_t storage;
53
54 static uint16_t eeprom_checksum(void)
55 {
56 uint16_t checksum = 0;
57 uint8_t *start = NULL;
58
59 for (uint16_t i = 0; i < sizeof(struct storage_t)-2; i++)
60 checksum = _crc16_update(checksum, eeprom_read_byte(start++));
61
62 return checksum;
63 }
64
65 void storage_init(void)
66 {
67 /* compare checksum and eeprom configuration content */
68 uint16_t checksum1 = eeprom_checksum();
69 uint16_t checksum2 = eeprom_read_word(&eeprom_storage.checksum);
70 storage.eeprom_good = (checksum1 == checksum2);
71 storage_load_config();
72
73 #ifdef INIT_ZERO
74 /* initialize state structure */
75 storage.state = STORAGE_IDLE;
76 PT_INIT(&storage.thread);
77 #endif
78 }
79
80 static PT_THREAD(storage_thread(struct pt *thread))
81 {
82 PT_BEGIN(thread);
83
84 while (1) {
85 if (storage.state == STORAGE_WRITE) {
86 /* pull int line */
87 remote_pull_int();
88
89 /* write data */
90 while (storage.bytes_remaining--) {
91 eeprom_write_byte(storage.address++, storage.buf[storage.index++]);
92
93 while (!eeprom_is_ready())
94 PT_YIELD(thread);
95 }
96
97 /* update checksum */
98 eeprom_write_word(&eeprom_storage.checksum, eeprom_checksum());
99 while (!eeprom_is_ready())
100 PT_YIELD(thread);
101
102 /* release int line */
103 remote_release_int();
104
105 storage.state = STORAGE_IDLE;
106 }
107
108 PT_YIELD(thread);
109 }
110
111 PT_END(thread);
112 }
113
114 void storage_poll(void)
115 {
116 /* call storage thread */
117 if (storage.state != STORAGE_IDLE)
118 PT_SCHEDULE(storage_thread(&storage.thread));
119 }
120
121 void storage_save_config(void)
122 {
123 if (storage.state != STORAGE_IDLE)
124 return;
125
126 /* set magic byte and save startup_config to EEPROM */
127 startup_config.magic = EEPROM_MAGIC_BYTE;
128
129 /* copy data to buffer */
130 memcpy(&storage.buf[0], &startup_config, sizeof(struct storage_config_t));
131 /* set address and bytes_remaining */
132 storage.index = 0;
133 storage.bytes_remaining = sizeof(struct storage_config_t);
134 storage.address = (uint8_t *)&eeprom_storage.config;
135 /* start write */
136 storage.state = STORAGE_WRITE;
137
138 /* reset magic config and mark EEPROM as good */
139 startup_config.magic = 0;
140 storage.eeprom_good = true;
141 }
142
143 void storage_load_config(void)
144 {
145 if (!storage.eeprom_good)
146 return;
147
148 /* load config */
149 eeprom_read_block(&startup_config, &eeprom_storage.config, sizeof(struct storage_config_t));
150 }
151
152 void storage_save_color(uint8_t position, struct storage_color_t *color)
153 {
154 if (storage.state != STORAGE_IDLE)
155 return;
156
157 /* copy data to buffer */
158 memcpy(&storage.buf[0], color, sizeof(struct storage_color_t));
159 /* set address and bytes_remaining */
160 storage.index = 0;
161 storage.bytes_remaining = sizeof(struct storage_color_t);
162 storage.address = (uint8_t *)&eeprom_storage.color[position];
163 /* start write */
164 storage.state = STORAGE_WRITE;
165 }
166
167 void storage_load_color(uint8_t position, struct storage_color_t *color)
168 {
169 eeprom_read_block(color, &eeprom_storage.color[position], sizeof(struct storage_color_t));
170 }
171
172 bool storage_valid_config(void)
173 {
174 return (storage.eeprom_good && startup_config.magic == EEPROM_MAGIC_BYTE);
175 }
Impressum, Datenschutz