altos/test: Handle new eeprom file format. Give up on telem files.
[fw/altos] / src / test / ao_eeprom_read.c
diff --git a/src/test/ao_eeprom_read.c b/src/test/ao_eeprom_read.c
new file mode 100644 (file)
index 0000000..803ef36
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright © 2017 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include "ao_eeprom_read.h"
+#include <json-c/json.h>
+#include <string.h>
+#include <errno.h>
+
+static struct json_object *
+ao_eeprom_read_config(FILE *file)
+{
+       char                    line[1024];
+       struct json_tokener     *tok;
+       struct json_object      *obj = NULL;
+       enum json_tokener_error err;
+
+       tok = json_tokener_new();
+       if (!tok)
+               goto fail_tok;
+
+       for (;;) {
+               if (fgets(line, sizeof(line), file) == NULL)
+                       goto fail_read;
+               obj = json_tokener_parse_ex(tok, line, strlen(line));
+               err = json_tokener_get_error(tok);
+               if (err == json_tokener_success)
+                       break;
+               if (err != json_tokener_continue)
+                       goto fail_read;
+       }
+       json_tokener_free(tok);
+       return obj;
+fail_read:
+       json_tokener_free(tok);
+fail_tok:
+       return NULL;
+}
+
+static int
+ao_eeprom_read_byte(FILE *file)
+{
+       int     byte;
+       if (fscanf(file, "%x", &byte) != 1)
+               return EOF;
+       return byte;
+}
+
+static int
+ao_eeprom_read_data(FILE *file, struct ao_eeprom *eeprom)
+{
+       uint8_t *data = NULL, *ndata;
+       int     len = 0;
+       int     size = 0;
+       int     byte;
+
+       data = malloc(size = 64);
+       if (!data)
+               goto fail_alloc;
+       while ((byte = ao_eeprom_read_byte(file)) != EOF) {
+               if (len == size) {
+                       ndata = realloc(data, size *= 2);
+                       if (!ndata)
+                               goto fail_realloc;
+                       data = ndata;
+               }
+               data[len++] = (uint8_t) byte;
+       }
+       eeprom->data = data;
+       eeprom->len = len;
+       return 1;
+fail_realloc:
+       free(data);
+fail_alloc:
+       return 0;
+}
+
+static int
+ao_json_get_int(struct json_object *obj, const char *key, int def)
+{
+       struct json_object *value;
+       int i;
+
+       if (!json_object_object_get_ex(obj, key, &value))
+               return def;
+       errno = 0;
+       i = (int) json_object_get_int(value);
+       if (errno != 0)
+               return def;
+       return i;
+}
+
+static const char *
+ao_json_get_string(struct json_object *obj, const char *key, const char *def)
+{
+       struct json_object *value;
+       const char *str;
+
+       if (!json_object_object_get_ex(obj, key, &value))
+               return def;
+       errno = 0;
+       str = json_object_get_string(value);
+       if (errno)
+               return def;
+       if (!str)
+               return def;
+       return str;
+}
+
+#if AO_PYRO_NUM
+static int
+ao_eeprom_get_pyro(struct ao_config *config, struct json_object *obj)
+{
+       struct json_object      *pyros;
+       struct json_object      *pyro;
+       int                     i, p;
+
+       if (!json_object_object_get_ex(obj, "pyros", &pyros))
+               return 1;
+
+       if (json_object_get_type(pyros) != json_type_array)
+               return 0;
+
+       for (i = 0; i < json_object_array_length(pyros); i++) {
+               pyro = json_object_array_get_idx(pyros, i);
+               if (pyro) {
+                       p = ao_json_get_int(pyro, "channel", -1);
+                       if (0 <= p && p < AO_PYRO_NUM) {
+                               config->pyro[p].flags           = ao_json_get_int(pyro, "flags", 0);
+                               config->pyro[p].accel_less      = ao_json_get_int(pyro, "accel_less", 0);
+                               config->pyro[p].accel_greater   = ao_json_get_int(pyro, "accel_greater", 0);
+                               config->pyro[p].speed_less      = ao_json_get_int(pyro, "speed_less", 0);
+                               config->pyro[p].speed_greater   = ao_json_get_int(pyro, "speed_greater", 0);
+                               config->pyro[p].height_less     = ao_json_get_int(pyro, "height_less", 0);
+                               config->pyro[p].height_greater  = ao_json_get_int(pyro, "height_greater", 0);
+                               config->pyro[p].orient_less     = ao_json_get_int(pyro, "orient_less", 0);
+                               config->pyro[p].orient_greater  = ao_json_get_int(pyro, "orient_greater", 0);
+                               config->pyro[p].time_less       = ao_json_get_int(pyro, "time_less", 0);
+                               config->pyro[p].time_greater    = ao_json_get_int(pyro, "time_greater", 0);
+                               config->pyro[p].delay           = ao_json_get_int(pyro, "delay", 0);
+                               config->pyro[p].state_less      = ao_json_get_int(pyro, "state_less", 0);
+                               config->pyro[p].state_greater_or_equal  = ao_json_get_int(pyro, "state_greater_or_equal", 0);
+                               config->pyro[p].motor           = ao_json_get_int(pyro, "motor", 0);
+                       }
+               }
+       }
+       return 1;
+}
+#endif
+
+static int
+ao_eeprom_get_ms5607(struct ao_ms5607_prom *ms5607_prom, struct json_object *obj)
+{
+       struct json_object      *ms5607;
+
+       if (!json_object_object_get_ex(obj, "ms5607", &ms5607))
+               return 1;
+
+       if (json_object_get_type(ms5607) != json_type_object)
+               return 0;
+
+       ms5607_prom->reserved = ao_json_get_int(ms5607, "reserved", 0);
+       ms5607_prom->sens =     ao_json_get_int(ms5607, "sens", 0);
+       ms5607_prom->off =      ao_json_get_int(ms5607, "off", 0);
+       ms5607_prom->tcs =      ao_json_get_int(ms5607, "tcs", 0);
+       ms5607_prom->tco =      ao_json_get_int(ms5607, "tco", 0);
+       ms5607_prom->tref =     ao_json_get_int(ms5607, "tref", 0);
+       ms5607_prom->tempsens = ao_json_get_int(ms5607, "tempsens", 0);
+       ms5607_prom->crc =      ao_json_get_int(ms5607, "crc", 0);
+       return 1;
+}
+
+static int
+ao_eeprom_get_config(struct ao_eeprom *ao_eeprom, struct json_object *obj)
+{
+       struct ao_config        *config = &ao_eeprom->config;
+       const char              *s;
+
+       if (json_object_get_type(obj) != json_type_object)
+               return 0;
+
+       ao_eeprom->log_format =         ao_json_get_int(obj, "log_format", 0);
+       ao_eeprom->serial_number =      ao_json_get_int(obj, "serial", 0);
+
+       config->major =                 ao_json_get_int(obj, "config_major", 0);
+       config->minor =                 ao_json_get_int(obj, "config_minor", 0);
+       if (config->major == 0 || config->minor == 0)
+               return 0;
+
+       config->main_deploy =           ao_json_get_int(obj, "main_deploy", 250);
+       config->accel_plus_g =          ao_json_get_int(obj, "accel_cal_plus", 0);
+
+       s = ao_json_get_string(obj, "callsign", "N0CALL");
+       strncpy(config->callsign, s, sizeof(config->callsign));
+
+       config->apogee_delay =          ao_json_get_int(obj, "apogee_delay", 0);
+       config->accel_minus_g =         ao_json_get_int(obj, "accel_cal_minus", 0);
+       config->radio_cal =             ao_json_get_int(obj, "radio_calibration", 0);
+       config->flight_log_max =        ao_json_get_int(obj, "flight_log_max", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->pad_orientation =       ao_json_get_int(obj, "pad_orientation", 0);
+       config->radio_setting =         ao_json_get_int(obj, "radio_setting", 0);
+       config->radio_enable =          ao_json_get_int(obj, "radio_enable", 1);
+       config->frequency =             ao_json_get_int(obj, "frequency", 434550);
+       config->apogee_lockout =        ao_json_get_int(obj, "apogee_lockout", 0);
+#if AO_PYRO_NUM
+       if (!ao_eeprom_get_pyro(config, obj))
+               return 0;
+#endif
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+
+       if (!ao_eeprom_get_ms5607(&ao_eeprom->ms5607_prom, obj))
+               return 0;
+
+       return 1;
+}
+
+struct ao_eeprom *
+ao_eeprom_read(FILE *file)
+{
+       struct ao_eeprom        *ao_eeprom;
+       struct json_object      *obj;
+       int                     ret;
+
+       ao_eeprom = calloc(1, sizeof (struct ao_eeprom));
+       if (!ao_eeprom)
+               goto fail_ao_eeprom;
+
+       obj = ao_eeprom_read_config(file);
+       if (!obj)
+               goto fail_config;
+
+       ret = ao_eeprom_get_config(ao_eeprom, obj);
+       json_object_put(obj);
+       if (!ret)
+               goto fail_config;
+
+       if (!ao_eeprom_read_data(file, ao_eeprom))
+               goto fail_data;
+
+       return ao_eeprom;
+fail_data:
+fail_config:
+       free(ao_eeprom);
+fail_ao_eeprom:
+       return NULL;
+}