Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
authorBdale Garbee <bdale@gag.com>
Tue, 29 Sep 2015 06:46:42 +0000 (00:46 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 29 Sep 2015 06:46:42 +0000 (00:46 -0600)
18 files changed:
altoslib/AltosState.java
altoslib/AltosTelemetryCompanion.java [new file with mode: 0644]
altoslib/AltosTelemetryStandard.java
altoslib/Makefile.am
ao-tools/ao-telem/ao-telem.c
src/drivers/ao_companion.c
src/drivers/ao_lco.c
src/drivers/ao_lco_cmd.c
src/drivers/ao_lco_func.c
src/drivers/ao_lco_func.h
src/drivers/ao_pad.c
src/drivers/ao_seven_segment.c
src/drivers/ao_seven_segment.h
src/easymega-v1.0/ao_pins.h
src/teleballoon-v2.0/ao_pins.h
src/telemega-v0.1/ao_pins.h
src/telemega-v1.0/ao_pins.h
src/telemetrum-v2.0/ao_pins.h

index 4edae54adaef19185e2735abe0013a68d9e29fc7..cf4fb9b030d66ca147be6af432e6304401d2d8a0 100644 (file)
@@ -1358,11 +1358,6 @@ public class AltosState implements Cloneable, Serializable {
                }
        }
 
-       public void make_companion (int nchannels) {
-               if (companion == null)
-                       companion = new AltosCompanion(nchannels);
-       }
-
        public void set_companion(AltosCompanion companion) {
                this.companion = companion;
        }
diff --git a/altoslib/AltosTelemetryCompanion.java b/altoslib/AltosTelemetryCompanion.java
new file mode 100644 (file)
index 0000000..96125ac
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2015 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_8;
+
+public class AltosTelemetryCompanion extends AltosTelemetryStandard {
+       AltosCompanion  companion;
+
+       static final public int max_channels = 12;
+
+       public AltosTelemetryCompanion(int[] bytes) {
+               super(bytes);
+
+               int     channels = uint8(7);
+
+               if (channels > max_channels)
+                       channels = max_channels;
+
+               companion = new AltosCompanion(channels);
+
+               companion.tick = tick;
+               companion.board_id = uint8(5);
+               companion.update_period = uint8(6);
+
+               if (channels == 0)
+                       companion.companion_data = null;
+               else {
+                       companion.companion_data = new int[channels];
+
+                       for (int i = 0; i < channels; i++)
+                               companion.companion_data[i] = uint16(8 + i * 2);
+               }
+       }
+
+       public void update_state(AltosState state) {
+               super.update_state(state);
+
+               state.set_companion(companion);
+       }
+}
index 2756182616f7cec6a2d79ac0d9025854feb3ffa2..c2a5ab3c584f8d32c0573d2ab292714bcdddb5ee 100644 (file)
@@ -68,11 +68,9 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry {
                case packet_type_satellite:
                        telem = new AltosTelemetrySatellite(bytes);
                        break;
-/*
                case packet_type_companion:
                        telem = new AltosTelemetryCompanion(bytes);
                        break;
-*/
                case packet_type_mega_sensor:
                        telem = new AltosTelemetryMegaSensor(bytes);
                        break;
index a6b178fa167fcbee9efcd110222432c5c7abf8ab..d1f8f2652e6329f0cce1db9c44ed8e6c913569d6 100644 (file)
@@ -96,6 +96,7 @@ altoslib_JAVA = \
        AltosStateUpdate.java \
        AltosTelemetry.java \
        AltosTelemetryConfiguration.java \
+       AltosTelemetryCompanion.java \
        AltosTelemetryFile.java \
        AltosTelemetryIterable.java \
        AltosTelemetryLegacy.java \
index da873838a7f79ad4b06e45be9815510234e8ea1f..05a69542d53b7c97a436df77d85dd4f59811ef12 100644 (file)
@@ -173,6 +173,15 @@ main (int argc, char **argv)
                                                telem.mega_sensor.mag_y,
                                                telem.mega_sensor.mag_z);
                                        break;
+                               case AO_TELEMETRY_COMPANION:
+                                       printf("board_id %3d update_period %3d channels %2d",
+                                              telem.companion.board_id,
+                                              telem.companion.update_period,
+                                              telem.companion.channels);
+                                       for (c = 0; c < telem.companion.channels; c++)
+                                               printf(" %6d", telem.companion.companion_data[c]);
+                                       printf("\n");
+                                       break;
                                case AO_TELEMETRY_MEGA_DATA:
                                        printf ("state %1d v_batt %5d v_pyro %5d ",
                                                telem.mega_data.state,
@@ -182,7 +191,7 @@ main (int argc, char **argv)
                                                printf ("s%1d %5d ", c,
                                                        telem.mega_data.sense[c] |
                                                        (telem.mega_data.sense[c] << 8));
-                                       
+
                                        printf ("ground_pres %5d ground_accel %5d accel_plus %5d accel_minus %5d ",
                                                telem.mega_data.ground_pres,
                                                telem.mega_data.ground_accel,
index 7e02939bf7bc0c01bca788bce526da7ee1172115..5f07e8b06cf8827e71e031b215c30a1aedbbc97d 100644 (file)
 #define ao_spi_fast(b)
 #endif
 
+#if !HAS_COMPANION
+#error HAS_COMPANION not set in ao_companion.c
+#endif
+
 #define COMPANION_SELECT()     do {                    \
                ao_spi_get_bit(AO_COMPANION_CS_PORT,    \
                               AO_COMPANION_CS_PIN,     \
index b8698a80dc8a67cd9b798b46c53b908759d312d9..8180c49de1137dc69af68f59702d9aa571e3cd1f 100644 (file)
@@ -36,28 +36,42 @@ static uint8_t      ao_lco_debug;
 #define AO_LCO_BOX_DIGIT_1     1
 #define AO_LCO_BOX_DIGIT_10    2
 
+#define AO_LCO_DRAG_RACE_START_TIME    AO_SEC_TO_TICKS(5)
+#define AO_LCO_DRAG_RACE_STOP_TIME     AO_SEC_TO_TICKS(2)
+
 static uint8_t ao_lco_min_box, ao_lco_max_box;
-static uint8_t ao_lco_pad;
-static uint8_t ao_lco_box;
+static uint8_t ao_lco_selected[AO_PAD_MAX_BOXES];
+static uint8_t ao_lco_valid[AO_PAD_MAX_BOXES];
+static uint8_t ao_lco_channels[AO_PAD_MAX_BOXES];
+static uint16_t        ao_lco_tick_offset[AO_PAD_MAX_BOXES];
+
+/* UI values */
 static uint8_t ao_lco_armed;
 static uint8_t ao_lco_firing;
-static uint8_t ao_lco_valid;
-static uint8_t ao_lco_got_channels;
-static uint16_t        ao_lco_tick_offset;
-
+static uint16_t        ao_lco_fire_tick;
+static uint8_t ao_lco_fire_down;
+static uint8_t ao_lco_drag_race;
+static uint8_t ao_lco_pad;
+static uint8_t ao_lco_box;
 static struct ao_pad_query     ao_pad_query;
 
+static uint8_t ao_lco_display_mutex;
+
 static void
 ao_lco_set_pad(uint8_t pad)
 {
-       ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad);
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad | (ao_lco_drag_race << 4));
+       ao_mutex_put(&ao_lco_display_mutex);
 }
 
 static void
 ao_lco_set_box(uint8_t box)
 {
-       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10);
-       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, box / 10);
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10 | (ao_lco_drag_race << 4));
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, box / 10 | (ao_lco_drag_race << 4));
+       ao_mutex_put(&ao_lco_display_mutex);
 }
 
 static void
@@ -68,9 +82,11 @@ ao_lco_set_voltage(uint16_t decivolts)
        tenths = decivolts % 10;
        ones = (decivolts / 10) % 10;
        tens = (decivolts / 100) % 10;
+       ao_mutex_get(&ao_lco_display_mutex);
        ao_seven_segment_set(AO_LCO_PAD_DIGIT, tenths);
        ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, ones | 0x10);
        ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, tens);
+       ao_mutex_put(&ao_lco_display_mutex);
 }
 
 static void
@@ -84,6 +100,33 @@ ao_lco_set_display(void)
        }
 }
 
+#define SEVEN_SEGMENT_d                ((0 << 0) |     \
+                                (0 << 1) |     \
+                                (1 << 2) |     \
+                                (1 << 3) |     \
+                                (1 << 4) |     \
+                                (1 << 5) |     \
+                                (1 << 6))
+
+
+#define SEVEN_SEGMENT_r                ((0 << 0) |     \
+                                (0 << 1) |     \
+                                (0 << 2) |     \
+                                (1 << 3) |     \
+                                (1 << 4) |     \
+                                (0 << 5) |     \
+                                (0 << 6))
+
+static void
+ao_lco_set_display_drag(void)
+{
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_direct(AO_LCO_BOX_DIGIT_10, SEVEN_SEGMENT_d | 0x80);
+       ao_seven_segment_direct(AO_LCO_BOX_DIGIT_1, SEVEN_SEGMENT_r | 0x80);
+       ao_mutex_put(&ao_lco_display_mutex);
+       ao_lco_set_pad(ao_lco_pad);
+}
+
 #define MASK_SIZE(n)   (((n) + 7) >> 3)
 #define MASK_ID(n)     ((n) >> 3)
 #define MASK_SHIFT(n)  ((n) & 7)
@@ -99,29 +142,211 @@ ao_lco_box_present(uint8_t box)
 }
 
 static uint8_t
-ao_lco_pad_present(uint8_t pad)
+ao_lco_pad_present(uint8_t box, uint8_t pad)
 {
-       if (!ao_lco_got_channels || !ao_pad_query.channels)
-               return pad == 0;
        /* voltage measurement is always valid */
        if (pad == 0)
                return 1;
+       if (!ao_lco_channels[box])
+               return 0;
        if (pad > AO_PAD_MAX_CHANNELS)
                return 0;
-       return (ao_pad_query.channels >> (pad - 1)) & 1;
+       return (ao_lco_channels[box] >> (pad - 1)) & 1;
 }
 
 static uint8_t
-ao_lco_pad_first(void)
+ao_lco_pad_first(uint8_t box)
 {
        uint8_t pad;
 
        for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++)
-               if (ao_lco_pad_present(pad))
+               if (ao_lco_pad_present(box, pad))
                        return pad;
        return 0;
 }
 
+static struct ao_task  ao_lco_drag_task;
+static uint8_t         ao_lco_drag_active;
+static uint8_t         ao_lco_drag_beep_count;
+static uint8_t         ao_lco_drag_beep_on;
+static uint16_t                ao_lco_drag_beep_time;
+static uint16_t                ao_lco_drag_warn_time;
+static uint16_t                ao_lco_drag_display_time;
+static uint8_t         ao_lco_drag_display_on;
+
+#define AO_LCO_DRAG_BEEP_TIME  AO_MS_TO_TICKS(50)
+#define AO_LCO_DRAG_WARN_TIME  AO_SEC_TO_TICKS(5)
+
+static void
+ao_lco_drag_beep_start(void)
+{
+       ao_beep(AO_BEEP_HIGH);
+       PRINTD("beep start\n");
+       ao_lco_drag_beep_on = 1;
+       ao_lco_drag_beep_time = ao_time() + AO_LCO_DRAG_BEEP_TIME;
+}
+
+static void
+ao_lco_drag_beep_stop(void)
+{
+       ao_beep(0);
+       PRINTD("beep stop\n");
+       ao_lco_drag_beep_on = 0;
+       if (ao_lco_drag_beep_count) {
+               --ao_lco_drag_beep_count;
+               if (ao_lco_drag_beep_count)
+                       ao_lco_drag_beep_time = ao_time() + AO_LCO_DRAG_BEEP_TIME;
+       }
+}
+
+static void
+ao_lco_drag_beep(uint8_t beeps)
+{
+       PRINTD("beep %d\n", beeps);
+       if (!ao_lco_drag_beep_count)
+               ao_lco_drag_beep_start();
+       ao_lco_drag_beep_count += beeps;
+}
+
+static uint16_t
+ao_lco_drag_beep_check(uint16_t now, uint16_t delay)
+{
+       PRINTD("beep check count %d delta %d\n",
+              ao_lco_drag_beep_count,
+              (int16_t) (now - ao_lco_drag_beep_time));
+       if (ao_lco_drag_beep_count) {
+               if ((int16_t) (now - ao_lco_drag_beep_time) >= 0) {
+                       if (ao_lco_drag_beep_on)
+                               ao_lco_drag_beep_stop();
+                       else
+                               ao_lco_drag_beep_start();
+               }
+       }
+
+       if (ao_lco_drag_beep_count) {
+               if (delay > AO_LCO_DRAG_BEEP_TIME)
+                       delay = AO_LCO_DRAG_BEEP_TIME;
+       }
+       return delay;
+}
+
+static void
+ao_lco_drag_enable(void)
+{
+       PRINTD("Drag enable\n");
+       ao_lco_drag_race = 1;
+       memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
+       ao_lco_drag_beep(5);
+       ao_lco_set_display_drag();
+       ao_lco_fire_down = 0;
+       ao_lco_drag_display_on = 1;
+       ao_lco_drag_display_time = ao_time() + AO_SEC_TO_TICKS(5);
+}
+
+static void
+ao_lco_drag_disable(void)
+{
+       PRINTD("Drag disable\n");
+       ao_lco_drag_race = 0;
+       memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
+       ao_lco_drag_beep(2);
+       ao_lco_set_display();
+       ao_lco_fire_down = 0;
+}
+
+static uint16_t
+ao_lco_drag_button_check(uint16_t now, uint16_t delay)
+{
+       uint16_t        button_delay = ~0;
+
+       /*
+        * Check to see if the button has been held down long enough
+        * to switch in/out of drag race mode
+        */
+       if (ao_lco_fire_down) {
+               if (ao_lco_drag_race) {
+                       if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_STOP_TIME)
+                               ao_lco_drag_disable();
+                       else
+                               button_delay = ao_lco_fire_tick + AO_LCO_DRAG_RACE_STOP_TIME - now;
+               } else {
+                       if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_START_TIME)
+                               ao_lco_drag_enable();
+                       else
+                               button_delay = ao_lco_fire_tick + AO_LCO_DRAG_RACE_START_TIME - now;
+               }
+               if (delay > button_delay)
+                       delay = button_delay;
+       }
+       return delay;
+}
+
+static uint16_t
+ao_lco_drag_warn_check(uint16_t now, uint16_t delay)
+{
+       uint16_t        warn_delay = ~0;
+
+       if (ao_lco_drag_race) {
+               if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) {
+                       ao_lco_drag_beep(1);
+                       ao_lco_drag_warn_time = now + AO_LCO_DRAG_WARN_TIME;
+               }
+               warn_delay = ao_lco_drag_warn_time - now;
+       }
+       if (delay > warn_delay)
+               delay = warn_delay;
+       return delay;
+}
+
+static uint16_t
+ao_lco_drag_display_check(uint16_t now, uint16_t delay)
+{
+       uint16_t        display_delay;
+
+       if (ao_lco_drag_display_on) {
+               if ((int16_t) (now - ao_lco_drag_display_time) >= 0) {
+                       ao_lco_drag_display_on = 0;
+                       ao_lco_set_display();
+               } else {
+                       display_delay = ao_lco_drag_display_time - now;
+                       if (delay > display_delay)
+                               delay = display_delay;
+               }
+       }
+       return delay;
+}
+
+static void
+ao_lco_drag_monitor(void)
+{
+       uint16_t        delay = ~0;
+       uint16_t        now;
+
+       for (;;) {
+               PRINTD("Drag monitor active %d delay %d\n", ao_lco_drag_active, delay);
+               if (delay == (uint16_t) ~0)
+                       ao_sleep(&ao_lco_drag_active);
+               else
+                       ao_sleep_for(&ao_lco_drag_active, delay);
+
+               delay = ~0;
+               if (!ao_lco_drag_active)
+                       continue;
+
+               now = ao_time();
+               delay = ao_lco_drag_button_check(now, delay);
+               delay = ao_lco_drag_warn_check(now, delay);
+               delay = ao_lco_drag_beep_check(now, delay);
+               delay = ao_lco_drag_display_check(now, delay);
+
+               /* check to see if there's anything left to do here */
+               if (!ao_lco_fire_down && !ao_lco_drag_race && !ao_lco_drag_beep_count) {
+                       delay = ~0;
+                       ao_lco_drag_active = 0;
+               }
+       }
+}
+
 static void
 ao_lco_input(void)
 {
@@ -148,7 +373,7 @@ ao_lco_input(void)
                                                        new_pad = AO_PAD_MAX_CHANNELS;
                                                if (new_pad == ao_lco_pad)
                                                        break;
-                                       } while (!ao_lco_pad_present(new_pad));
+                                       } while (!ao_lco_pad_present(ao_lco_box, new_pad));
                                        if (new_pad != ao_lco_pad) {
                                                ao_lco_pad = new_pad;
                                                ao_lco_set_display();
@@ -171,7 +396,7 @@ ao_lco_input(void)
                                        if (ao_lco_box != new_box) {
                                                ao_lco_box = new_box;
                                                ao_lco_pad = 1;
-                                               ao_lco_got_channels = 0;
+                                               ao_lco_channels[ao_lco_box] = 0;
                                                ao_lco_set_display();
                                        }
                                }
@@ -183,13 +408,49 @@ ao_lco_input(void)
                        case AO_BUTTON_ARM:
                                ao_lco_armed = event.value;
                                PRINTD("Armed %d\n", ao_lco_armed);
+                               if (ao_lco_armed) {
+                                       if (ao_lco_drag_race) {
+                                               uint8_t box;
+
+                                               for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) {
+                                                       if (ao_lco_selected[box]) {
+                                                               ao_wakeup(&ao_lco_armed);
+                                                               break;
+                                                       }
+                                               }
+                                       } else if (ao_lco_pad != 0) {
+                                               memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
+                                               ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1));
+                                       }
+                               }
                                ao_wakeup(&ao_lco_armed);
                                break;
                        case AO_BUTTON_FIRE:
                                if (ao_lco_armed) {
+                                       ao_lco_fire_down = 0;
                                        ao_lco_firing = event.value;
                                        PRINTD("Firing %d\n", ao_lco_firing);
                                        ao_wakeup(&ao_lco_armed);
+                               } else {
+                                       if (event.value) {
+                                               ao_lco_fire_down = 1;
+                                               ao_lco_fire_tick = ao_time();
+                                               ao_lco_drag_active = 1;
+                                               /* ao_lco_fire_down will already be off if we just enabled drag mode */
+                                               if (ao_lco_fire_down && ao_lco_drag_race) {
+                                                       if (ao_lco_pad != 0) {
+                                                               ao_lco_selected[ao_lco_box] ^= (1 << (ao_lco_pad - 1));
+                                                               PRINTD("Toggle box %d pad %d (pads now %x) to drag race\n",
+                                                                      ao_lco_pad, ao_lco_box, ao_lco_selected[ao_lco_box]);
+                                                               ao_lco_drag_beep(ao_lco_pad);
+                                                       }
+                                               }
+                                               ao_wakeup(&ao_lco_drag_active);
+                                       } else {
+                                               ao_lco_fire_down = 0;
+                                               if (ao_lco_drag_active)
+                                                       ao_wakeup(&ao_lco_drag_active);
+                                       }
                                }
                                break;
                        }
@@ -225,37 +486,36 @@ static AO_LED_TYPE        continuity_led[AO_LED_CONTINUITY_NUM] = {
 #endif
 };
 
-static void
-ao_lco_update(void)
+static uint8_t
+ao_lco_get_channels(uint8_t box, struct ao_pad_query *query)
 {
        int8_t                  r;
-       uint8_t                 c;
 
-       r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset);
+       r = ao_lco_query(box, query, &ao_lco_tick_offset[box]);
        if (r == AO_RADIO_CMAC_OK) {
-               c = ao_lco_got_channels;
-               ao_lco_got_channels = 1;
-               ao_lco_valid = 1;
-               if (!c) {
+               ao_lco_channels[box] = query->channels;
+               ao_lco_valid[box] = 1;
+       } else
+               ao_lco_valid[box] = 0;
+       PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r);
+       ao_wakeup(&ao_pad_query);
+       return ao_lco_valid[box];
+}
+
+static void
+ao_lco_update(void)
+{
+       uint8_t previous_valid = ao_lco_valid[ao_lco_box];
+
+       if (ao_lco_get_channels(ao_lco_box, &ao_pad_query)) {
+               if (!previous_valid) {
                        if (ao_lco_pad != 0)
-                               ao_lco_pad = ao_lco_pad_first();
+                               ao_lco_pad = ao_lco_pad_first(ao_lco_box);
                        ao_lco_set_display();
                }
                if (ao_lco_pad == 0)
                        ao_lco_set_display();
-       } else
-               ao_lco_valid = 0;
-
-#if 0
-       PRINTD("lco_query success arm_status %d i0 %d i1 %d i2 %d i3 %d\n",
-              query.arm_status,
-              query.igniter_status[0],
-              query.igniter_status[1],
-              query.igniter_status[2],
-              query.igniter_status[3]);
-#endif
-       PRINTD("ao_lco_update valid %d\n", ao_lco_valid);
-       ao_wakeup(&ao_pad_query);
+       }
 }
 
 static void
@@ -309,8 +569,8 @@ ao_lco_search(void)
                ao_lco_box = ao_lco_min_box;
        else
                ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0;
-       ao_lco_valid = 0;
-       ao_lco_got_channels = 0;
+       memset(ao_lco_valid, 0, sizeof (ao_lco_valid));
+       memset(ao_lco_channels, 0, sizeof (ao_lco_channels));
        ao_lco_pad = 1;
        ao_lco_set_display();
 }
@@ -319,11 +579,12 @@ static void
 ao_lco_igniter_status(void)
 {
        uint8_t         c;
+       uint8_t         t = 0;
 
        for (;;) {
                ao_sleep(&ao_pad_query);
-               PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid);
-               if (!ao_lco_valid) {
+               PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid[ao_lco_box]);
+               if (!ao_lco_valid[ao_lco_box]) {
                        ao_led_on(AO_LED_RED);
                        ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
                        continue;
@@ -339,18 +600,27 @@ ao_lco_igniter_status(void)
                        ao_led_on(AO_LED_REMOTE_ARM);
                else
                        ao_led_off(AO_LED_REMOTE_ARM);
+
                for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
                        uint8_t status;
 
-                       if (ao_pad_query.channels & (1 << c))
-                               status = ao_pad_query.igniter_status[c];
-                       else
-                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
-                       if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
-                               ao_led_on(continuity_led[c]);
-                       else
-                               ao_led_off(continuity_led[c]);
+                       if (ao_lco_drag_race) {
+                               if (ao_lco_selected[ao_lco_box] & (1 << c) && t)
+                                       ao_led_on(continuity_led[c]);
+                               else
+                                       ao_led_off(continuity_led[c]);
+                       } else {
+                               if (ao_pad_query.channels & (1 << c))
+                                       status = ao_pad_query.igniter_status[c];
+                               else
+                                       status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+                               if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
+                                       ao_led_on(continuity_led[c]);
+                               else
+                                       ao_led_off(continuity_led[c]);
+                       }
                }
+               t = 1-t;
        }
 }
 
@@ -374,34 +644,31 @@ static void
 ao_lco_monitor(void)
 {
        uint16_t                delay;
+       uint8_t                 box;
 
        ao_lco_search();
        ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
        ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
        ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
+       ao_add_task(&ao_lco_drag_task, ao_lco_drag_monitor, "drag race");
        for (;;) {
-               PRINTD("monitor armed %d firing %d offset %d\n",
-                      ao_lco_armed, ao_lco_firing, ao_lco_tick_offset);
+               PRINTD("monitor armed %d firing %d\n",
+                      ao_lco_armed, ao_lco_firing);
 
                if (ao_lco_armed && ao_lco_firing) {
-                       PRINTD("Firing box %d pad %d: valid %d\n",
-                              ao_lco_box, ao_lco_pad, ao_lco_valid);
-                       if (!ao_lco_valid)
-                               ao_lco_update();
-                       if (ao_lco_valid && ao_lco_pad)
-                               ao_lco_ignite(ao_lco_box, 1 << (ao_lco_pad - 1), ao_lco_tick_offset);
-               } else if (ao_lco_armed) {
-                       PRINTD("Arming box %d pad %d\n",
-                              ao_lco_box, ao_lco_pad);
-                       if (!ao_lco_valid)
-                               ao_lco_update();
-                       if (ao_lco_pad) {
-                               ao_lco_arm(ao_lco_box, 1 << (ao_lco_pad - 1), ao_lco_tick_offset);
-                               ao_delay(AO_MS_TO_TICKS(30));
-                               ao_lco_update();
-                       }
+                       ao_lco_ignite();
                } else {
                        ao_lco_update();
+                       if (ao_lco_armed) {
+                               for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) {
+                                       if (ao_lco_selected[box]) {
+                                               PRINTD("Arming box %d pads %x\n",
+                                                      box, ao_lco_selected[box]);
+                                               if (ao_lco_valid[box])
+                                                       ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[ao_lco_box]);
+                                       }
+                               }
+                       }
                }
                if (ao_lco_armed && ao_lco_firing)
                        delay = AO_MS_TO_TICKS(100);
index acbf589aa4cd0d13054b24d5037804f27689cec5..6a36568748b39218440d45cbf351dd9f534cc94b 100644 (file)
@@ -62,7 +62,7 @@ lco_arm(void)
 static void
 lco_ignite(void)
 {
-       ao_lco_ignite(lco_box, lco_channels, tick_offset);
+       ao_lco_ignite();
 }
 
 static void
index 32c00068a58d9d89b0a5c29358458afc6c332c1d..08d454670acb0bd881da59385e6e2ac265a3e038 100644 (file)
@@ -44,7 +44,7 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset)
        }
 #endif
        ao_mutex_get(&ao_lco_mutex);
-       command.tick = ao_time() - *tick_offset;
+       command.tick = ao_time();
        command.box = box;
        command.cmd = AO_LAUNCH_QUERY;
        command.channels = 0;
@@ -70,14 +70,13 @@ ao_lco_arm(uint16_t box, uint8_t channels, uint16_t tick_offset)
 }
 
 void
-ao_lco_ignite(uint16_t box, uint8_t channels, uint16_t tick_offset)
+ao_lco_ignite(void)
 {
        ao_mutex_get(&ao_lco_mutex);
-       command.tick = ao_time() - tick_offset;
-       command.box = box;
+       command.tick = 0;
+       command.box = 0;
        command.cmd = AO_LAUNCH_FIRE;
-       command.channels = channels;
+       command.channels = 0;
        ao_radio_cmac_send(&command, sizeof (command));
        ao_mutex_put(&ao_lco_mutex);
 }
-
index dccf602ae1a2c797f0883948bab1a1f433a059f6..42754352e2b3a0b96edd5780d3d77bea094d6faf 100644 (file)
@@ -27,6 +27,6 @@ void
 ao_lco_arm(uint16_t box, uint8_t channels, uint16_t tick_offset);
 
 void
-ao_lco_ignite(uint16_t box, uint8_t channels, uint16_t tick_offset);
+ao_lco_ignite(void);
 
 #endif /* _AO_LCO_FUNC_H_ */
index ffe46c6833723df2279559690e1bec2e7ad6272e..419ea8d34c58e4b5a5281e80f1aff0b4e883eeff 100644 (file)
@@ -288,8 +288,7 @@ ao_pad(void)
                        PRINTD ("armed\n");
                        ao_pad_armed = command.channels;
                        ao_pad_arm_time = ao_time();
-
-                       /* fall through ... */
+                       break;
 
                case AO_LAUNCH_QUERY:
                        if (command.box != ao_pad_box) {
@@ -320,13 +319,6 @@ ao_pad(void)
                                        ao_pad_arm_time, ao_time());
                                break;
                        }
-                       time_difference = command.tick - ao_time();
-                       if (time_difference < 0)
-                               time_difference = -time_difference;
-                       if (time_difference > 10) {
-                               PRINTD ("time different too large %d\n", time_difference);
-                               break;
-                       }
                        PRINTD ("ignite\n");
                        ao_pad_ignite = ao_pad_armed;
                        ao_pad_arm_time = ao_time();
index 961fbb8400e95dab27624b2295075f6a5c6b481e..f1339ee5a543c43d998ce3c5da962489079f6cdb 100644 (file)
@@ -168,10 +168,20 @@ static const uint8_t ao_segments[] = {
        (0 << 6),               /* F */
 };
 
+
 void
-ao_seven_segment_set(uint8_t digit, uint8_t value)
+ao_seven_segment_direct(uint8_t digit, uint8_t segments)
 {
        uint8_t s;
+
+       for (s = 0; s <= 7; s++)
+               ao_lcd_set(digit, s, !!(segments & (1 << s)));
+       ao_lcd_flush();
+}
+
+void
+ao_seven_segment_set(uint8_t digit, uint8_t value)
+{
        uint8_t segments;
 
        if (value == AO_SEVEN_SEGMENT_CLEAR)
@@ -183,10 +193,7 @@ ao_seven_segment_set(uint8_t digit, uint8_t value)
                if (value & 0x10)
                        segments |= (1 << 7);
        }
-
-       for (s = 0; s <= 7; s++)
-               ao_lcd_set(digit, s, !!(segments & (1 << s)));
-       ao_lcd_flush();
+       ao_seven_segment_direct(digit, segments);
 }
 
 void
index 5b29deaf636ea5e07e6e14e874938d90a6302375..f997f3b55776c87e3d2e93f14d1e1b24f3f88289 100644 (file)
@@ -22,6 +22,9 @@
 
 #define AO_SEVEN_SEGMENT_CLEAR         0xff
 
+void
+ao_seven_segment_direct(uint8_t digit, uint8_t segments);
+
 void
 ao_seven_segment_set(uint8_t digit, uint8_t value);
 
index d6490ba59cb34866d91170418530e21960e6f780..a5e556384615a6e6a52b2b4b615de5302c119b66 100644 (file)
@@ -78,6 +78,7 @@
 #define HAS_RADIO              0
 #define HAS_TELEMETRY          0
 #define HAS_APRS               0
+#define HAS_COMPANION          1
 
 #define HAS_SPI_1              1
 #define SPI_1_PA5_PA6_PA7      1       /* Barometer */
index a369070f2fd85435f5542eeedcfa6e686e666562..b62b55800b9c23abc2c78ecc45e6e30829dd982d 100644 (file)
@@ -75,6 +75,7 @@
 #define HAS_RADIO              1
 #define HAS_TELEMETRY          1
 #define HAS_APRS               1
+#define HAS_COMPANION          1
 
 #define HAS_SPI_1              1
 #define SPI_1_PA5_PA6_PA7      1       /* Barometer */
index 2616e9061e20a5d1a7ea93073d3c4287dd1dc2bb..7ccc6085ba1b49139dcf1c6ba164304a2393b19f 100644 (file)
@@ -79,6 +79,7 @@
 #define HAS_RADIO              1
 #define HAS_TELEMETRY          1
 #define HAS_APRS               1
+#define HAS_COMPANION          1
 
 #define HAS_SPI_1              1
 #define SPI_1_PA5_PA6_PA7      1       /* Barometer */
index 77b753d1edb3083cf56c6d917f30154438da864f..664546c2fc02d4ba3aa5b0462b6b0bae747f24dd 100644 (file)
@@ -79,6 +79,7 @@
 #define HAS_RADIO              1
 #define HAS_TELEMETRY          1
 #define HAS_APRS               1
+#define HAS_COMPANION          1
 
 #define HAS_SPI_1              1
 #define SPI_1_PA5_PA6_PA7      1       /* Barometer */
index a9a4b243a690643b65e0431a4406cfb1e30e3452..fbb38df2cf05dba4f17203bd3bb341c40972d485 100644 (file)
@@ -75,6 +75,7 @@
 #define HAS_RADIO              1
 #define HAS_TELEMETRY          1
 #define HAS_APRS               1
+#define HAS_COMPANION          1
 
 #define HAS_SPI_1              1
 #define SPI_1_PA5_PA6_PA7      1       /* Barometer */