b24602e92beb13c70fb56e23c6e53ff1e1410bc5
[fw/altos] / ao_log.c
1 /*
2  * Copyright © 2009 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ao.h"
20
21 __data uint32_t         ao_log_current_pos;
22 __data uint32_t         ao_log_start_pos;
23 __xdata uint8_t         ao_log_running;
24 __xdata uint8_t         ao_log_mutex;
25
26 static uint8_t
27 ao_log_csum(uint8_t *b)
28 {
29         uint8_t sum = 0x5a;
30         uint8_t i;
31
32         for (i = 0; i < sizeof (struct ao_log_record); i++)
33                 sum += *b++;
34         return -sum;
35 }
36
37 void
38 ao_log_data(struct ao_log_record *log)
39 {
40         /* set checksum */
41         log->csum = 0;
42         log->csum = ao_log_csum((uint8_t *) log);
43         ao_mutex_get(&ao_log_mutex); {
44                 if (ao_log_running) {
45                         ao_ee_write(ao_log_current_pos,
46                                     (uint8_t *) log,
47                                     sizeof (struct ao_log_record));
48                         ao_log_current_pos += sizeof (struct ao_log_record);
49                         if (ao_log_current_pos >= AO_EE_DATA_SIZE)
50                                 ao_log_current_pos = 0;
51                         if (ao_log_current_pos == ao_log_start_pos)
52                                 ao_log_running = 0;
53                 }
54         } ao_mutex_put(&ao_log_mutex);
55 }
56
57 void
58 ao_log_flush(void)
59 {
60         ao_ee_flush();
61 }
62
63 __xdata struct ao_log_record ao_log_dump;
64 static __xdata uint16_t ao_log_dump_flight;
65 static __xdata uint32_t ao_log_dump_pos;
66
67 static uint8_t
68 ao_log_dump_check_data(void)
69 {
70         if (ao_log_csum((uint8_t *) &ao_log_dump) != 0)
71                 return 0;
72         return 1;
73 }
74
75 static uint8_t
76 ao_log_dump_scan(void)
77 {
78         if (!ao_ee_read(0, (uint8_t *) &ao_log_dump, sizeof (struct ao_log_record)))
79                 ao_panic(AO_PANIC_LOG);
80         if (ao_log_dump_check_data() && ao_log_dump.type == AO_LOG_FLIGHT) {
81                 ao_log_dump_flight = ao_log_dump.u.flight.flight;
82                 return 1;
83         } else {
84                 ao_log_dump_flight = 0;
85                 return 0;
86         }
87 }
88
89 uint8_t
90 ao_log_dump_first(void)
91 {
92         ao_log_dump_pos = 0;
93         if (!ao_log_dump_scan())
94                 return 0;
95         return 1;
96 }
97
98 uint8_t
99 ao_log_dump_next(void)
100 {
101         ao_log_dump_pos += sizeof (struct ao_log_record);
102         if (ao_log_dump_pos >= AO_EE_DEVICE_SIZE)
103                 return 0;
104         if (!ao_ee_read(ao_log_dump_pos, (uint8_t *) &ao_log_dump,
105                         sizeof (struct ao_log_record)))
106                 return 0;
107         return ao_log_dump_check_data();
108 }
109
110 __xdata uint8_t ao_log_adc_pos;
111 __xdata enum flight_state ao_log_state;
112
113 void
114 ao_log(void)
115 {
116         static __xdata struct ao_log_record     log;
117         
118         ao_log_dump_scan();
119
120         while (!ao_log_running)
121                 ao_sleep(&ao_log_running);
122         
123         log.type = AO_LOG_FLIGHT;
124         log.tick = ao_flight_tick;
125         log.u.flight.serial = 0;
126         log.u.flight.flight = ao_log_dump_flight + 1;
127         ao_log_data(&log);
128         for (;;) {
129                 /* Write state change to EEPROM */
130                 if (ao_flight_state != ao_log_state) {
131                         ao_log_state = ao_flight_state;
132                         log.type = AO_LOG_STATE;
133                         log.tick = ao_flight_tick;
134                         log.u.state.state = ao_log_state;
135                         log.u.state.reason = 0;
136                         ao_log_data(&log);
137                 }
138                 /* Write samples to EEPROM */
139                 while (ao_log_adc_pos != ao_adc_head) {
140                         log.type = AO_LOG_SENSOR;
141                         log.tick = ao_adc_ring[ao_log_adc_pos].tick;
142                         log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel;
143                         log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres;
144                         ao_log_data(&log);
145                         if (ao_log_adc_pos == 0) {
146                                 log.type = AO_LOG_TEMP_VOLT;
147                                 log.tick = ao_adc_ring[ao_log_adc_pos].tick;
148                                 log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp;
149                                 log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt;
150                                 ao_log_data(&log);
151                                 log.type = AO_LOG_DEPLOY;
152                                 log.tick = ao_adc_ring[ao_log_adc_pos].tick;
153                                 log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d;
154                                 log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m;
155                                 ao_log_data(&log);
156                         }
157                         ao_log_adc_pos++;
158                         if (ao_log_adc_pos == AO_ADC_RING)
159                                 ao_log_adc_pos = 0;
160                 }
161                 
162                 /* Wait for a while */
163                 ao_delay(AO_MS_TO_TICKS(100));
164         }
165 }
166
167 void
168 ao_log_start(void)
169 {
170         /* start logging */
171         ao_log_running = 1;
172         ao_wakeup(&ao_log_running);
173 }
174
175 void
176 ao_log_stop(void)
177 {
178         ao_log_running = 0;
179         ao_log_flush();
180 }
181
182 static __xdata struct ao_task ao_log_task;
183
184 void
185 ao_log_init(void)
186 {
187         ao_log_running = 0;
188
189         /* For now, just log the flight starting at the begining of eeprom */
190         ao_log_start_pos = 0;
191         ao_log_current_pos = ao_log_start_pos;
192         ao_log_state = ao_flight_invalid;
193
194         /* Create a task to log events to eeprom */
195         ao_add_task(&ao_log_task, ao_log);
196 }