altoslib: Support TeleMega v5.0
[fw/altos] / altoslib / AltosEepromRecordMega.java
1 /*
2  * Copyright © 2017 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
15 package org.altusmetrum.altoslib_14;
16
17 public class AltosEepromRecordMega extends AltosEepromRecord {
18         public static final int record_length = 32;
19
20         public static final int max_sat = 12;
21
22         private int log_format;
23
24         /* AO_LOG_FLIGHT elements */
25         private int flight() { return data16(0); }
26         private int ground_accel() { return data16(2); }
27         private int ground_pres() { return data32(4); }
28         private int ground_accel_along() { return data16(8); }
29         private int ground_accel_across() { return data16(10); }
30         private int ground_accel_through() { return data16(12); }
31         private int ground_roll() {
32                 switch (log_format) {
33                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
34                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
35                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
36                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
37                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
38                         return data32(16);
39                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
40                         return data16(14);
41                 default:
42                         return AltosLib.MISSING;
43                 }
44         }
45         private int ground_pitch() {
46                 switch (log_format) {
47                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
48                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
49                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
50                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
51                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
52                         return data32(20);
53                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
54                         return data16(16);
55                 default:
56                         return AltosLib.MISSING;
57                 }
58         }
59         private int ground_yaw() {
60                 switch (log_format) {
61                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
62                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
63                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
64                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
65                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
66                         return data32(24);
67                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
68                         return data16(18);
69                 default:
70                         return AltosLib.MISSING;
71                 }
72         }
73
74         /* AO_LOG_STATE elements */
75         private int state() { return data16(0); }
76         private int reason() { return data16(2); }
77
78         /* AO_LOG_SENSOR elements */
79         private int pres() { return data32(0); }
80         private int temp() { return data32(4); }
81         private int accel_x() { return data16(8); }
82         private int accel_y() { return data16(10); }
83         private int accel_z() { return data16(12); }
84         private int gyro_x() { return data16(14); }
85         private int gyro_y() { return data16(16); }
86         private int gyro_z() { return data16(18); }
87         private int mag_x() { return data16(20); }
88         private int mag_z() { return data16(22); }
89         private int mag_y() { return data16(24); }
90
91         /* normalized log data */
92         private int norm_accel_along() { return data16(8); }
93         private int norm_accel_across() { return data16(10); }
94         private int norm_accel_through() { return data16(12); }
95         private int norm_gyro_roll() { return data16(14); }
96         private int norm_gyro_pitch() { return data16(16); }
97         private int norm_gyro_yaw() { return data16(18); }
98         private int norm_mag_along() { return data16(20); }
99         private int norm_mag_across() { return data16(22); }
100         private int norm_mag_through() { return data16(24); }
101
102         private int imu_type() {
103                 switch (log_format) {
104                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
105                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
106                         return AltosIMU.imu_type_telemega_v1_v2;
107                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
108                         return AltosIMU.imu_type_telemega_v3;
109                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
110                         return AltosIMU.imu_type_easymega_v2;
111                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
112                         return AltosIMU.imu_type_telemega_v4;
113                 default:
114                         return AltosLib.MISSING;
115                 }
116         }
117
118         private int imu_model() {
119                 switch (log_format) {
120                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
121                         return AltosLib.model_mpu6000;
122                 }
123                 return AltosLib.MISSING;
124         }
125
126         private boolean sensor_normalized() {
127                 switch (log_format) {
128                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
129                         return true;
130                 }
131                 return false;
132         }
133
134         private int mag_model() {
135                 switch (log_format) {
136                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
137                         return AltosLib.model_mmc5983;
138                 }
139                 return AltosLib.MISSING;
140         }
141
142         private int accel_across() {
143                 if (sensor_normalized()) {
144                         return norm_accel_across();
145                 }
146
147                 switch (log_format) {
148                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
149                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
150                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
151                         return accel_x();
152                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
153                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
154                         return -accel_y();
155                 default:
156                         return AltosLib.MISSING;
157                 }
158         }
159
160         private int accel_along(){
161                 if (sensor_normalized()) {
162                         return norm_accel_along();
163                 }
164
165                 switch (log_format) {
166                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
167                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
168                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
169                         return accel_y();
170                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
171                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
172                         return accel_x();
173                 default:
174                         return AltosLib.MISSING;
175                 }
176         }
177
178         private int accel_through() {
179                 if (sensor_normalized()) {
180                         return norm_accel_through();
181                 }
182
183                 return accel_z();
184         }
185
186         private int gyro_pitch() {
187                 if (sensor_normalized()) {
188                         return norm_gyro_pitch();
189                 }
190
191                 switch (log_format) {
192                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
193                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
194                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
195                         return gyro_x();
196                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
197                         return -gyro_y();
198                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
199                         return -gyro_y();
200                 default:
201                         return AltosLib.MISSING;
202                 }
203         }
204
205         private int gyro_roll() {
206                 if (sensor_normalized()) {
207                         return norm_gyro_roll();
208                 }
209
210                 switch (log_format) {
211                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
212                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
213                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
214                         return gyro_y();
215                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
216                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
217                         return gyro_x();
218                 default:
219                         return AltosLib.MISSING;
220                 }
221         }
222
223         private int gyro_yaw() {
224                 if (sensor_normalized()) {
225                         return norm_gyro_yaw();
226                 }
227
228                 return gyro_z();
229         }
230
231         private int mag_across() {
232                 if (sensor_normalized()) {
233                         return norm_mag_across();
234                 }
235
236                 switch (log_format) {
237                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
238                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
239                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
240                         return mag_x();
241                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
242                         return -mag_y();
243                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
244                         return mag_y();
245                 default:
246                         return AltosLib.MISSING;
247                 }
248         }
249
250         private int mag_along() {
251                 if (sensor_normalized()) {
252                         return norm_mag_along();
253                 }
254
255                 switch (log_format) {
256                 case AltosLib.AO_LOG_FORMAT_TELEMEGA:
257                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
258                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
259                         return mag_y();
260                 case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
261                 case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
262                         return mag_x();
263                 default:
264                         return AltosLib.MISSING;
265                 }
266         }
267
268         private int mag_through() {
269                 if (sensor_normalized()) {
270                         return norm_mag_through();
271                 }
272
273                 return mag_z();
274         }
275
276
277         private int accel() { return data16(26); }
278
279         /* AO_LOG_TEMP_VOLT elements */
280         private int v_batt() { return data16(0); }
281         private int v_pbatt() { return data16(2); }
282         private int nsense() { return data16(4); }
283         private int sense(int i) { return data16(6 + i * 2); }
284         private int pyro() { return data16(26); }
285
286         /* AO_LOG_GPS_TIME elements */
287         private int latitude() { return data32(0); }
288         private int longitude() { return data32(4); }
289         private int altitude_low() { return data16(8); }
290         private int hour() { return data8(10); }
291         private int minute() { return data8(11); }
292         private int second() { return data8(12); }
293         private int flags() { return data8(13); }
294         private int year() { return data8(14); }
295         private int month() { return data8(15); }
296         private int day() { return data8(16); }
297         private int course() { return data8(17); }
298         private int ground_speed() { return data16(18); }
299         private int climb_rate() { return data16(20); }
300         private int pdop() { return data8(22); }
301         private int hdop() { return data8(23); }
302         private int vdop() { return data8(24); }
303         private int mode() { return data8(25); }
304         private int altitude_high() { return data16(26); }
305
306         /* AO_LOG_GPS_SAT elements */
307         private int nsat() { return data16(0); }
308         private int svid(int n) { return data8(2 + n * 2); }
309         private int c_n(int n) { return data8(2 + n * 2 + 1); }
310
311         public void provide_data(AltosDataListener listener, AltosCalData cal_data) {
312                 super.provide_data(listener, cal_data);
313
314                 AltosGPS        gps;
315
316                 cal_data.set_imu_type(imu_type());
317                 cal_data.set_imu_model(imu_model());
318                 cal_data.set_mag_model(mag_model());
319
320                 switch (cmd()) {
321                 case AltosLib.AO_LOG_FLIGHT:
322                         cal_data.set_flight(flight());
323                         cal_data.set_ground_accel(ground_accel());
324                         cal_data.set_ground_pressure(ground_pres());
325                         listener.set_accel_ground(cal_data.accel_along(ground_accel_along()),
326                                                   cal_data.accel_across(ground_accel_across()),
327                                                   cal_data.accel_through(ground_accel_through()));
328                         cal_data.set_gyro_zero(ground_roll() / 512.0,
329                                                ground_pitch() / 512.0,
330                                                ground_yaw() / 512.0);
331                         break;
332                 case AltosLib.AO_LOG_STATE:
333                         listener.set_state(state());
334                         break;
335                 case AltosLib.AO_LOG_SENSOR:
336                         AltosConfigData config_data = eeprom.config_data();
337                         AltosPresTemp pt = config_data.ms5607().pres_temp(pres(), temp());;
338                         listener.set_pressure(pt.pres);
339                         listener.set_temperature(pt.temp);
340
341                         int     accel_along = accel_along();
342                         int     accel_across = accel_across();
343                         int     accel_through = accel_through();
344                         int     gyro_roll = gyro_roll();
345                         int     gyro_pitch = gyro_pitch();
346                         int     gyro_yaw = gyro_yaw();
347
348                         int     mag_along = mag_along();
349                         int     mag_across = mag_across();
350                         int     mag_through = mag_through();
351
352                         if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD)
353                                 cal_data.check_imu_wrap(gyro_roll, gyro_pitch, gyro_yaw);
354
355                         listener.set_accel(cal_data.accel_along(accel_along),
356                                            cal_data.accel_across(accel_across),
357                                            cal_data.accel_through(accel_through));
358                         listener.set_gyro(cal_data.gyro_roll(gyro_roll),
359                                           cal_data.gyro_pitch(gyro_pitch),
360                                           cal_data.gyro_yaw(gyro_yaw));
361
362                         listener.set_mag(cal_data.mag_along(mag_along),
363                                          cal_data.mag_across(mag_across),
364                                          cal_data.mag_through(mag_through));
365
366                         listener.set_acceleration(cal_data.acceleration(accel()));
367                         break;
368                 case AltosLib.AO_LOG_TEMP_VOLT:
369                         listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
370                         listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt()));
371
372                         int nsense = nsense();
373
374                         listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2)));
375                         listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1)));
376
377                         double voltages[] = new double[nsense-2];
378                         for (int i = 0; i < nsense-2; i++)
379                                 voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
380
381                         listener.set_igniter_voltage(voltages);
382                         listener.set_pyro_fired(pyro());
383                         break;
384                 case AltosLib.AO_LOG_GPS_TIME:
385                         gps = listener.make_temp_gps(false);
386                         gps.lat = latitude() / 1e7;
387                         gps.lon = longitude() / 1e7;
388
389                         if (config_data().altitude_32())
390                                 gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
391                         else
392                                 gps.alt = altitude_low();
393
394                         gps.hour = hour();
395                         gps.minute = minute();
396                         gps.second = second();
397
398                         int flags = flags();
399
400                         gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0;
401                         gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0;
402                         gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >>
403                                 AltosLib.AO_GPS_NUM_SAT_SHIFT;
404
405                         gps.year = 2000 + year();
406                         gps.month = month();
407                         gps.day = day();
408                         gps.ground_speed = ground_speed() * 1.0e-2;
409                         gps.course = course() * 2;
410                         gps.climb_rate = climb_rate() * 1.0e-2;
411                         if (config_data().compare_version("1.4.9") >= 0) {
412                                 gps.pdop = pdop() / 10.0;
413                                 gps.hdop = hdop() / 10.0;
414                                 gps.vdop = vdop() / 10.0;
415                         } else {
416                                 gps.pdop = pdop() / 100.0;
417                                 if (gps.pdop < 0.8)
418                                         gps.pdop += 2.56;
419                                 gps.hdop = hdop() / 100.0;
420                                 if (gps.hdop < 0.8)
421                                         gps.hdop += 2.56;
422                                 gps.vdop = vdop() / 100.0;
423                                 if (gps.vdop < 0.8)
424                                         gps.vdop += 2.56;
425                         }
426                         break;
427                 case AltosLib.AO_LOG_GPS_SAT:
428                         gps = listener.make_temp_gps(true);
429
430                         int n = nsat();
431                         if (n > max_sat)
432                                 n = max_sat;
433                         for (int i = 0; i < n; i++)
434                                 gps.add_sat(svid(i), c_n(i));
435                         break;
436                 }
437         }
438
439         public AltosEepromRecord next() {
440                 int     s = next_start();
441                 if (s < 0)
442                         return null;
443                 return new AltosEepromRecordMega(eeprom, s);
444         }
445
446         public AltosEepromRecordMega(AltosEeprom eeprom, int start) {
447                 super(eeprom, start, record_length);
448                 log_format = eeprom.config_data().log_format;
449         }
450
451         public AltosEepromRecordMega(AltosEeprom eeprom) {
452                 this(eeprom, 0);
453         }
454 }