1f367d9332265be4f4f9941afbe4b3e76ee87def
[fw/altos] / ao-tools / ao-eeprom / ao-eeprom.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 <stdio.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <unistd.h>
23 #include <getopt.h>
24 #include <ao-eeprom-read.h>
25 #include <ao-atmosphere.h>
26
27 static const struct option options[] = {
28         { .name = "raw", .has_arg = 0, .val = 'r' },
29         { .name = "csum", .has_arg = 0, .val = 'c' },
30         { .name = "verbose", .has_arg = 0, .val = 'v' },
31         { .name = "len", .has_arg = 1, .val = 'l' },
32         { 0, 0, 0, 0},
33 };
34
35 static void usage(char *program)
36 {
37         fprintf(stderr, "usage: %s [--raw] [--csum] [--verbose] [--len <record-len>] {flight.eeprom} ...\n", program);
38         exit(1);
39 }
40
41 static bool
42 ao_csum_valid(uint8_t *d, int len)
43 {
44         uint8_t sum = 0x5a;
45         int i;
46         for (i = 0; i < len; i++)
47                 sum += d[i];
48         return sum == 0;
49 }
50
51 static void
52 ao_ms5607(uint32_t pres, uint32_t temp, struct ao_eeprom *eeprom, bool is_ms5611)
53 {
54         struct ao_ms5607_sample ms5607_sample = { .pres = pres, .temp = temp };
55         struct ao_ms5607_value ms5607_value;
56
57         ao_ms5607_convert(&ms5607_sample, &ms5607_value,
58                           &eeprom->ms5607_prom, is_ms5611);
59         printf(" pres %9u %7.3f kPa  %7.1f m temp %9u %6.2f °C",
60                pres,
61                ms5607_value.pres / 1000.0,
62                ao_pressure_to_altitude(ms5607_value.pres),
63                temp,
64                ms5607_value.temp / 100.0);
65 }
66
67 #define GRAVITY 9.80665
68
69 static void
70 ao_accel(int16_t accel, struct ao_eeprom *eeprom)
71 {
72         double accel_2g = eeprom->config.accel_minus_g - eeprom->config.accel_plus_g;
73         double accel_scale = GRAVITY * 2.0 / accel_2g;
74         printf(" accel %6d %7.2f m/s²",
75                accel, (eeprom->config.accel_plus_g - accel) * accel_scale);
76 }
77
78 static const char *state_names[] = {
79         "startup",
80         "idle",
81         "pad",
82         "boost",
83         "fast",
84         "coast",
85         "drogue",
86         "main",
87         "landed",
88         "invalid"
89 };
90
91 #define NUM_STATE       (sizeof state_names/sizeof state_names[0])
92
93 static const char *
94 ao_state_name(uint16_t state)
95 {
96         if (state < NUM_STATE)
97                 return state_names[state];
98         return "UNKNOWN";
99 }
100
101 static void
102 ao_state(uint16_t state, uint16_t reason)
103 {
104         printf(" state %5u %s reason %5u",
105                state, ao_state_name(state), reason);
106 }
107
108 static double
109 ao_adc_to_volts(int16_t value, int16_t max_adc, double ref, double r1, double r2)
110 {
111         return ref * ((double) value / max_adc) * (r1 + r2) / r2;
112 }
113
114 static void
115 ao_volts(const char *name, int16_t value, int16_t max_adc, double ref, double r1, double r2)
116 {
117         printf(" %s %5d",
118                name, value);
119         if (r1 && r2 && ref)
120                 printf(" %6.3f V", ao_adc_to_volts(value, max_adc, ref, r1, r2));
121 }
122
123 static double lb_to_n(double lb)
124 {
125         return lb / 0.22480894;
126 }
127
128 static double psi_to_pa(double psi)
129 {
130         return psi * 6894.76;
131 }
132
133 static double
134 ao_volts_to_newtons(double volts)
135 {
136         /* this is a total guess */
137         return lb_to_n(volts * 57.88645 * GRAVITY);
138 }
139
140 static void
141 ao_thrust(int16_t value, int16_t max_adc, double ref, double r1, double r2)
142 {
143         printf(" thrust %5d", value);
144         if (r1 && r2 && ref) {
145                 double volts = ao_adc_to_volts(value, max_adc, ref, r1, r2);
146                 printf(" %6.3f V %8.1f N", volts, ao_volts_to_newtons(volts));
147         }
148 }
149
150 static void
151 ao_pressure(int16_t value, int16_t max_adc, double ref, double r1, double r2, double sensor_range)
152 {
153         printf(" pressure %5d", value);
154         if (r1 && r2 && ref) {
155                 double volts = ao_adc_to_volts(value, max_adc, ref, r1, r2);
156                 if (volts < 0.5) volts = 0.5;
157                 if (volts > 4.5) volts = 4.5;
158
159                 double psi = (volts - 0.5) / 4.0 * sensor_range;
160                 double pa = psi_to_pa(psi);
161                 printf(" %9.3f kPa", pa / 1000.0);
162         }
163 }
164
165 #if 0
166 static uint16_t
167 uint16(uint8_t *bytes, int off)
168 {
169         return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8);
170 }
171
172 static int16_t
173 int16(uint8_t *bytes, int off)
174 {
175         return (int16_t) uint16(bytes, off);
176 }
177
178 static uint32_t
179 uint32(uint8_t *bytes, int off)
180 {
181         return (uint32_t) bytes[off] | (((uint32_t) bytes[off+1]) << 8) |
182                 (((uint32_t) bytes[off+2]) << 16) |
183                 (((uint32_t) bytes[off+3]) << 24);
184 }
185
186 static int32_t
187 int32(uint8_t *bytes, int off)
188 {
189         return (int32_t) uint32(bytes, off);
190 }
191 #endif
192
193 static uint32_t
194 uint24(uint8_t *bytes, int off)
195 {
196         return (uint32_t) bytes[off] | (((uint32_t) bytes[off+1]) << 8) |
197                 (((uint32_t) bytes[off+2]) << 16);
198 }
199
200 static int32_t
201 int24(uint8_t *bytes, int off)
202 {
203         return (int32_t) uint24(bytes, off);
204 }
205
206 int
207 main (int argc, char **argv)
208 {
209         struct ao_eeprom        *eeprom;
210         FILE                    *file;
211         int                     c;
212         bool                    raw = false;
213         bool                    csum = false;
214         bool                    verbose = false;
215         int                     arg_len = 0;
216         char                    *end;
217         int                     ret = 0;
218         int                     i;
219
220         while ((c = getopt_long(argc, argv, "rcvl:", options, NULL)) != -1) {
221                 switch (c) {
222                 case 'r':
223                         raw = true;
224                         break;
225                 case 'c':
226                         csum = true;
227                         break;
228                 case 'v':
229                         verbose = true;
230                         break;
231                 case 'l':
232                         arg_len = strtol(optarg, &end, 0);
233                         if (!*optarg || *end)
234                                 usage(argv[0]);
235                         break;
236                 default:
237                         usage(argv[0]);
238                         break;
239                 }
240         }
241         for (i = optind; i < argc; i++) {
242                 file = fopen(argv[i], "r");
243                 if (!file) {
244                         perror(argv[i]);
245                         ret++;
246                         continue;
247                 }
248                 eeprom = ao_eeprom_read(file);
249                 fclose(file);
250                 if (!eeprom) {
251                         perror(argv[i]);
252                         ret++;
253                         continue;
254                 }
255                 int     len = 0;
256                 bool    is_ms5611 = false;
257
258                 int64_t current_tick = 0;
259                 int64_t first_tick = 0x7fffffffffffffffLL;
260
261                 double  sense_r1 = 0.0, sense_r2 = 0.0;
262                 double  batt_r1 = 0.0, batt_r2 = 0.0;
263                 double  adc_ref = 0.0;
264                 double  pressure_sensor = 0.0;
265                 int16_t max_adc = 0;
266
267                 switch (eeprom->log_format) {
268                 case AO_LOG_FORMAT_TELEMEGA_OLD:
269                         len = 32;
270                         break;
271                 case AO_LOG_FORMAT_EASYMINI1:
272                         len = 16;
273                         max_adc = 32767;
274                         if (eeprom->serial_number < 1000)
275                                 adc_ref = 3.0;
276                         else
277                                 adc_ref = 3.3;
278                         batt_r1 = sense_r1 = 100e3;
279                         batt_r2 = sense_r2 = 27e3;
280                         break;
281                 case AO_LOG_FORMAT_TELEMETRUM:
282                         len = 16;
283                         max_adc = 4095;
284                         adc_ref = 3.3;
285                         batt_r1 = 5600;
286                         batt_r2 = 10000;
287                         sense_r1 = 100e3;
288                         sense_r2 = 27e3;
289                         break;
290                 case AO_LOG_FORMAT_TELEMINI2:
291                         len = 16;
292                         break;
293                 case AO_LOG_FORMAT_TELEGPS:
294                         len = 32;
295                         break;
296                 case AO_LOG_FORMAT_TELEMEGA:
297                         len = 32;
298                         max_adc = 4095;
299                         adc_ref = 3.3;
300                         batt_r1 = 5600;
301                         batt_r2 = 10000;
302                         sense_r1 = 100e3;
303                         sense_r2 = 27e3;
304                         break;
305                 case AO_LOG_FORMAT_DETHERM:
306                         len = 16;
307                         break;
308                 case AO_LOG_FORMAT_TELEMINI3:
309                         len = 16;
310                         max_adc = 4095;
311                         adc_ref = 3.3;
312                         batt_r1 = 5600;
313                         batt_r2 = 10000;
314                         sense_r1 = 100e3;
315                         sense_r2 = 27e3;
316                         break;
317                 case AO_LOG_FORMAT_TELEFIRETWO:
318                         len = 32;
319                         pressure_sensor = 2500.0;
320                         max_adc = 4095;
321                         adc_ref = 3.3;
322                         sense_r1 = batt_r1 = 5600;
323                         sense_r2 = batt_r2 = 10000;
324                         break;
325                 case AO_LOG_FORMAT_EASYMINI2:
326                         len = 16;
327                         max_adc = 4095;
328                         adc_ref = 3.3;
329                         batt_r1 = sense_r1 = 100e3;
330                         batt_r2 = sense_r2 = 27e3;
331                         break;
332                 case AO_LOG_FORMAT_TELEMEGA_3:
333                         len = 32;
334                         max_adc = 4095;
335                         adc_ref = 3.3;
336                         batt_r1 = 5600;
337                         batt_r2 = 10000;
338                         sense_r1 = 100e3;
339                         sense_r2 = 27e3;
340                         break;
341                 case AO_LOG_FORMAT_EASYMEGA_2:
342                         len = 32;
343                         max_adc = 4095;
344                         adc_ref = 3.3;
345                         batt_r1 = 5600;
346                         batt_r2 = 10000;
347                         sense_r1 = 100e3;
348                         sense_r2 = 27e3;
349                         break;
350                 case AO_LOG_FORMAT_TELESTATIC:
351                         len = 32;
352                         break;
353                 case AO_LOG_FORMAT_MICROPEAK2:
354                         len = 2;
355                         break;
356                 case AO_LOG_FORMAT_TELEMEGA_4:
357                         len = 32;
358                         max_adc= 4095;
359                         adc_ref = 3.3;
360                         batt_r1 = 5600;
361                         batt_r2 = 10000;
362                         sense_r1 = 100e3;
363                         sense_r2 = 27e3;
364                         break;
365                 case AO_LOG_FORMAT_EASYMOTOR:
366                         len = 16;
367                         max_adc = 32767;
368                         adc_ref = 3.3;
369                         pressure_sensor = 1600.0;
370                         batt_r1 = 5600;
371                         batt_r2 = 10000;
372                         sense_r1 = 5600;
373                         sense_r2 = 10000;
374                         break;
375                 }
376                 if (arg_len)
377                         len = arg_len;
378                 if (verbose)
379                         printf("config major %d minor %d log format %d total %u len %d\n",
380                                eeprom->config.major,
381                                eeprom->config.minor,
382                                eeprom->log_format,
383                                eeprom->len,
384                                len);
385
386                 uint32_t        pos;
387                 for (pos = 0; pos < eeprom->len; pos += len) {
388                         int i;
389                         if (raw) {
390                                 printf("%9u", pos);
391                                 for (i = 0; i < len; i++)
392                                         printf(" %02x", eeprom->data[pos + i]);
393                         } else {
394                                 struct ao_log_mega *log_mega;
395                                 struct ao_log_mini *log_mini;
396                                 struct ao_log_metrum *log_metrum;
397                                 struct ao_log_gps *log_gps;
398                                 struct ao_log_firetwo *log_firetwo;
399                                 struct ao_log_motor *log_motor;
400
401                                 if (!csum && !ao_csum_valid(&eeprom->data[pos], len)) {
402                                         if (verbose)
403                                                 printf("\tchecksum error at %d\n", pos);
404                                         continue;
405                                 }
406
407                                 struct ao_log_header *log_header = (struct ao_log_header *) &eeprom->data[pos];
408
409                                 if (first_tick == 0x7fffffffffffffffLL) {
410                                         current_tick = first_tick = log_header->tick;
411                                 } else {
412                                         int16_t diff = (int16_t) (log_header->tick - (uint16_t) current_tick);
413
414                                         current_tick += diff;
415                                 }
416                                 printf("type %c tick %5u %6.2f S", log_header->type, log_header->tick, (current_tick - first_tick) / 100.0);
417
418                                 switch (eeprom->log_format) {
419                                 case AO_LOG_FORMAT_TELEMEGA_OLD:
420                                 case AO_LOG_FORMAT_TELEMEGA:
421                                 case AO_LOG_FORMAT_TELEMEGA_3:
422                                 case AO_LOG_FORMAT_EASYMEGA_2:
423                                 case AO_LOG_FORMAT_TELEMEGA_4:
424                                         log_mega = (struct ao_log_mega *) &eeprom->data[pos];
425                                         switch (log_mega->type) {
426                                         case AO_LOG_FLIGHT:
427                                                 printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u kPa  %7.1f  %7.1f m",
428                                                        eeprom->serial_number,
429                                                        log_mega->u.flight.flight,
430                                                        log_mega->u.flight.ground_accel,
431                                                        log_mega->u.flight.ground_pres,
432                                                        log_mega->u.flight.ground_pres / 1000.0,
433                                                        ao_pressure_to_altitude(log_mega->u.flight.ground_pres));
434
435                                                 printf(" along %6d aross %6d through %6d",
436                                                        log_mega->u.flight.ground_accel_along,
437                                                        log_mega->u.flight.ground_accel_across,
438                                                        log_mega->u.flight.ground_accel_through);
439                                                 printf(" roll %6d pitch %6d yaw %6d",
440                                                        log_mega->u.flight.ground_roll,
441                                                        log_mega->u.flight.ground_pitch,
442                                                        log_mega->u.flight.ground_yaw);
443                                                 break;
444                                         case AO_LOG_STATE:
445                                                 ao_state(log_mega->u.state.state,
446                                                          log_mega->u.state.reason);
447                                                 break;
448                                         case AO_LOG_SENSOR:
449                                                 ao_ms5607(log_mega->u.sensor.pres,
450                                                           log_mega->u.sensor.temp,
451                                                           eeprom, is_ms5611);
452                                                 printf(" accel_x %6d accel_y %6d accel_z %6d",
453                                                        log_mega->u.sensor.accel_x,
454                                                        log_mega->u.sensor.accel_y,
455                                                        log_mega->u.sensor.accel_z);
456                                                 printf (" gyro_x %6d gyro_y %6d gyro_z %6d",
457                                                        log_mega->u.sensor.gyro_x,
458                                                        log_mega->u.sensor.gyro_y,
459                                                        log_mega->u.sensor.gyro_z);
460                                                 printf (" mag_x %6d mag_y %6d mag_z %6d",
461                                                        log_mega->u.sensor.mag_x,
462                                                        log_mega->u.sensor.mag_y,
463                                                        log_mega->u.sensor.mag_z);
464                                                 ao_accel(log_mega->u.sensor.accel, eeprom);
465                                                 break;
466                                         case AO_LOG_TEMP_VOLT:
467                                                 ao_volts("v_batt",
468                                                          log_mega->u.volt.v_batt,
469                                                          max_adc,
470                                                          adc_ref,
471                                                          batt_r1, batt_r2);
472                                                 ao_volts("v_pbatt",
473                                                          log_mega->u.volt.v_pbatt,
474                                                          max_adc,
475                                                          adc_ref,
476                                                          sense_r1, sense_r2);
477                                                 printf(" n_sense %1d",
478                                                        log_mega->u.volt.n_sense);
479                                                 for (i = 0; i < log_mega->u.volt.n_sense; i++) {
480                                                         char name[10];
481                                                         sprintf(name, "sense%d", i);
482                                                         ao_volts(name,
483                                                                  log_mega->u.volt.sense[i],
484                                                                  max_adc,
485                                                                  adc_ref,
486                                                                  sense_r1, sense_r2);
487                                                 }
488                                                 printf(" pyro %04x", log_mega->u.volt.pyro);
489                                                 break;
490                                         case AO_LOG_GPS_TIME:
491                                                 printf(" lat %10.7f ° lon %10.7f ° alt %8d m",
492                                                        log_mega->u.gps.latitude / 10000000.0,
493                                                        log_mega->u.gps.longitude/ 10000000.0,
494                                                        (int32_t) (log_mega->u.gps.altitude_low |
495                                                                   (log_mega->u.gps.altitude_high << 16)));
496                                                 printf(" time %02d:%02d:%02d %04d-%02d-%02d flags %02x",
497                                                        log_mega->u.gps.hour,
498                                                        log_mega->u.gps.minute,
499                                                        log_mega->u.gps.second,
500                                                        log_mega->u.gps.year + 2000,
501                                                        log_mega->u.gps.month,
502                                                        log_mega->u.gps.day,
503                                                        log_mega->u.gps.flags);
504                                                 printf(" course %3d ground_speed %5u climb_rate %6d pdop %3d hdop %3d vdop %3d mode %3d",
505                                                        log_mega->u.gps.course,
506                                                        log_mega->u.gps.ground_speed,
507                                                        log_mega->u.gps.climb_rate,
508                                                        log_mega->u.gps.pdop,
509                                                        log_mega->u.gps.hdop,
510                                                        log_mega->u.gps.vdop,
511                                                        log_mega->u.gps.mode);
512                                                 break;
513                                         case AO_LOG_GPS_SAT:
514                                                 printf(" channels %2d",
515                                                        log_mega->u.gps_sat.channels);
516                                                 for (i = 0; i < 12; i++) {
517                                                         printf(" svid %3d c_n %2d",
518                                                                log_mega->u.gps_sat.sats[i].svid,
519                                                                log_mega->u.gps_sat.sats[i].c_n);
520                                                 }
521                                                 break;
522                                         }
523                                         break;
524                                 case AO_LOG_FORMAT_EASYMINI1:
525                                 case AO_LOG_FORMAT_EASYMINI2:
526                                 case AO_LOG_FORMAT_TELEMINI2:
527                                 case AO_LOG_FORMAT_TELEMINI3:
528                                         log_mini = (struct ao_log_mini *) &eeprom->data[pos];
529                                         switch (log_mini->type) {
530                                         case AO_LOG_FLIGHT:
531                                                 printf(" serial %5u flight %5u ground_pres %9u kPa  %7.1f  %7.1f m",
532                                                        eeprom->serial_number,
533                                                        log_mini->u.flight.flight,
534                                                        log_mini->u.flight.ground_pres,
535                                                        log_mini->u.flight.ground_pres / 1000.0,
536                                                        ao_pressure_to_altitude(log_mini->u.flight.ground_pres));
537                                                 break;
538                                         case AO_LOG_STATE:
539                                                 ao_state(log_mini->u.state.state,
540                                                          log_mini->u.state.reason);
541                                                 break;
542                                         case AO_LOG_SENSOR:
543                                                 ao_ms5607(int24(log_mini->u.sensor.pres, 0),
544                                                           int24(log_mini->u.sensor.temp, 0),
545                                                           eeprom, is_ms5611);
546                                                 ao_volts("sense_a",
547                                                          log_mini->u.sensor.sense_a, max_adc,
548                                                          adc_ref, sense_r1, sense_r2);
549                                                 ao_volts("sense_m",
550                                                          log_mini->u.sensor.sense_m, max_adc,
551                                                          adc_ref, sense_r1, sense_r2);
552                                                 ao_volts("v_batt",
553                                                          log_mini->u.sensor.v_batt, max_adc,
554                                                          adc_ref, batt_r1, batt_r2);
555                                                 break;
556                                         } /*  */
557                                         break;
558                                 case AO_LOG_FORMAT_TELEMETRUM:
559                                         log_metrum = (struct ao_log_metrum *) &eeprom->data[pos];
560                                         switch (log_metrum->type) {
561                                         case AO_LOG_FLIGHT:
562                                                 printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u kPa  %7.1f  %7.1f m ground_temp %9u",
563                                                        eeprom->serial_number,
564                                                        log_metrum->u.flight.flight,
565                                                        log_metrum->u.flight.ground_accel,
566                                                        log_metrum->u.flight.ground_pres,
567                                                        log_metrum->u.flight.ground_pres / 1000.0,
568                                                        ao_pressure_to_altitude(log_metrum->u.flight.ground_pres),
569                                                        log_metrum->u.flight.ground_temp);
570                                                 break;
571                                         case AO_LOG_SENSOR:
572                                                 ao_ms5607(log_metrum->u.sensor.pres,
573                                                           log_metrum->u.sensor.temp,
574                                                           eeprom, is_ms5611);
575                                                 ao_accel(log_metrum->u.sensor.accel, eeprom);
576                                                 break;
577                                         case AO_LOG_TEMP_VOLT:
578                                                 ao_volts("v_batt",
579                                                          log_metrum->u.volt.v_batt, max_adc,
580                                                          adc_ref, batt_r1, batt_r2);
581                                                 ao_volts("sense_a",
582                                                          log_metrum->u.volt.sense_a, max_adc,
583                                                          adc_ref, sense_r1, sense_r2);
584                                                 ao_volts("sense_m",
585                                                          log_metrum->u.volt.sense_m, max_adc,
586                                                          adc_ref, sense_r1, sense_r2);
587                                                 break;
588                                         case AO_LOG_DEPLOY:
589                                                 break;
590                                         case AO_LOG_STATE:
591                                                 ao_state(log_metrum->u.state.state,
592                                                          log_metrum->u.state.reason);
593                                                 break;
594                                         case AO_LOG_GPS_TIME:
595                                                 printf(" time %02d:%02d:%02d 20%02d-%02d-%02d flags %02x pdop %3u",
596                                                        log_metrum->u.gps_time.hour,
597                                                        log_metrum->u.gps_time.minute,
598                                                        log_metrum->u.gps_time.second,
599                                                        log_metrum->u.gps_time.year,
600                                                        log_metrum->u.gps_time.month,
601                                                        log_metrum->u.gps_time.day,
602                                                        log_metrum->u.gps_time.flags,
603                                                        log_metrum->u.gps_time.pdop);
604                                                 break;
605                                         case AO_LOG_GPS_SAT:
606                                                 printf(" channels %2d more %1d",
607                                                        log_metrum->u.gps_sat.channels,
608                                                        log_metrum->u.gps_sat.more);
609                                                 for (i = 0; i < 4; i++) {
610                                                         printf(" svid %3d c_n %2d",
611                                                                log_metrum->u.gps_sat.sats[i].svid,
612                                                                log_metrum->u.gps_sat.sats[i].c_n);
613                                                 }
614                                                 break;
615                                         case AO_LOG_GPS_POS:
616                                                 printf(" lat %10.7f° lon %10.7f° alt %8d m",
617                                                        log_metrum->u.gps.latitude / 10000000.0,
618                                                        log_metrum->u.gps.longitude/ 10000000.0,
619                                                        (int32_t) (log_metrum->u.gps.altitude_low |
620                                                                   (log_metrum->u.gps.altitude_high << 16)));
621                                                 break;
622                                         default:
623                                                 printf(" unknown");
624                                         }
625                                         break;
626                                 case AO_LOG_FORMAT_TELEFIRETWO:
627                                         log_firetwo = (struct ao_log_firetwo *) &eeprom->data[pos];
628                                         switch (log_firetwo->type) {
629                                         case AO_LOG_FLIGHT:
630                                                 printf(" serial %5u flight %5u",
631                                                        eeprom->serial_number,
632                                                        log_firetwo->u.flight.flight);
633                                                 break;
634                                         case AO_LOG_STATE:
635                                                 ao_state(log_firetwo->u.state.state,
636                                                          log_firetwo->u.state.reason);
637                                                 break;
638                                         case AO_LOG_SENSOR:
639                                                 ao_pressure(log_firetwo->u.sensor.pressure,
640                                                             max_adc, adc_ref,
641                                                             sense_r1, sense_r2,
642                                                             pressure_sensor);
643                                                 ao_thrust(log_firetwo->u.sensor.thrust,
644                                                           max_adc, adc_ref,
645                                                           sense_r1, sense_r2);
646                                                 for (i = 0; i < 4; i++) {
647                                                         char name[20];
648                                                         sprintf(name, "thermistor%d", i);
649                                                         ao_volts(name,
650                                                                  log_firetwo->u.sensor.thermistor[i],
651                                                                  max_adc, adc_ref,
652                                                                  sense_r1, sense_r2);
653                                                 }
654                                                 break;
655                                         }
656                                         break;
657                                 case AO_LOG_FORMAT_TELEGPS:
658                                         log_gps = (struct ao_log_gps *) &eeprom->data[pos];
659                                         switch (log_gps->type) {
660                                         case AO_LOG_GPS_TIME:
661                                                 printf(" lat %10.7f ° lon %10.7f ° alt %8d m",
662                                                        log_gps->u.gps.latitude / 10000000.0,
663                                                        log_gps->u.gps.longitude/ 10000000.0,
664                                                        (int32_t) (log_gps->u.gps.altitude_low |
665                                                                   (log_gps->u.gps.altitude_high << 16)));
666                                                 printf(" time %02d:%02d:%02d %04d-%02d-%02d flags %02x",
667                                                        log_gps->u.gps.hour,
668                                                        log_gps->u.gps.minute,
669                                                        log_gps->u.gps.second,
670                                                        log_gps->u.gps.year + 2000,
671                                                        log_gps->u.gps.month,
672                                                        log_gps->u.gps.day,
673                                                        log_gps->u.gps.flags);
674                                                 printf(" course %3d ground_speed %5u climb_rate %6d pdop %3d hdop %3d vdop %3d mode %3d",
675                                                        log_gps->u.gps.course,
676                                                        log_gps->u.gps.ground_speed,
677                                                        log_gps->u.gps.climb_rate,
678                                                        log_gps->u.gps.pdop,
679                                                        log_gps->u.gps.hdop,
680                                                        log_gps->u.gps.vdop,
681                                                        log_gps->u.gps.mode);
682                                                 break;
683                                         case AO_LOG_GPS_SAT:
684                                                 printf(" channels %2d",
685                                                        log_gps->u.gps_sat.channels);
686                                                 for (i = 0; i < 12; i++) {
687                                                         printf(" svid %3d c_n %2d",
688                                                                log_gps->u.gps_sat.sats[i].svid,
689                                                                log_gps->u.gps_sat.sats[i].c_n);
690                                                 }
691                                                 break;
692                                         default:
693                                                 printf (" unknown");
694                                                 break;
695                                         }
696                                         break;
697                                 case AO_LOG_FORMAT_EASYMOTOR:
698                                         log_motor = (struct ao_log_motor *) &eeprom->data[pos];
699                                         switch (log_motor->type) {
700                                         case AO_LOG_FLIGHT:
701                                                 printf(" serial %5u flight %5u ground_accel %6d",
702                                                        eeprom->serial_number,
703                                                        log_motor->u.flight.flight,
704                                                        log_motor->u.flight.ground_accel);
705                                                 printf(" along %6d aross %6d through %6d",
706                                                        log_motor->u.flight.ground_accel_along,
707                                                        log_motor->u.flight.ground_accel_across,
708                                                        log_motor->u.flight.ground_accel_through);
709                                                 ao_volts("ground pressure",
710                                                          log_motor->u.flight.ground_motor_pressure,
711                                                          max_adc, adc_ref,
712                                                          sense_r1, sense_r2);
713                                                 break;
714                                         case AO_LOG_STATE:
715                                                 ao_state(log_motor->u.state.state,
716                                                          log_motor->u.state.reason);
717                                                 break;
718                                         case AO_LOG_SENSOR:
719                                                 ao_volts("pressure",
720                                                          log_motor->u.sensor.pressure,
721                                                          max_adc, adc_ref,
722                                                          sense_r1, sense_r2);
723                                                 ao_volts("v_batt",
724                                                          log_motor->u.sensor.v_batt,
725                                                          max_adc,
726                                                          adc_ref, batt_r1, batt_r2);
727                                                 printf(" accel %6d",
728                                                        log_motor->u.sensor.accel);
729                                                 printf(" along %6d aross %6d through %6d",
730                                                        log_motor->u.sensor.accel_along,
731                                                        log_motor->u.sensor.accel_across,
732                                                        log_motor->u.sensor.accel_through);
733                                                 break;
734                                         }
735                                         break;
736                                 case AO_LOG_FORMAT_DETHERM:
737                                         break;
738                                 case AO_LOG_FORMAT_EASYMOTOR:
739                                         log_motor = (struct ao_log_motor *) &eeprom->data[pos];
740                                         switch (log_motor->type) {
741                                         case AO_LOG_FLIGHT:
742                                                 printf(" serial %5u flight %5u",
743                                                        eeprom->serial_number,
744                                                        log_motor->u.flight.flight);
745                                                 break;
746                                         case AO_LOG_STATE:
747                                                 ao_state(log_motor->u.state.state,
748                                                          log_motor->u.state.reason);
749                                                 break;
750                                         case AO_LOG_SENSOR:
751                                                 ao_pressure(log_motor->u.sensor.pressure,
752                                                             max_adc, adc_ref,
753                                                             sense_r1, sense_r2,
754                                                             pressure_sensor);
755                                                 ao_volts("v_batt",
756                                                          log_motor->u.sensor.v_batt,
757                                                          max_adc,
758                                                          adc_ref,
759                                                          batt_r1, batt_r2);
760                                                 break;
761                                         }
762                                         break;
763                                 }
764                         }
765                         printf("\n");
766                 }
767         }
768         return ret;
769 }