diff options
Diffstat (limited to 'ao-tools/lib/cc-logfile.c')
-rw-r--r-- | ao-tools/lib/cc-logfile.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c new file mode 100644 index 00000000..4abf7eb6 --- /dev/null +++ b/ao-tools/lib/cc-logfile.c @@ -0,0 +1,251 @@ +/* + * Copyright © 2009 Keith Packard <keithp@keithp.com> + * + * 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; version 2 of the License. + * + * 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "cc.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int +timedata_add(struct cc_timedata *data, double time, double value) +{ + struct cc_timedataelt *newdata; + int newsize; + if (data->size == data->num) { + if (data->size == 0) + newdata = malloc((newsize = 256) * sizeof (struct cc_timedataelt)); + else + newdata = realloc (data->data, (newsize = data->size * 2) + * sizeof (struct cc_timedataelt)); + if (!newdata) + return 0; + data->size = newsize; + data->data = newdata; + } + time += data->time_offset; + if (data->num && data->data[data->num-1].time > time) { + data->time_offset += 65536; + time += 65536; + } + data->data[data->num].time = time; + data->data[data->num].value = value; + data->num++; + return 1; +} + +static void +timedata_free(struct cc_timedata *data) +{ + if (data->data) + free(data->data); +} + +static int +gpsdata_add(struct cc_gpsdata *data, struct cc_gpselt *elt) +{ + struct cc_gpselt *newdata; + int newsize; + if (data->size == data->num) { + if (data->size == 0) + newdata = malloc((newsize = 256) * sizeof (struct cc_gpselt)); + else + newdata = realloc (data->data, (newsize = data->size * 2) + * sizeof (struct cc_gpselt)); + if (!newdata) + return 0; + data->size = newsize; + data->data = newdata; + } + elt->time += data->time_offset; + if (data->num && data->data[data->num-1].time > elt->time) { + data->time_offset += 65536; + elt->time += 65536; + } + data->data[data->num] = *elt; + data->num++; + return 1; +} + +static void +gpsdata_free(struct cc_gpsdata *data) +{ + if (data->data) + free(data->data); +} + +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#define AO_LOG_TEMP_VOLT 'T' +#define AO_LOG_DEPLOY 'D' +#define AO_LOG_STATE 'S' +#define AO_LOG_GPS_TIME 'G' +#define AO_LOG_GPS_LAT 'N' +#define AO_LOG_GPS_LON 'W' +#define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' + +#define AO_LOG_POS_NONE (~0UL) + +static int +read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int *ground_pres_count) +{ + char type; + int tick; + int a, b; + struct cc_gpselt gps; + int serial; + + if (sscanf(line, "serial-number %u", &serial) == 1) { + f->serial = serial; + return 1; + } + if (sscanf(line, "%c %x %x %x", &type, &tick, &a, &b) != 4) + return 0; + switch (type) { + case AO_LOG_FLIGHT: + f->ground_accel = a; + f->ground_pres = 0; + f->flight = b; + *ground_pres = 0; + *ground_pres_count = 0; + break; + case AO_LOG_SENSOR: + timedata_add(&f->accel, tick, a); + timedata_add(&f->pres, tick, b); + if (*ground_pres_count < 20) { + *ground_pres += b; + (*ground_pres_count)++; + if (*ground_pres_count >= 20) + f->ground_pres = *ground_pres / *ground_pres_count; + } + break; + case AO_LOG_TEMP_VOLT: + timedata_add(&f->temp, tick, a); + timedata_add(&f->volt, tick, b); + break; + case AO_LOG_DEPLOY: + timedata_add(&f->drogue, tick, a); + timedata_add(&f->main, tick, b); + break; + case AO_LOG_STATE: + timedata_add(&f->state, tick, a); + break; + case AO_LOG_GPS_TIME: + gps.time = tick; + break; + case AO_LOG_GPS_LAT: + gps.lat = ((int32_t) (a + (b << 16))) / 10000000.0; + break; + case AO_LOG_GPS_LON: + gps.lon = ((int32_t) (a + (b << 16))) / 10000000.0; + break; + case AO_LOG_GPS_ALT: + gps.alt = ((int32_t) (a + (b << 16))); + gpsdata_add(&f->gps, &gps); + break; + case AO_LOG_GPS_SAT: + break; + default: + return 0; + } + return 1; +} + +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + +static enum ao_flight_state +state_name_to_state(char *state_name) +{ + enum ao_flight_state state; + for (state = ao_flight_startup; state < ao_flight_invalid; state++) + if (!strcmp(state_names[state], state_name)) + return state; + return ao_flight_invalid; +} + +static int +read_telem(const char *line, struct cc_flightraw *f) +{ + struct cc_telem telem; + struct cc_gpselt gps; + if (!cc_telem_parse(line, &telem)) + return 0; + f->ground_accel = telem.ground_accel; + f->ground_pres = telem.ground_pres; + f->flight = 0; + timedata_add(&f->accel, telem.tick, telem.flight_accel); + timedata_add(&f->pres, telem.tick, telem.flight_pres); + timedata_add(&f->temp, telem.tick, telem.temp); + timedata_add(&f->volt, telem.tick, telem.batt); + timedata_add(&f->drogue, telem.tick, telem.drogue); + timedata_add(&f->main, telem.tick, telem.main); + timedata_add(&f->state, telem.tick, state_name_to_state(telem.state)); + if (telem.gps.gps_locked) { + gps.time = telem.tick; + gps.lat = telem.gps.lat; + gps.lon = telem.gps.lon; + gps.alt = telem.gps.alt; + gpsdata_add(&f->gps, &gps); + } + return 1; +} + +struct cc_flightraw * +cc_log_read(FILE *file) +{ + struct cc_flightraw *f; + char line[8192]; + double ground_pres; + int ground_pres_count; + + f = calloc(1, sizeof (struct cc_flightraw)); + if (!f) + return NULL; + while (fgets(line, sizeof (line), file)) { + if (read_eeprom(line, f, &ground_pres, &ground_pres_count)) + continue; + if (read_telem(line, f)) + continue; + fprintf (stderr, "invalid line: %s", line); + } + return f; +} + +void +cc_flightraw_free(struct cc_flightraw *raw) +{ + timedata_free(&raw->accel); + timedata_free(&raw->pres); + timedata_free(&raw->temp); + timedata_free(&raw->volt); + timedata_free(&raw->main); + timedata_free(&raw->drogue); + timedata_free(&raw->state); + gpsdata_free(&raw->gps); + free(raw); +} |