2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
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.
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.
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.
25 timedata_add(struct cc_timedata *data, double time, double value)
27 struct cc_timedataelt *newdata;
29 if (data->size == data->num) {
31 newdata = malloc((newsize = 256) * sizeof (struct cc_timedataelt));
33 newdata = realloc (data->data, (newsize = data->size * 2)
34 * sizeof (struct cc_timedataelt));
40 time += data->time_offset;
41 if (data->num && data->data[data->num-1].time > time) {
42 data->time_offset += 65536;
45 data->data[data->num].time = time;
46 data->data[data->num].value = value;
52 timedata_free(struct cc_timedata *data)
59 gpsdata_add(struct cc_gpsdata *data, struct cc_gpselt *elt)
61 struct cc_gpselt *newdata;
63 if (data->size == data->num) {
65 newdata = malloc((newsize = 256) * sizeof (struct cc_gpselt));
67 newdata = realloc (data->data, (newsize = data->size * 2)
68 * sizeof (struct cc_gpselt));
74 elt->time += data->time_offset;
75 if (data->num && data->data[data->num-1].time > elt->time) {
76 data->time_offset += 65536;
79 data->data[data->num] = *elt;
85 gpssat_add(struct cc_gpsdata *data, struct cc_gpssat *sat)
90 struct cc_gpssats *newsats;
92 for (i = data->numsats; --i >= 0;) {
93 if (data->sats[i].sat[0].time == sat->time) {
97 if (data->sats[i].sat[0].time < sat->time)
101 if (data->numsats == data->sizesats) {
102 if (data->sizesats == 0)
103 newsats = malloc((newsizesats = 256) * sizeof (struct cc_gpssats));
105 newsats = realloc (data->sats, (newsizesats = data->sizesats * 2)
106 * sizeof (struct cc_gpssats));
109 data->sats = newsats;
110 data->sizesats = newsizesats;
113 data->sats[i].nsat = 0;
115 j = data->sats[i].nsat;
117 data->sats[i].sat[j] = *sat;
118 data->sats[i].nsat = j + 1;
124 gpsdata_free(struct cc_gpsdata *data)
130 #define AO_LOG_FLIGHT 'F'
131 #define AO_LOG_SENSOR 'A'
132 #define AO_LOG_TEMP_VOLT 'T'
133 #define AO_LOG_DEPLOY 'D'
134 #define AO_LOG_STATE 'S'
135 #define AO_LOG_GPS_TIME 'G'
136 #define AO_LOG_GPS_LAT 'N'
137 #define AO_LOG_GPS_LON 'W'
138 #define AO_LOG_GPS_ALT 'H'
139 #define AO_LOG_GPS_SAT 'V'
140 #define AO_LOG_GPS_DATE 'Y'
142 #define AO_LOG_POS_NONE (~0UL)
150 read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int *ground_pres_count)
155 static struct cc_gpselt gps;
156 static int gps_valid;
157 struct cc_gpssat sat;
160 if (sscanf(line, "serial-number %u", &serial) == 1) {
164 if (sscanf(line, "%c %x %x %x", &type, &tick, &a, &b) != 4)
172 *ground_pres_count = 0;
175 timedata_add(&f->accel, tick, a);
176 timedata_add(&f->pres, tick, b);
177 if (*ground_pres_count < 20) {
179 (*ground_pres_count)++;
180 if (*ground_pres_count >= 20)
181 f->ground_pres = *ground_pres / *ground_pres_count;
184 case AO_LOG_TEMP_VOLT:
185 timedata_add(&f->temp, tick, a);
186 timedata_add(&f->volt, tick, b);
189 timedata_add(&f->drogue, tick, a);
190 timedata_add(&f->main, tick, b);
193 timedata_add(&f->state, tick, a);
195 case AO_LOG_GPS_TIME:
196 /* the flight computer writes TIME first, so reset
197 * any stale data before adding this record
200 gps.hour = (a & 0xff);
201 gps.minute = (a >> 8) & 0xff;
202 gps.second = (b & 0xff);
203 gps.flags = (b >> 8) & 0xff;
204 gps_valid = GPS_TIME;
207 gps.lat = ((int32_t) (a + (b << 16))) / 10000000.0;
208 gps_valid |= GPS_LAT;
211 gps.lon = ((int32_t) (a + (b << 16))) / 10000000.0;
212 gps_valid |= GPS_LON;
215 gps.alt = (int16_t) a;
216 gps_valid |= GPS_ALT;
221 sat.c_n = (b >> 8) & 0xff;
222 gpssat_add(&f->gps, &sat);
224 case AO_LOG_GPS_DATE:
225 f->year = 2000 + (a & 0xff);
226 f->month = (a >> 8) & 0xff;
232 if (gps_valid == 0xf) {
234 gpsdata_add(&f->gps, &gps);
239 static const char *state_names[] = {
252 static enum ao_flight_state
253 state_name_to_state(char *state_name)
255 enum ao_flight_state state;
256 for (state = ao_flight_startup; state < ao_flight_invalid; state++)
257 if (!strcmp(state_names[state], state_name))
259 return ao_flight_invalid;
263 read_telem(const char *line, struct cc_flightraw *f)
265 struct cc_telem telem;
266 struct cc_gpselt gps;
267 struct cc_gpssat sat;
270 if (!cc_telem_parse(line, &telem))
272 f->ground_accel = telem.ground_accel;
273 f->ground_pres = telem.ground_pres;
275 timedata_add(&f->accel, telem.tick, telem.flight_accel);
276 timedata_add(&f->pres, telem.tick, telem.flight_pres);
277 timedata_add(&f->temp, telem.tick, telem.temp);
278 timedata_add(&f->volt, telem.tick, telem.batt);
279 timedata_add(&f->drogue, telem.tick, telem.drogue);
280 timedata_add(&f->main, telem.tick, telem.main);
281 timedata_add(&f->state, telem.tick, state_name_to_state(telem.state));
282 if (telem.gps.gps_locked) {
283 f->year = telem.gps.gps_time.year;
284 f->month = telem.gps.gps_time.month;
285 f->day = telem.gps.gps_time.day;
286 gps.time = telem.tick;
287 gps.lat = telem.gps.lat;
288 gps.lon = telem.gps.lon;
289 gps.alt = telem.gps.alt;
290 gps.hour = telem.gps.gps_time.hour;
291 gps.minute = telem.gps.gps_time.minute;
292 gps.second = telem.gps.gps_time.second;
293 gpsdata_add(&f->gps, &gps);
295 for (s = 0; s < telem.gps_tracking.channels; s++) {
296 sat.time = telem.tick;
297 sat.svid = telem.gps_tracking.sats[s].svid;
298 sat.c_n = telem.gps_tracking.sats[s].c_n0;
299 gpssat_add(&f->gps, &sat);
304 struct cc_flightraw *
305 cc_log_read(FILE *file)
307 struct cc_flightraw *f;
310 int ground_pres_count;
312 f = calloc(1, sizeof (struct cc_flightraw));
315 while (fgets(line, sizeof (line), file)) {
316 if (read_eeprom(line, f, &ground_pres, &ground_pres_count))
318 if (read_telem(line, f))
320 fprintf (stderr, "invalid line: %s", line);
326 cc_flightraw_free(struct cc_flightraw *raw)
328 timedata_free(&raw->accel);
329 timedata_free(&raw->pres);
330 timedata_free(&raw->temp);
331 timedata_free(&raw->volt);
332 timedata_free(&raw->main);
333 timedata_free(&raw->drogue);
334 timedata_free(&raw->state);
335 gpsdata_free(&raw->gps);