altoslib, altosui, telegps: Add configuration support for APRS offset
[fw/altos] / altoslib / AltosConfigData.java
index 63c34310f6d12458338d08b2e3a46b8b4cffed06..3c5f6c06678977f6a7790c850e125a543dbc0611 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_12;
+package org.altusmetrum.altoslib_14;
 
 import java.util.*;
 import java.text.*;
 import java.util.concurrent.*;
 
+/* Don't change the field names in this structure; they're part of all .eeprom files */
 public class AltosConfigData {
 
        /* Version information */
@@ -53,6 +54,8 @@ public class AltosConfigData {
 
        /* HAS_ACCEL */
        public int      accel_cal_plus, accel_cal_minus;
+       private int     accel_cal_plus_cooked, accel_cal_minus_cooked;
+       private boolean accel_cal_adjusted;
        public int      pad_orientation;
 
        /* HAS_LOG */
@@ -75,6 +78,7 @@ public class AltosConfigData {
        public int              aprs_interval;
        public int              aprs_ssid;
        public int              aprs_format;
+       public int              aprs_offset;
 
        /* HAS_BEEP */
        public int              beep;
@@ -186,6 +190,26 @@ public class AltosConfigData {
                }
        }
 
+       public int invert_accel_value(int value) {
+               if (value == AltosLib.MISSING)
+                       return AltosLib.MISSING;
+
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_FULL:
+                       return 0x7fff - value;
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+               case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
+                       return 4095 - value;
+               case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
+                       return -value;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
        public boolean has_monitor_battery() {
                if (product.startsWith("TeleBT"))
                        return true;
@@ -252,9 +276,12 @@ public class AltosConfigData {
                radio_setting = AltosLib.MISSING;
                telemetry_rate = AltosLib.MISSING;
 
+               accel_cal_plus_cooked = AltosLib.MISSING;
+               accel_cal_minus_cooked = AltosLib.MISSING;
                accel_cal_plus = AltosLib.MISSING;
                accel_cal_minus = AltosLib.MISSING;
                pad_orientation = AltosLib.MISSING;
+               accel_cal_adjusted = false;
 
                flight_log_max = AltosLib.MISSING;
                log_fixed = AltosLib.MISSING;
@@ -270,6 +297,7 @@ public class AltosConfigData {
                aprs_interval = AltosLib.MISSING;
                aprs_ssid = AltosLib.MISSING;
                aprs_format = AltosLib.MISSING;
+               aprs_offset = AltosLib.MISSING;
 
                beep = AltosLib.MISSING;
 
@@ -285,6 +313,59 @@ public class AltosConfigData {
                accel_zero_through = AltosLib.MISSING;
        }
 
+       /* Return + accel calibration relative to a specific pad orientation */
+       public int accel_cal_plus(int pad_orientation) {
+               adjust_accel_cal();
+               switch (pad_orientation) {
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+                       return accel_cal_plus_cooked;
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+                       return invert_accel_value(accel_cal_minus_cooked);
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       /* Return - accel calibration relative to a specific pad orientation */
+       public int accel_cal_minus(int pad_orientation) {
+               adjust_accel_cal();
+               switch (pad_orientation) {
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+                       return accel_cal_minus_cooked;
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+                       return invert_accel_value(accel_cal_plus_cooked);
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       /* Once we have all of the values from the config data, compute the
+        * accel cal values relative to Antenna Up orientation.
+        */
+       private void adjust_accel_cal() {
+               if (!accel_cal_adjusted &&
+                   pad_orientation != AltosLib.MISSING &&
+                   accel_cal_plus != AltosLib.MISSING &&
+                   accel_cal_minus != AltosLib.MISSING &&
+                   log_format != AltosLib.AO_LOG_FORMAT_UNKNOWN)
+               {
+                       switch (pad_orientation) {
+                       case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+                               accel_cal_plus_cooked = accel_cal_plus;
+                               accel_cal_minus_cooked = accel_cal_minus;
+                               accel_cal_adjusted = true;
+                               break;
+                       case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+                               accel_cal_plus_cooked = invert_accel_value(accel_cal_minus);
+                               accel_cal_minus_cooked = invert_accel_value(accel_cal_plus);
+                               accel_cal_adjusted = true;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
        public void parse_line(String line) {
 
                /* Version replies */
@@ -351,6 +432,7 @@ public class AltosConfigData {
                                if (bits.length >= 6) {
                                        accel_cal_plus = Integer.parseInt(bits[3]);
                                        accel_cal_minus = Integer.parseInt(bits[5]);
+                                       accel_cal_adjusted = false;
                                }
                        }
                } catch (Exception e) {}
@@ -385,6 +467,7 @@ public class AltosConfigData {
                try { aprs_interval = get_int(line, "APRS interval:"); } catch (Exception e) {}
                try { aprs_ssid = get_int(line, "APRS SSID:"); } catch (Exception e) {}
                try { aprs_format = get_int(line, "APRS format:"); } catch (Exception e) {}
+               try { aprs_offset = get_int(line, "APRS offset:"); } catch (Exception e) {}
 
                /* HAS_BEEP */
                try { beep = get_int(line, "Beeper setting:"); } catch (Exception e) {}
@@ -405,7 +488,7 @@ public class AltosConfigData {
 
                /* HAS_GYRO */
                try {
-                       if (line.startsWith("IMU call along")) {
+                       if (line.startsWith("IMU cal along")) {
                                String[] bits = line.split("\\s+");
                                if (bits.length >= 8) {
                                        accel_zero_along = Integer.parseInt(bits[3]);
@@ -414,6 +497,9 @@ public class AltosConfigData {
                                }
                        }
                } catch (Exception e) {}
+
+               /* Fix accel cal as soon as all of the necessary values appear */
+               adjust_accel_cal();
        }
 
        public AltosConfigData() {
@@ -481,6 +567,8 @@ public class AltosConfigData {
                        return false;
                if (product.startsWith("TeleMetrum-v2"))
                        return false;
+               if (product.startsWith("TeleMetrum-v3"))
+                       return false;
                if (product.startsWith("EasyMega"))
                        return false;
                return true;
@@ -501,6 +589,30 @@ public class AltosConfigData {
                throw new AltosUnknownProduct(product);
        }
 
+       public boolean adxl375_inverted() throws AltosUnknownProduct {
+               if (product != null) {
+                       if (product.startsWith("EasyMega-v2"))
+                               return true;
+                       if (product.startsWith("TeleMetrum-v3"))
+                               return true;
+                       if (product.startsWith("TeleMega-v4"))
+                               return true;
+               }
+               throw new AltosUnknownProduct(product);
+       }
+
+       public int adxl375_axis() throws AltosUnknownProduct {
+               if (product != null) {
+                       if (product.startsWith("EasyMega-v2"))
+                               return AltosAdxl375.X_AXIS;
+                       if (product.startsWith("TeleMetrum-v3"))
+                               return AltosAdxl375.X_AXIS;
+                       if (product.startsWith("TeleMega-v4"))
+                               return AltosAdxl375.X_AXIS;
+               }
+               throw new AltosUnknownProduct(product);
+       }
+
        public void get_values(AltosConfigValues source) throws AltosConfigDataException {
 
                /* HAS_FLIGHT */
@@ -525,6 +637,12 @@ public class AltosConfigData {
                if (pad_orientation != AltosLib.MISSING)
                        pad_orientation = source.pad_orientation();
 
+               if (accel_cal_plus_cooked != AltosLib.MISSING)
+                       accel_cal_plus_cooked = source.accel_cal_plus();
+
+               if (accel_cal_minus_cooked != AltosLib.MISSING)
+                       accel_cal_minus_cooked = source.accel_cal_minus();
+
                /* HAS_LOG */
                if (flight_log_max != AltosLib.MISSING)
                        flight_log_max = source.flight_log_max();
@@ -546,6 +664,8 @@ public class AltosConfigData {
                        aprs_ssid = source.aprs_ssid();
                if (aprs_format != AltosLib.MISSING)
                        aprs_format = source.aprs_format();
+               if (aprs_offset != AltosLib.MISSING)
+                       aprs_offset = source.aprs_offset();
 
                /* HAS_BEEP */
                if (beep != AltosLib.MISSING)
@@ -592,6 +712,8 @@ public class AltosConfigData {
                dest.set_flight_log_max(flight_log_max);
                dest.set_ignite_mode(ignite_mode);
                dest.set_pad_orientation(pad_orientation);
+               dest.set_accel_cal(accel_cal_plus(AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP),
+                                  accel_cal_minus(AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP));
                dest.set_callsign(callsign);
                if (npyro != AltosLib.MISSING)
                        dest.set_pyros(pyros);
@@ -601,6 +723,7 @@ public class AltosConfigData {
                dest.set_aprs_interval(aprs_interval);
                dest.set_aprs_ssid(aprs_ssid);
                dest.set_aprs_format(aprs_format);
+               dest.set_aprs_offset(aprs_offset);
                dest.set_beep(beep);
                dest.set_tracker_motion(tracker_motion);
                dest.set_tracker_interval(tracker_interval);
@@ -669,9 +792,13 @@ public class AltosConfigData {
                        link.printf("c e %d\n", radio_enable);
 
                /* HAS_ACCEL */
-               /* UI doesn't support accel cal */
+               /* set orientation first so that we know how to set the accel cal */
                if (pad_orientation != AltosLib.MISSING)
                        link.printf("c o %d\n", pad_orientation);
+               int plus = accel_cal_plus(pad_orientation);
+               int minus = accel_cal_minus(pad_orientation);
+               if (plus != AltosLib.MISSING && minus != AltosLib.MISSING)
+                       link.printf("c a %d %d\n", plus, minus);
 
                /* HAS_LOG */
                if (flight_log_max != 0)
@@ -701,6 +828,8 @@ public class AltosConfigData {
                        link.printf("c S %d\n", aprs_ssid);
                if (aprs_format != AltosLib.MISSING)
                        link.printf("c C %d\n", aprs_format);
+               if (aprs_offset != AltosLib.MISSING)
+                       link.printf("c O %d\n", aprs_offset);
 
                /* HAS_BEEP */
                if (beep != AltosLib.MISSING)