altoslib: Deal with TeleMetrum v2.0 MMA6555 being inverted
authorKeith Packard <keithp@keithp.com>
Mon, 2 May 2016 23:13:53 +0000 (16:13 -0700)
committerKeith Packard <keithp@keithp.com>
Mon, 2 May 2016 23:18:54 +0000 (16:18 -0700)
Dumping the MMA655X data with the 'A' command provides the raw sensor
value. On TM v2.0 boards, the sensor is inverted, and all of the
firmware uses the inverted value except for the 'dump the raw data'
command. As a result, MonitorIdle was using the un-inverted value and
displaying mystic values.

I've fixed this in the ground station code by checking the product
name and conditionally inverting the value (4095 - value) for
TeleMetrum v2.0 products. Unknown products will generate a warning
dialog on AltosUI so we'll catch places where we've failed to add a
new product name.

Signed-off-by: Keith Packard <keithp@keithp.com>
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
altoslib/AltosConfigData.java
altoslib/AltosIdleFetch.java
altoslib/AltosIdleMonitor.java
altoslib/AltosIdleMonitorListener.java
altoslib/AltosMma655x.java
altoslib/AltosStateUpdate.java
altoslib/AltosUnknownProduct.java [new file with mode: 0644]
altoslib/Makefile.am
altosui/AltosIdleMonitorUI.java

index 7c5fde5..3c1a178 100644 (file)
@@ -700,4 +700,8 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene
 
        public void failed() {
        }
+
+       public void error(String reason) {
+               stop_idle_monitor();
+       }
 }
index 7affbde..812296f 100644 (file)
@@ -476,6 +476,18 @@ public class AltosConfigData implements Iterable<String> {
        }
 
 
+       public boolean mma655x_inverted() throws AltosUnknownProduct {
+               if (product.startsWith("EasyMega-v1"))
+                       return false;
+               if (product.startsWith("TeleMetrum-v2"))
+                       return true;
+               if (product.startsWith("TeleMega-v2"))
+                       return false;
+               if (product.startsWith("TeleMega-v1"))
+                       return false;
+               throw new AltosUnknownProduct(product);
+       }
+
        public void get_values(AltosConfigValues source) throws AltosConfigDataException {
 
                /* HAS_FLIGHT */
index 3e96f3b..0095bb7 100644 (file)
@@ -40,7 +40,7 @@ class AltosIdler {
        static final int        idle_sensor_tmini = 14;
        static final int        idle_sensor_tgps = 15;
 
-       public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
+       public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct {
                for (int idler : idlers) {
                        AltosIdle idle = null;
                        switch (idler) {
@@ -137,8 +137,9 @@ public class AltosIdleFetch implements AltosStateUpdate {
        double                  frequency;
        String                  callsign;
 
-       public void update_state(AltosState state) throws InterruptedException {
+       public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct {
                try {
+                       boolean matched = false;
                        /* Fetch config data from remote */
                        AltosConfigData config_data = new AltosConfigData(link);
                        state.set_state(AltosLib.ao_flight_stateless);
@@ -150,9 +151,12 @@ public class AltosIdleFetch implements AltosStateUpdate {
                        for (AltosIdler idler : idlers) {
                                if (idler.matches(config_data)) {
                                        idler.update_state(state, link, config_data);
+                                       matched = true;
                                        break;
                                }
                        }
+                       if (!matched)
+                               throw new AltosUnknownProduct(config_data.product);
                        state.set_received_time(System.currentTimeMillis());
                } catch (TimeoutException te) {
                }
index bcf20ef..c67b4d8 100644 (file)
@@ -51,7 +51,7 @@ public class AltosIdleMonitor extends Thread {
                return link.reply_abort;
        }
 
-       boolean update_state(AltosState state) throws InterruptedException, TimeoutException {
+       boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct {
                boolean         worked = false;
                boolean         aborted = false;
 
@@ -99,6 +99,8 @@ public class AltosIdleMonitor extends Thread {
                                        update_state(state);
                                        listener.update(state, listener_state);
                                } catch (TimeoutException te) {
+                               } catch (AltosUnknownProduct ae) {
+                                       listener.error(String.format("Unknown product \"%s\"", ae.product));
                                }
                                if (link.has_error || link.reply_abort) {
                                        listener.failed();
index 235e609..36857f5 100644 (file)
@@ -19,5 +19,6 @@ package org.altusmetrum.altoslib_10;
 
 public interface AltosIdleMonitorListener {
        public void update(AltosState state, AltosListenerState listener_state);
+       public void error(String reason);
        public void failed();
 }
index da57c27..b09ec74 100644 (file)
@@ -21,7 +21,7 @@ import java.util.concurrent.*;
 
 public class AltosMma655x implements Cloneable {
 
-       int     accel;
+       private int     accel;
 
        public boolean parse_line(String line) throws NumberFormatException {
                if (line.startsWith("MMA655X value")) {
@@ -45,12 +45,18 @@ public class AltosMma655x implements Cloneable {
                return n;
        }
 
-       static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+       static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct {
                try {
                        AltosMma655x    mma655x = new AltosMma655x(link);
 
-                       if (mma655x != null)
-                               state.set_accel(mma655x.accel);
+                       if (mma655x != null) {
+                               int accel = mma655x.accel;
+                               if (config_data.mma655x_inverted())
+                                       accel = 4095 - accel;
+                               if (config_data.pad_orientation == 1)
+                                       accel = 4095 - accel;
+                               state.set_accel(accel);
+                       }
                } catch (TimeoutException te) {
                } catch (NumberFormatException ne) {
                }
index cfc010a..12d4dd4 100644 (file)
@@ -18,5 +18,5 @@
 package org.altusmetrum.altoslib_10;
 
 public interface AltosStateUpdate {
-       public void     update_state(AltosState state) throws InterruptedException;
-}
\ No newline at end of file
+       public void     update_state(AltosState state) throws InterruptedException, AltosUnknownProduct;
+}
diff --git a/altoslib/AltosUnknownProduct.java b/altoslib/AltosUnknownProduct.java
new file mode 100644 (file)
index 0000000..ff536f5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2010 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_10;
+
+public class AltosUnknownProduct extends Exception {
+       public String product;
+
+       public AltosUnknownProduct (String in_product) {
+               product = in_product;
+       }
+}
index 7363878..dc9da8f 100644 (file)
@@ -113,6 +113,7 @@ altoslib_JAVA = \
        AltosTelemetrySatellite.java \
        AltosTelemetryStandard.java \
        AltosUnitsListener.java \
+       AltosUnknownProduct.java \
        AltosMs5607.java \
        AltosIMU.java \
        AltosMag.java \
index 2f14e2d..d789de7 100644 (file)
@@ -128,6 +128,19 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                SwingUtilities.invokeLater(r);
        }
 
+       public void error(final String reason) {
+               Runnable r = new Runnable() {
+                               public void run() {
+                                       disconnect();
+                                       JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
+                                                                     reason,
+                                                                     "Error fetching data",
+                                                                     JOptionPane.ERROR_MESSAGE);
+                               }
+                       };
+               SwingUtilities.invokeLater(r);
+       }
+
        Container       bag;
        AltosUIFreqList frequencies;
        JTextField      callsign_value;