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 7c5fde500aba3c5d3b935f28d4cdcb5c155e27c5..3c1a17823d595c681cfa61a938e6537093df173f 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 7affbdec193c5726b23e397c3ba31b0ef094860f..812296f33dff04483f08d8ed9ebfb78102096920 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 3e96f3b8e054ef993d6ab20d46a3bdabc11ce300..0095bb732899d81ffa445db1049bc5aece33efcb 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 bcf20ef36fe767c940767a9ee9c20e4499785791..c67b4d8aa6b5f08e696959323bd0af1aef28d851 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 235e609e36675e4ae9ac74e3e9b0973123259ad2..36857f588d5e98fcb634a4d257a3c464a112ba99 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 da57c27feccd612cec6c2d463baf91f527e2c78d..b09ec74b250e4a46c2cf377768130f2f15282af2 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 cfc010a104e5ce4eaf822ae546f24fb480ca9118..12d4dd41fad8856bf5b4dc983b35f90526058e6c 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 736387826ba619e154d57541d335ae9cb5019ba9..dc9da8fdbb9fb00f66102fefb8904019e11b292a 100644 (file)
@@ -113,6 +113,7 @@ altoslib_JAVA = \
        AltosTelemetrySatellite.java \
        AltosTelemetryStandard.java \
        AltosUnitsListener.java \
+       AltosUnknownProduct.java \
        AltosMs5607.java \
        AltosIMU.java \
        AltosMag.java \
index 2f14e2dffa38db5b9bb37c5d5021fa0da9c43133..d789de77191319de63c00b7a0ac3a346ff516dfc 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;