Merge remote-tracking branch 'mjb/altosdroid'
authorKeith Packard <keithp@keithp.com>
Tue, 23 Oct 2012 05:39:31 +0000 (22:39 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 23 Oct 2012 05:39:31 +0000 (22:39 -0700)
14 files changed:
altoslib/AltosConfigData.java
altoslib/AltosLib.java
altoslib/AltosPyro.java [new file with mode: 0644]
altoslib/Makefile.am
altosui/AltosConfig.java
altosui/AltosConfigPyroUI.java [new file with mode: 0644]
altosui/AltosConfigUI.java
altosui/AltosDialog.java
altosui/Makefile.am
src/avr/ao_arch.h
src/avr/ao_pins.h
src/core/ao_pyro.c
src/core/ao_pyro.h
src/util/check-avr-mem [changed mode: 0644->0755]

index a962b1058ed5da60b9b4682a337839ba37ba2aeb..45a88783ad3a4a5e33fa023188804a66da6d077f 100644 (file)
@@ -50,6 +50,8 @@ public class AltosConfigData implements Iterable<String> {
        public int      storage_size;
        public int      storage_erase_unit;
 
+       public AltosPyro[]      pyros;
+
        public static String get_string(String line, String label) throws  ParseException {
                if (line.startsWith(label)) {
                        String  quoted = line.substring(label.length()).trim();
@@ -135,6 +137,10 @@ public class AltosConfigData implements Iterable<String> {
                radio_frequency = 0;
                stored_flight = 0;
                serial = -1;
+               pyros = null;
+
+               int npyro = 0;
+               int pyro = 0;
                for (;;) {
                        String line = link.get_reply();
                        if (line == null)
@@ -142,6 +148,16 @@ public class AltosConfigData implements Iterable<String> {
                        if (line.contains("Syntax error"))
                                continue;
                        lines.add(line);
+                       if (pyro < npyro - 1) {
+                               if (pyros == null)
+                                       pyros = new AltosPyro[npyro];
+                               try {
+                                       pyros[pyro] = new AltosPyro(pyro, line);
+                               } catch (ParseException e) {
+                               }
+                               ++pyro;
+                               continue;
+                       }
                        try { serial = get_int(line, "serial-number"); } catch (Exception e) {}
                        try { log_format = get_int(line, "log-format"); } catch (Exception e) {}
                        try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {}
@@ -173,6 +189,7 @@ public class AltosConfigData implements Iterable<String> {
                        try { get_int(line, "flight"); stored_flight++; }  catch (Exception e) {}
                        try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {}
                        try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {}
+                       try { npyro = get_int(line, "Pyro-count:"); pyro = 0; } catch (Exception e) {}
 
                        /* signals the end of the version info */
                        if (line.startsWith("software-version"))
index 192c445e0c42dabe2b9e3c42a209fe8843e9269c..07516aebd389fe3af4fcac245ffb42fa25ef8b1c 100644 (file)
@@ -199,7 +199,7 @@ public class AltosLib {
 
        public static String state_name_capital(int state) {
                if (state < 0 || state_to_string.length <= state)
-                       return "invalid";
+                       return "Invalid";
                return state_to_string_capital[state];
        }
 
diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java
new file mode 100644 (file)
index 0000000..1405116
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright © 2012 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;
+
+import java.util.*;
+import java.text.*;
+import java.util.concurrent.*;
+
+public class AltosPyro {
+       public static final int pyro_none                       = 0x00000000;
+
+       public static final int pyro_accel_less                 = 0x00000001;
+       public static final int pyro_accel_greater              = 0x00000002;
+       public static final String pyro_accel_less_string       = "a<";
+       public static final String pyro_accel_greater_string    = "a>";
+       public static final String pyro_accel_less_name         = "Acceleration less than (m/s²)";
+       public static final String pyro_accel_greater_name      = "Acceleration greater than (m/s²)";
+       public static final double pyro_accel_scale             = 16.0;
+
+       public static final int pyro_speed_less                 = 0x00000004;
+       public static final int pyro_speed_greater              = 0x00000008;
+       public static final String pyro_speed_less_string       = "s<";
+       public static final String pyro_speed_greater_string    = "s>";
+       public static final String pyro_speed_less_name         = "Speed less than (m/s)";
+       public static final String pyro_speed_greater_name      = "Speed greater than (m/s)";
+       public static final double pyro_speed_scale             = 16.0;
+
+       public static final int pyro_height_less                = 0x00000010;
+       public static final int pyro_height_greater             = 0x00000020;
+       public static final String pyro_height_less_string      = "h<";
+       public static final String pyro_height_greater_string   = "h>";
+       public static final String pyro_height_less_name        = "Height less than (m)";
+       public static final String pyro_height_greater_name     = "Height greater than (m)";
+       public static final double pyro_height_scale            = 1.0;
+
+       public static final int pyro_orient_less                = 0x00000040;
+       public static final int pyro_orient_greater             = 0x00000080;
+       public static final String pyro_orient_less_string      = "o<";
+       public static final String pyro_orient_greater_string   = "o>";
+       public static final String pyro_orient_less_name        = "Angle from vertical less than (degrees)";
+       public static final String pyro_orient_greater_name     = "Angle from vertical greater than (degrees)";
+       public static final double pyro_orient_scale            = 1.0;
+
+       public static final int pyro_time_less                  = 0x00000100;
+       public static final int pyro_time_greater               = 0x00000200;
+       public static final String pyro_time_less_string        = "t<";
+       public static final String pyro_time_greater_string     = "t>";
+       public static final String pyro_time_less_name          = "Time since boost less than (s)";
+       public static final String pyro_time_greater_name       = "Time since boost greater than (s)";
+       public static final double pyro_time_scale              = 100.0;
+
+       public static final int pyro_ascending                  = 0x00000400;
+       public static final int pyro_descending                 = 0x00000800;
+       public static final String pyro_ascending_string        = "A";
+       public static final String pyro_descending_string       = "D";
+       public static final String pyro_ascending_name          = "Ascending";
+       public static final String pyro_descending_name         = "Descending";
+
+       public static final int pyro_after_motor                = 0x00001000;
+       public static final String pyro_after_motor_string      = "m";
+       public static final String pyro_after_motor_name        = "After motor number";
+       public static final double pyro_after_motor_scale       = 1.0;
+
+       public static final int pyro_delay                      = 0x00002000;
+       public static final String pyro_delay_string            = "d";
+       public static final String pyro_delay_name              = "Delay after other conditions (s)";
+       public static final double pyro_delay_scale             = 100.0;
+
+       public static final int pyro_state_less                 = 0x00004000;
+       public static final int pyro_state_greater_or_equal     = 0x00008000;
+       public static final String pyro_state_less_string       = "f<";
+       public static final String pyro_state_greater_or_equal_string   = "f>=";
+       public static final String pyro_state_less_name         = "Flight state before";
+       public static final String pyro_state_greater_or_equal_name     = "Flight state after";
+       public static final double pyro_state_scale             = 1.0;
+
+       public static final int pyro_all                        = 0x0000ffff;
+
+       public static final int pyro_no_value                   = (pyro_ascending |
+                                                                  pyro_descending);
+
+       public static final int pyro_state_value                = pyro_state_less | pyro_state_greater_or_equal;
+
+       private static HashMap<String,Integer> string_to_pyro = new HashMap<String,Integer>();
+
+       private static HashMap<Integer,String> pyro_to_string = new HashMap<Integer,String>();
+
+       private static HashMap<Integer,String> pyro_to_name = new HashMap<Integer,String>();
+
+       private static HashMap<Integer,Double> pyro_to_scale = new HashMap<Integer,Double>();
+       
+       private static void insert_map(int flag, String string, String name, double scale) {
+               string_to_pyro.put(string, flag);
+               pyro_to_string.put(flag, string);
+               pyro_to_name.put(flag, name);
+               pyro_to_scale.put(flag, scale);
+       }
+       
+       public static int string_to_pyro(String name) {
+               if (string_to_pyro.containsKey(name))
+                       return string_to_pyro.get(name);
+               return pyro_none;
+       }
+
+       public static String pyro_to_string(int flag) {
+               if (pyro_to_string.containsKey(flag))
+                       return pyro_to_string.get(flag);
+               return null;
+       }
+
+       public static String pyro_to_name(int flag) {
+               if (pyro_to_name.containsKey(flag))
+                       return pyro_to_name.get(flag);
+               return null;
+       }
+
+       public static double pyro_to_scale(int flag) {
+               if (pyro_to_scale.containsKey(flag))
+                       return pyro_to_scale.get(flag);
+               return 1.0;
+       }
+
+       private static void initialize_maps() {
+               insert_map(pyro_accel_less, pyro_accel_less_string, pyro_accel_less_name, pyro_accel_scale);
+               insert_map(pyro_accel_greater, pyro_accel_greater_string, pyro_accel_greater_name, pyro_accel_scale);
+
+               insert_map(pyro_speed_less, pyro_speed_less_string, pyro_speed_less_name, pyro_speed_scale);
+               insert_map(pyro_speed_greater, pyro_speed_greater_string, pyro_speed_greater_name, pyro_speed_scale);
+
+               insert_map(pyro_height_less, pyro_height_less_string, pyro_height_less_name, pyro_height_scale);
+               insert_map(pyro_height_greater, pyro_height_greater_string, pyro_height_greater_name, pyro_height_scale);
+
+               insert_map(pyro_orient_less, pyro_orient_less_string, pyro_orient_less_name, pyro_orient_scale);
+               insert_map(pyro_orient_greater, pyro_orient_greater_string, pyro_orient_greater_name, pyro_orient_scale);
+
+               insert_map(pyro_time_less, pyro_time_less_string, pyro_time_less_name, pyro_time_scale);
+               insert_map(pyro_time_greater, pyro_time_greater_string, pyro_time_greater_name, pyro_time_scale);
+
+               insert_map(pyro_ascending, pyro_ascending_string, pyro_ascending_name, 1.0);
+               insert_map(pyro_descending, pyro_descending_string, pyro_descending_name, 1.0);
+
+               insert_map(pyro_after_motor, pyro_after_motor_string, pyro_after_motor_name, 1.0);
+               insert_map(pyro_delay, pyro_delay_string, pyro_delay_name, pyro_delay_scale);
+               
+               insert_map(pyro_state_less, pyro_state_less_string, pyro_state_less_name, 1.0);
+               insert_map(pyro_state_greater_or_equal, pyro_state_greater_or_equal_string, pyro_state_greater_or_equal_name, 1.0);
+       }
+
+       {
+               initialize_maps();
+       }
+
+       public int      channel;
+       public int      flags;
+       public int      accel_less, accel_greater;
+       public int      speed_less, speed_greater;
+       public int      height_less, height_greater;
+       public int      orient_less, orient_greater;
+       public int      time_less, time_greater;
+       public int      delay;
+       public int      state_less, state_greater_or_equal;
+       public int      motor;
+
+       public AltosPyro(int in_channel) {
+               channel = in_channel;
+               flags = 0;
+       }
+
+       private boolean set_ivalue(int flag, int value) {
+               switch (flag) {
+               case pyro_accel_less:                   accel_less = value; break;
+               case pyro_accel_greater:                accel_greater = value; break;
+               case pyro_speed_less:                   speed_less = value; break;
+               case pyro_speed_greater:                speed_greater = value; break;
+               case pyro_height_less:                  height_less = value; break;
+               case pyro_height_greater:               height_greater = value; break;
+               case pyro_orient_less:                  orient_less = value; break;
+               case pyro_orient_greater:               orient_greater = value; break;
+               case pyro_time_less:                    time_less = value; break;
+               case pyro_time_greater:                 time_greater = value; break;
+               case pyro_after_motor:                  motor = value; break;
+               case pyro_delay:                        delay = value; break;
+               case pyro_state_less:                   state_less = value; break;
+               case pyro_state_greater_or_equal:       state_greater_or_equal = value; break;
+               default:
+                       return false;
+               }
+               return true;
+       }
+
+       public boolean set_value(int flag, double dvalue) {
+               return set_ivalue(flag, (int) (dvalue * pyro_to_scale(flag)));
+       }
+
+       private int get_ivalue (int flag) {
+               int     value;
+
+               switch (flag) {
+               case pyro_accel_less:                   value = accel_less; break;
+               case pyro_accel_greater:                value = accel_greater; break;
+               case pyro_speed_less:                   value = speed_less; break;
+               case pyro_speed_greater:                value = speed_greater; break;
+               case pyro_height_less:                  value = height_less; break;
+               case pyro_height_greater:               value = height_greater; break;
+               case pyro_orient_less:                  value = orient_less; break;
+               case pyro_orient_greater:               value = orient_greater; break;
+               case pyro_time_less:                    value = time_less; break;
+               case pyro_time_greater:                 value = time_greater; break;
+               case pyro_after_motor:                  value = motor; break;
+               case pyro_delay:                        value = delay; break;
+               case pyro_state_less:                   value = state_less; break;
+               case pyro_state_greater_or_equal:       value = state_greater_or_equal; break;
+               default:                                value = 0; break;
+               }
+               return value;
+       }
+
+       public double get_value(int flag) {
+               return get_ivalue(flag) / pyro_to_scale(flag);
+       }
+
+       public AltosPyro(int in_channel, String line) throws ParseException {
+               String[] tokens = line.split("\\s+");
+
+               channel = in_channel;
+               flags = 0;
+
+               int i = 0;
+               if (tokens[i].equals("Pyro"))
+                       i += 2;
+
+               for (; i < tokens.length; i++) {
+
+                       if (tokens[i].equals("<disabled>"))
+                               break;
+
+                       int     flag = string_to_pyro(tokens[i]);
+                       if (flag == pyro_none)
+                               throw new ParseException(String.format("Invalid pyro token \"%s\"",
+                                                                      tokens[i]), i);
+                       flags |= flag;
+
+                       if ((flag & pyro_no_value) == 0) {
+                               int     value = 0;
+                               ++i;
+                               try {
+                                       value = AltosLib.fromdec(tokens[i]);
+                               } catch (NumberFormatException n) {
+                                       throw new ParseException(String.format("Invalid pyro value \"%s\"",
+                                                                              tokens[i]), i);
+                               }
+                               if (!set_ivalue(flag, value))
+                                       throw new ParseException(String.format("Internal parser error \"%s\" \"%s\"",
+                                                                              tokens[i-1], tokens[i]), i-1);
+                       }
+               }
+       }
+
+       public String toString() {
+               String  ret = String.format("%d", channel);
+
+               for (int flag = 1; flag <= flags; flag <<= 1) {
+                       if ((flags & flag) != 0) {
+                               String  add;
+                               if ((flag & pyro_no_value) == 0) {
+                                       add = String.format(" %s %d",
+                                                           pyro_to_string.get(flag),
+                                                           get_ivalue(flag));
+                               } else {
+                                       add = String.format(" %s",
+                                                           pyro_to_string.get(flag));
+                               }
+                               ret = ret.concat(add);
+                       }
+               }
+               return ret;
+       }
+}
index f04c10c6aa7392798efe7143a3ee294d3be4e7d7..2579a65030a625a89784ab6876fbd97908e02886 100644 (file)
@@ -75,7 +75,8 @@ AltosLib_JAVA = \
        $(SRC)/AltosDistance.java \
        $(SRC)/AltosHeight.java \
        $(SRC)/AltosSpeed.java \
-       $(SRC)/AltosAccel.java
+       $(SRC)/AltosAccel.java \
+       $(SRC)/AltosPyro.java
 
 JAR=AltosLib.jar
 
index 44e5a3faf4c5265414476cbc0bc31464543c5a4a..44c6239af278821f0d229bd29e5d4eb2cdddb17b 100644 (file)
@@ -22,6 +22,7 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import org.altusmetrum.AltosLib.*;
+import java.text.*;
 
 public class AltosConfig implements ActionListener {
 
@@ -78,6 +79,8 @@ public class AltosConfig implements ActionListener {
        string_ref      version;
        string_ref      product;
        string_ref      callsign;
+       int_ref         npyro;
+       AltosPyro[]     pyros;
        AltosConfigUI   config_ui;
        boolean         serial_started;
        boolean         made_visible;
@@ -162,6 +165,8 @@ public class AltosConfig implements ActionListener {
                config_ui.set_ignite_mode(ignite_mode.get());
                config_ui.set_pad_orientation(pad_orientation.get());
                config_ui.set_callsign(callsign.get());
+               config_ui.set_pyros(pyros);
+               config_ui.set_has_pyro(npyro.get() > 0);
                config_ui.set_clean();
                if (!made_visible) {
                        made_visible = true;
@@ -169,6 +174,8 @@ public class AltosConfig implements ActionListener {
                }
        }
 
+       int     pyro;
+
        void process_line(String line) {
                if (line == null) {
                        abort();
@@ -179,6 +186,18 @@ public class AltosConfig implements ActionListener {
                                update_ui();
                        return;
                }
+               if (pyro < npyro.get()) {
+                       if (pyros == null)
+                               pyros = new AltosPyro[npyro.get()];
+
+                       try {
+                               pyros[pyro] = new AltosPyro(pyro, line);
+                       } catch (ParseException e) {
+                               System.out.printf ("pyro parse failed %s\n", line);
+                       }
+                       ++pyro;
+                       return;
+               }
                get_int(line, "serial-number", serial);
                get_int(line, "log-format", log_format);
                get_int(line, "Main deploy:", main_deploy);
@@ -200,6 +219,7 @@ public class AltosConfig implements ActionListener {
                get_string(line, "Callsign:", callsign);
                get_string(line,"software-version", version);
                get_string(line,"product", product);
+               get_int(line, "Pyro-count:", npyro);
        }
 
        final static int        serial_mode_read = 0;
@@ -243,6 +263,8 @@ public class AltosConfig implements ActionListener {
                        callsign.set("N0CALL");
                        version.set("unknown");
                        product.set("unknown");
+                       pyro = 0;
+                       npyro.set(0);
                }
 
                void get_data() {
@@ -304,6 +326,12 @@ public class AltosConfig implements ActionListener {
                                        serial_line.printf("c i %d\n", ignite_mode.get());
                                if (pad_orientation.get() >= 0)
                                        serial_line.printf("c o %d\n", pad_orientation.get());
+                               if (pyros.length > 0) {
+                                       for (int p = 0; p < pyros.length; p++) {
+                                               serial_line.printf("c P %s\n",
+                                                                  pyros[p].toString());
+                                       }
+                               }
                                serial_line.printf("c w\n");
                        } catch (InterruptedException ie) {
                        } catch (TimeoutException te) {
@@ -431,6 +459,9 @@ public class AltosConfig implements ActionListener {
                if (pad_orientation.get() >= 0)
                        pad_orientation.set(config_ui.pad_orientation());
                callsign.set(config_ui.callsign());
+               if (npyro.get() > 0) {
+                       pyros = config_ui.pyros();
+               }
                run_serial_thread(serial_mode_save);
        }
 
@@ -477,13 +508,14 @@ public class AltosConfig implements ActionListener {
                callsign = new string_ref("N0CALL");
                version = new string_ref("unknown");
                product = new string_ref("unknown");
+               npyro = new int_ref(0);
 
                device = AltosDeviceDialog.show(owner, Altos.product_any);
                if (device != null) {
                        try {
                                serial_line = new AltosSerial(device);
                                try {
-                                       if (!device.matchProduct(Altos.product_altimeter))
+                                       if (device.matchProduct(Altos.product_basestation))
                                                remote = true;
                                        init_ui();
                                } catch (InterruptedException ie) {
diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java
new file mode 100644 (file)
index 0000000..17adb15
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright © 2012 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 altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.altusmetrum.AltosLib.*;
+
+public class AltosConfigPyroUI
+       extends AltosDialog
+       implements ItemListener, DocumentListener
+{
+       AltosConfigUI   owner;
+       Container       pane;
+
+       static Insets il = new Insets(4,4,4,4);
+       static Insets ir = new Insets(4,4,4,4);
+
+       static String[] state_names;
+
+       static void make_state_names() {
+               if (state_names == null) {
+
+                       state_names = new String[AltosLib.ao_flight_landed - AltosLib.ao_flight_boost + 1];
+                       for (int state = AltosLib.ao_flight_boost; state <= AltosLib.ao_flight_landed; state++)
+                               state_names[state - AltosLib.ao_flight_boost] = AltosLib.state_name_capital(state);
+               }
+       }
+
+       class PyroItem implements ItemListener, DocumentListener
+       {
+               public int              flag;
+               public JRadioButton     enable;
+               public JTextField       value;
+               public JComboBox        combo;
+               AltosConfigPyroUI       ui;
+
+               public void set_enable(boolean enable) {
+                       if (value != null)
+                               value.setEnabled(enable);
+                       if (combo != null)
+                               combo.setEnabled(enable);
+               }
+
+               public void itemStateChanged(ItemEvent e) {
+                       set_enable(enable.isSelected());
+                       ui.set_dirty();
+               }
+
+               public void changedUpdate(DocumentEvent e) {
+                       ui.set_dirty();
+               }
+
+               public void insertUpdate(DocumentEvent e) {
+                       ui.set_dirty();
+               }
+
+               public void removeUpdate(DocumentEvent e) {
+                       ui.set_dirty();
+               }
+
+               public void set(boolean new_enable, double new_value) {
+                       enable.setSelected(new_enable);
+                       set_enable(new_enable);
+                       if (value != null) {
+                               double  scale = AltosPyro.pyro_to_scale(flag);
+                               String  format = "%6.0f";
+                               if (scale >= 10)
+                                       format = "%6.1f";
+                               else if (scale >= 100)
+                                       format = "%6.2f";
+                               value.setText(String.format(format, new_value));
+                       }
+                       if (combo != null)
+                               if (new_value >= AltosLib.ao_flight_boost && new_value <= AltosLib.ao_flight_landed)
+                                       combo.setSelectedIndex((int) new_value - AltosLib.ao_flight_boost);
+               }
+
+               public boolean enabled() {
+                       return enable.isSelected();
+               }
+
+               public double value() {
+                       if (value != null)
+                               return Double.parseDouble(value.getText());
+                       if (combo != null)
+                               return combo.getSelectedIndex() + AltosLib.ao_flight_boost;
+                       return 0;
+               }
+
+               public PyroItem(AltosConfigPyroUI in_ui, int in_flag, int x, int y) {
+
+                       ui = in_ui;
+                       flag = in_flag;
+
+                       GridBagConstraints      c;
+                       c = new GridBagConstraints();
+                       c.gridx = x; c.gridy = y;
+                       c.gridwidth = 1;
+                       c.fill = GridBagConstraints.NONE;
+                       c.anchor = GridBagConstraints.LINE_START;
+                       c.insets = il;
+                       enable = new JRadioButton();
+                       enable.addItemListener(this);
+                       pane.add(enable, c);
+                       
+                       if ((flag & AltosPyro.pyro_no_value) == 0) {
+                               c = new GridBagConstraints();
+                               c.gridx = x+1; c.gridy = y;
+                               c.gridwidth = 1;
+                               c.fill = GridBagConstraints.NONE;
+                               c.anchor = GridBagConstraints.LINE_START;
+                               c.insets = il;
+                               if ((flag & AltosPyro.pyro_state_value) != 0) {
+                                       make_state_names();
+                                       combo = new JComboBox(state_names);
+                                       combo.addItemListener(this);
+                                       pane.add(combo, c);
+                               } else {
+                                       value = new JTextField(10);
+                                       value.getDocument().addDocumentListener(this);
+                                       pane.add(value, c);
+                               }
+                       }
+               }
+       }
+
+       class PyroColumn {
+               public PyroItem[]       items;
+               public JLabel           label;
+               int                     channel;
+
+               public void set(AltosPyro pyro) {
+                       int row = 0;
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                               if ((AltosPyro.pyro_all & flag) != 0) {
+                                       items[row].set((pyro.flags & flag) != 0,
+                                                      pyro.get_value(flag));
+                                       row++;
+                               }
+                       }
+               }
+
+               public AltosPyro get() {
+                       AltosPyro       p = new AltosPyro(channel);
+
+                       int row = 0;
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                               if ((AltosPyro.pyro_all & flag) != 0) {
+                                       if (items[row].enabled()) {
+                                               System.out.printf ("Flag %x enabled\n", flag);
+                                               p.flags |= flag;
+                                               p.set_value(flag, items[row].value());
+                                       }
+                                       row++;
+                               }
+                       }
+                       System.out.printf ("Pyro %x %s\n", p.flags, p.toString());
+                       return p;
+               }
+
+               public PyroColumn(AltosConfigPyroUI ui, int x, int y, int in_channel) {
+
+                       channel = in_channel;
+
+                       int     nrow = 0;
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
+                               if ((flag & AltosPyro.pyro_all) != 0)
+                                       nrow++;
+
+                       items = new PyroItem[nrow];
+                       int row = 0;
+                       
+                       GridBagConstraints      c;
+                       c = new GridBagConstraints();
+                       c.gridx = x; c.gridy = y;
+                       c.gridwidth = 2;
+                       c.fill = GridBagConstraints.NONE;
+                       c.anchor = GridBagConstraints.CENTER;
+                       c.insets = il;
+                       label = new JLabel(String.format("Pyro Channel %d", channel));
+                       pane.add(label, c);
+                       y++;
+
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
+                               if ((flag & AltosPyro.pyro_all) != 0) {
+                                       items[row] = new PyroItem(ui, flag, x, y + row);
+                                       row++;
+                               }
+               }
+       }
+
+       PyroColumn[]    columns;
+
+       public void set_pyros(AltosPyro[] pyros) {
+               for (int i = 0; i < pyros.length; i++) {
+                       if (pyros[i].channel < columns.length)
+                               columns[pyros[i].channel].set(pyros[i]);
+               }
+       }
+
+       public AltosPyro[] get_pyros() {
+               AltosPyro[]     pyros = new AltosPyro[columns.length];
+               for (int c = 0; c < columns.length; c++)
+                       pyros[c] = columns[c].get();
+               return pyros;
+       }
+
+       public void set_dirty() {
+               owner.set_dirty();
+       }
+
+       public void itemStateChanged(ItemEvent e) {
+               owner.set_dirty();
+       }
+
+       public void changedUpdate(DocumentEvent e) {
+               owner.set_dirty();
+       }
+
+       public void insertUpdate(DocumentEvent e) {
+               owner.set_dirty();
+       }
+
+       public void removeUpdate(DocumentEvent e) {
+               owner.set_dirty();
+       }
+
+       public AltosConfigPyroUI(AltosConfigUI in_owner, AltosPyro[] pyros) {
+
+               super(in_owner, "Configure Pyro Channels", false);
+
+               owner = in_owner;
+
+               GridBagConstraints      c;
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               int     row = 1;
+
+               for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
+                       String  n;
+
+                       n = AltosPyro.pyro_to_name(flag);
+                       if (n != null) {
+                               c = new GridBagConstraints();
+                               c.gridx = 0; c.gridy = row;
+                               c.gridwidth = 1;
+                               c.fill = GridBagConstraints.NONE;
+                               c.anchor = GridBagConstraints.LINE_START;
+                               c.insets = il;
+                               JLabel label = new JLabel(n);
+                               pane.add(label, c);
+                               row++;
+                       }
+               }
+
+               columns = new PyroColumn[pyros.length];
+
+               for (int i = 0; i < pyros.length; i++) {
+                       columns[i] = new PyroColumn(this, i*2 + 1, 0, i);
+                       columns[i].set(pyros[i]);
+               }
+       }
+
+       public void make_visible() {
+               pack();
+               setVisible(true);
+       }
+}
index dd34a9cf348c84dbbb4a219652527f2e0db0c5a8..feac053be9ad0fc1ec358de8926c1ae5d1425231 100644 (file)
@@ -29,7 +29,6 @@ public class AltosConfigUI
 {
 
        Container       pane;
-       Box             box;
        JLabel          product_label;
        JLabel          version_label;
        JLabel          serial_label;
@@ -62,11 +61,15 @@ public class AltosConfigUI
        JComboBox       pad_orientation_value;
        JTextField      callsign_value;
 
+       JButton         pyro;
+
        JButton         save;
        JButton         reset;
        JButton         reboot;
        JButton         close;
 
+       AltosPyro[]     pyros;
+
        ActionListener  listener;
 
        static String[] main_deploy_values = {
@@ -510,6 +513,20 @@ public class AltosConfigUI
                set_pad_orientation_tool_tip();
                row++;
 
+               /* Pyro channels */
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               pyro = new JButton("Configure Pyro Channels");
+               pane.add(pyro, c);
+               pyro.addActionListener(this);
+               pyro.setActionCommand("Pyro");
+               row++;
+
                /* Buttons */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -582,10 +599,30 @@ public class AltosConfigUI
                return true;
        }
 
+       void set_dirty() {
+               dirty = true;
+               save.setEnabled(true);
+       }
+
+       public void set_clean() {
+               dirty = false;
+               save.setEnabled(false);
+       }
+
+       AltosConfigPyroUI       pyro_ui;
+
        /* Listen for events from our buttons */
        public void actionPerformed(ActionEvent e) {
                String  cmd = e.getActionCommand();
 
+               if (cmd.equals("Pyro")) {
+                       if (pyro_ui == null && pyros != null) {
+                               pyro_ui = new AltosConfigPyroUI(this, pyros);
+                               pyro_ui.make_visible();
+                       }
+                       return;
+               }
+
                if (cmd.equals("Close") || cmd.equals("Reboot"))
                        if (!check_dirty(cmd))
                                return;
@@ -594,25 +631,25 @@ public class AltosConfigUI
                        setVisible(false);
                        dispose();
                }
-               dirty = false;
+               set_clean();
        }
 
        /* ItemListener interface method */
        public void itemStateChanged(ItemEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        /* DocumentListener interface methods */
        public void changedUpdate(DocumentEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        public void insertUpdate(DocumentEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        public void removeUpdate(DocumentEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        /* Let the config code hook on a listener */
@@ -725,8 +762,7 @@ public class AltosConfigUI
        }
 
        public void set_flight_log_max(int new_flight_log_max) {
-               if (new_flight_log_max == 0)
-                       flight_log_max_value.setEnabled(false);
+               flight_log_max_value.setEnabled(new_flight_log_max > 0);
                flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max));
                set_flight_log_max_tool_tip();
        }
@@ -793,7 +829,19 @@ public class AltosConfigUI
                        return -1;
        }
 
-       public void set_clean() {
-               dirty = false;
+       public void set_has_pyro(boolean has_pyro) {
+               pyro.setEnabled(has_pyro);
+       }
+
+       public void set_pyros(AltosPyro[] new_pyros) {
+               pyros = new_pyros;
+               if (pyro_ui != null)
+                       pyro_ui.set_pyros(pyros);
+       }
+
+       public AltosPyro[] pyros() {
+               if (pyro_ui != null)
+                       pyros = pyro_ui.get_pyros();
+               return pyros;
        }
 }
index eac371aa2fde152f65382da3f15f8901c05ea2ce..c2a9d6e6e1a6af68e11c83dff70b8ef5b27ef365 100644 (file)
@@ -45,6 +45,12 @@ public class AltosDialog extends JDialog implements AltosUIListener {
                addWindowListener(new AltosDialogListener());
        }
 
+       public AltosDialog(Dialog dialog, String label, boolean modal) {
+               super(dialog, label, modal);
+               AltosUIPreferences.register_ui_listener(this);
+               addWindowListener(new AltosDialogListener());
+       }
+
        public AltosDialog(Frame frame, boolean modal) {
                super(frame, modal);
                AltosUIPreferences.register_ui_listener(this);
index 9f03ceb6b5cdec3250110c6318772e77f22b9921..2c46da4a5f1f75643782044ad0df14ad45e94883 100644 (file)
@@ -24,6 +24,7 @@ altosui_JAVA = \
        AltosConfig.java \
        AltosConfigFreqUI.java \
        AltosConfigUI.java \
+       AltosConfigPyroUI.java \
        AltosConfigureUI.java \
        AltosConfigTD.java \
        AltosConfigTDUI.java \
index a14d0adecc6d7fc3d0cb3d5e0965768c15eb4818..96659aaf9c530c92fd16837b0975724da34a0918 100644 (file)
@@ -37,7 +37,9 @@
  * AVR definitions and code fragments for AltOS
  */
 
+#ifndef AO_STACK_SIZE
 #define AO_STACK_SIZE  116
+#endif
 
 /* Various definitions to make GCC look more like SDCC */
 
index 0aa978e9dd174830163d2d20ac2e1e27c7a9fd1f..a08e87fa021660ed21c04050c1690e37e4ad1ea1 100644 (file)
@@ -69,6 +69,7 @@
 #endif
 
 #ifdef TELEPYRO
+       #define AO_STACK_SIZE           104
        #define LEDS_AVAILABLE          0
        #define HAS_USB                 1
        #define HAS_LOG                 0
index 4f37e9793e6cbe0c37dc424119e93445adc8a89f..aac8fda51c7219d6895fce2655ec922b01bf4b9f 100644 (file)
@@ -113,6 +113,15 @@ ao_pyro_ready(struct ao_pyro *pyro)
                        /* handled separately */
                        continue;
 
+               case ao_pyro_state_less:
+                       if (ao_flight_state < pyro->state_less)
+                               continue;
+                       break;
+               case ao_pyro_state_greater_or_equal:
+                       if (ao_flight_state >= pyro->state_greater_or_equal)
+                               continue;
+                       break;
+
                default:
                        continue;
                }
@@ -166,7 +175,7 @@ uint8_t     ao_pyro_wakeup;
 static void
 ao_pyro(void)
 {
-       uint8_t         p;
+       uint8_t         p, any_waiting;
        struct ao_pyro  *pyro;
 
        ao_config_get();
@@ -177,6 +186,7 @@ ao_pyro(void)
                ao_alarm(AO_MS_TO_TICKS(100));
                ao_sleep(&ao_pyro_wakeup);
                ao_clear_alarm();
+               any_waiting = 0;
                for (p = 0; p < AO_PYRO_NUM; p++) {
                        pyro = &ao_config.pyro[p];
 
@@ -190,6 +200,7 @@ ao_pyro(void)
                        if (!pyro->flags)
                                continue;
 
+                       any_waiting = 1;
                        /* Check pyro state to see if it shoule fire
                         */
                        if (!pyro->delay_done) {
@@ -213,7 +224,10 @@ ao_pyro(void)
 
                        ao_pyro_fire(p);
                }
+               if (!any_waiting)
+                       break;
        }
+       ao_exit();
 }
 
 __xdata struct ao_task ao_pyro_task;
@@ -257,6 +271,9 @@ const struct {
        { "t<", ao_pyro_time_less,      offsetof(struct ao_pyro, time_less), HELP("time less (s * 100)") },
        { "t>", ao_pyro_time_greater,   offsetof(struct ao_pyro, time_greater), HELP("time greater (s * 100)")  },
 
+       { "f<", ao_pyro_state_less,     offsetof(struct ao_pyro, state_less), HELP("state less") },
+       { "f>=",ao_pyro_state_greater_or_equal, offsetof(struct ao_pyro, state_greater_or_equal), HELP("state greater or equal")  },
+
        { "A", ao_pyro_ascending,       NO_VALUE, HELP("ascending") },
        { "D", ao_pyro_descending,      NO_VALUE, HELP("descending") },
 
index 5deb69d0bf3eccafef80479f28d176c43be7f51b..cde850add58eab6a2d8d2903820e6f2d44b11f9a 100644 (file)
@@ -42,6 +42,9 @@ enum ao_pyro_flag {
        ao_pyro_after_motor             = 0x00001000,
 
        ao_pyro_delay                   = 0x00002000,
+
+       ao_pyro_state_less              = 0x00004000,
+       ao_pyro_state_greater_or_equal  = 0x00008000,
 };
 
 struct ao_pyro {
@@ -52,6 +55,7 @@ struct ao_pyro {
        int16_t                 orient_less, orient_greater;
        int16_t                 time_less, time_greater;
        int16_t                 delay;
+       uint8_t                 state_less, state_greater_or_equal;
        int16_t                 motor;
        uint16_t                delay_done;
        uint8_t                 fired;
old mode 100644 (file)
new mode 100755 (executable)