Add Mini logging format. Use in EasyMini
[fw/altos] / altoslib / AltosEepromMiniIterable.java
1 /*
2  * Copyright © 2010 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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package org.altusmetrum.altoslib_1;
19
20 import java.io.*;
21 import java.util.*;
22 import java.text.*;
23
24 public class AltosEepromMiniIterable extends AltosRecordIterable {
25
26         static final int        seen_flight = 1;
27         static final int        seen_sensor = 2;
28
29         static final int        seen_basic = seen_flight|seen_sensor;
30
31         boolean                 has_accel;
32         boolean                 has_gps;
33         boolean                 has_ignite;
34
35         AltosEepromMini flight_record;
36
37         TreeSet<AltosOrderedMiniRecord> records;
38
39         AltosMs5607             baro;
40
41         LinkedList<AltosRecord> list;
42
43         class EepromState {
44                 int     seen;
45                 int     n_pad_samples;
46                 double  ground_pres;
47                 int     boost_tick;
48                 int     sensor_tick;
49
50                 EepromState() {
51                         seen = 0;
52                         n_pad_samples = 0;
53                         ground_pres = 0.0;
54                 }
55         }
56
57         void update_state(AltosRecordMini state, AltosEepromMini record, EepromState eeprom) {
58                 state.tick = record.tick;
59                 switch (record.cmd) {
60                 case AltosLib.AO_LOG_FLIGHT:
61                         eeprom.seen |= seen_flight;
62                         state.ground_pres = record.ground_pres();
63                         state.flight_pres = state.ground_pres;
64                         state.flight = record.data16(0);
65                         eeprom.boost_tick = record.tick;
66                         break;
67                 case AltosLib.AO_LOG_SENSOR:
68                         baro.set(record.pres(), record.temp());
69                         state.pres = baro.pa;
70                         state.temp = baro.cc;
71                         state.sense_m = record.sense_m();
72                         state.sense_a = record.sense_a();
73                         state.v_batt = record.v_batt();
74                         if (state.state < AltosLib.ao_flight_boost) {
75                                 eeprom.n_pad_samples++;
76                                 eeprom.ground_pres += state.pres;
77                                 state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples);
78                                 state.flight_pres = state.ground_pres;
79                         } else {
80                                 state.flight_pres = (state.flight_pres * 15 + state.pres) / 16;
81                         }
82                         if ((eeprom.seen & seen_sensor) == 0)
83                                 eeprom.sensor_tick = record.tick - 1;
84                         eeprom.seen |= seen_sensor;
85                         eeprom.sensor_tick = record.tick;
86                         break;
87                 case AltosLib.AO_LOG_STATE:
88                         state.state = record.state();
89                         break;
90                 case AltosLib.AO_LOG_CONFIG_VERSION:
91                         break;
92                 case AltosLib.AO_LOG_MAIN_DEPLOY:
93                         break;
94                 case AltosLib.AO_LOG_APOGEE_DELAY:
95                         break;
96                 case AltosLib.AO_LOG_RADIO_CHANNEL:
97                         break;
98                 case AltosLib.AO_LOG_CALLSIGN:
99                         state.callsign = record.data;
100                         break;
101                 case AltosLib.AO_LOG_RADIO_CAL:
102                         break;
103                 case AltosLib.AO_LOG_MANUFACTURER:
104                         break;
105                 case AltosLib.AO_LOG_PRODUCT:
106                         break;
107                 case AltosLib.AO_LOG_SERIAL_NUMBER:
108                         state.serial = record.config_a;
109                         break;
110                 case AltosLib.AO_LOG_SOFTWARE_VERSION:
111                         break;
112                 case AltosLib.AO_LOG_BARO_RESERVED:
113                         baro.reserved = record.config_a;
114                         break;
115                 case AltosLib.AO_LOG_BARO_SENS:
116                         baro.sens =record.config_a;
117                         break;
118                 case AltosLib.AO_LOG_BARO_OFF:
119                         baro.off =record.config_a;
120                         break;
121                 case AltosLib.AO_LOG_BARO_TCS:
122                         baro.tcs =record.config_a;
123                         break;
124                 case AltosLib.AO_LOG_BARO_TCO:
125                         baro.tco =record.config_a;
126                         break;
127                 case AltosLib.AO_LOG_BARO_TREF:
128                         baro.tref =record.config_a;
129                         break;
130                 case AltosLib.AO_LOG_BARO_TEMPSENS:
131                         baro.tempsens =record.config_a;
132                         break;
133                 case AltosLib.AO_LOG_BARO_CRC:
134                         baro.crc =record.config_a;
135                         break;
136                 }
137                 state.seen |= eeprom.seen;
138         }
139
140         LinkedList<AltosRecord> make_list() {
141                 LinkedList<AltosRecord>         list = new LinkedList<AltosRecord>();
142                 Iterator<AltosOrderedMiniRecord> iterator = records.iterator();
143                 AltosOrderedMiniRecord          record = null;
144                 AltosRecordMini                 state = new AltosRecordMini();
145                 //boolean                       last_reported = false;
146                 EepromState                     eeprom = new EepromState();
147
148                 state.state = AltosLib.ao_flight_pad;
149
150                 /* Pull in static data from the flight records */
151                 if (flight_record != null)
152                         update_state(state, flight_record, eeprom);
153
154                 while (iterator.hasNext()) {
155                         record = iterator.next();
156                         if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) {
157                                 AltosRecordMini r = state.clone();
158                                 r.time = (r.tick - eeprom.boost_tick) / 100.0;
159                                 list.add(r);
160                         }
161                         update_state(state, record, eeprom);
162                 }
163                 AltosRecordMini r = state.clone();
164                 r.time = (r.tick - eeprom.boost_tick) / 100.0;
165                 list.add(r);
166                 return list;
167         }
168
169         public Iterator<AltosRecord> iterator() {
170                 if (list == null)
171                         list = make_list();
172                 return list.iterator();
173         }
174
175         public boolean has_gps() { return has_gps; }
176         public boolean has_accel() { return has_accel; }
177         public boolean has_ignite() { return has_ignite; }
178
179         public void write_comments(PrintStream out) {
180                 Iterator<AltosOrderedMiniRecord>        iterator = records.iterator();
181                 out.printf("# Comments\n");
182                 while (iterator.hasNext()) {
183                         AltosOrderedMiniRecord  record = iterator.next();
184                         switch (record.cmd) {
185                         case AltosLib.AO_LOG_CONFIG_VERSION:
186                                 out.printf("# Config version: %s\n", record.data);
187                                 break;
188                         case AltosLib.AO_LOG_MAIN_DEPLOY:
189                                 out.printf("# Main deploy: %s\n", record.config_a);
190                                 break;
191                         case AltosLib.AO_LOG_APOGEE_DELAY:
192                                 out.printf("# Apogee delay: %s\n", record.config_a);
193                                 break;
194                         case AltosLib.AO_LOG_RADIO_CHANNEL:
195                                 out.printf("# Radio channel: %s\n", record.config_a);
196                                 break;
197                         case AltosLib.AO_LOG_CALLSIGN:
198                                 out.printf("# Callsign: %s\n", record.data);
199                                 break;
200                         case AltosLib.AO_LOG_ACCEL_CAL:
201                                 out.printf ("# Accel cal: %d %d\n", record.config_a, record.config_b);
202                                 break;
203                         case AltosLib.AO_LOG_RADIO_CAL:
204                                 out.printf ("# Radio cal: %d\n", record.config_a);
205                                 break;
206                         case AltosLib.AO_LOG_MAX_FLIGHT_LOG:
207                                 out.printf ("# Max flight log: %d\n", record.config_a);
208                                 break;
209                         case AltosLib.AO_LOG_MANUFACTURER:
210                                 out.printf ("# Manufacturer: %s\n", record.data);
211                                 break;
212                         case AltosLib.AO_LOG_PRODUCT:
213                                 out.printf ("# Product: %s\n", record.data);
214                                 break;
215                         case AltosLib.AO_LOG_SERIAL_NUMBER:
216                                 out.printf ("# Serial number: %d\n", record.config_a);
217                                 break;
218                         case AltosLib.AO_LOG_SOFTWARE_VERSION:
219                                 out.printf ("# Software version: %s\n", record.data);
220                                 break;
221                         case AltosLib.AO_LOG_BARO_RESERVED:
222                                 out.printf ("# Baro reserved: %d\n", record.config_a);
223                                 break;
224                         case AltosLib.AO_LOG_BARO_SENS:
225                                 out.printf ("# Baro sens: %d\n", record.config_a);
226                                 break;
227                         case AltosLib.AO_LOG_BARO_OFF:
228                                 out.printf ("# Baro off: %d\n", record.config_a);
229                                 break;
230                         case AltosLib.AO_LOG_BARO_TCS:
231                                 out.printf ("# Baro tcs: %d\n", record.config_a);
232                                 break;
233                         case AltosLib.AO_LOG_BARO_TCO:
234                                 out.printf ("# Baro tco: %d\n", record.config_a);
235                                 break;
236                         case AltosLib.AO_LOG_BARO_TREF:
237                                 out.printf ("# Baro tref: %d\n", record.config_a);
238                                 break;
239                         case AltosLib.AO_LOG_BARO_TEMPSENS:
240                                 out.printf ("# Baro tempsens: %d\n", record.config_a);
241                                 break;
242                         case AltosLib.AO_LOG_BARO_CRC:
243                                 out.printf ("# Baro crc: %d\n", record.config_a);
244                                 break;
245                         }
246                 }
247         }
248
249         /*
250          * Read the whole file, dumping records into a RB tree so
251          * we can enumerate them in time order -- the eeprom data
252          * are sometimes out of order
253          */
254         public AltosEepromMiniIterable (FileInputStream input) {
255                 records = new TreeSet<AltosOrderedMiniRecord>();
256
257                 AltosOrderedMiniRecord last_gps_time = null;
258
259                 baro = new AltosMs5607();
260
261                 int index = 0;
262                 int prev_tick = 0;
263                 boolean prev_tick_valid = false;
264                 boolean missing_time = false;
265
266                 try {
267                         for (;;) {
268                                 String line = AltosLib.gets(input);
269                                 if (line == null)
270                                         break;
271                                 AltosOrderedMiniRecord record = new AltosOrderedMiniRecord(line, index++, prev_tick, prev_tick_valid);
272                                 if (record.cmd == AltosLib.AO_LOG_INVALID)
273                                         continue;
274                                 prev_tick = record.tick;
275                                 if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION)
276                                         prev_tick_valid = true;
277                                 if (record.cmd == AltosLib.AO_LOG_FLIGHT) {
278                                         flight_record = record;
279                                         continue;
280                                 }
281
282                                 records.add(record);
283
284                                 /* Bail after reading the 'landed' record; we're all done */
285                                 if (record.cmd == AltosLib.AO_LOG_STATE &&
286                                     record.state() == AltosLib.ao_flight_landed)
287                                         break;
288                         }
289                 } catch (IOException io) {
290                 } catch (ParseException pe) {
291                 }
292                 try {
293                         input.close();
294                 } catch (IOException ie) {
295                 }
296         }
297 }