implement static test start and stop protocol for telefiretwo+telebt
[fw/altos] / src / drivers / ao_lco_two.c
index 0fd8e3626d45b8e709d0cc344f753937ca95d8a0..e2f867454c5183e1f63cb30d212681093110c438 100644 (file)
@@ -3,7 +3,8 @@
  *
  * 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.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,6 +19,7 @@
 #include <ao.h>
 #include <ao_lco.h>
 #include <ao_event.h>
+#include <ao_button.h>
 #include <ao_lco_func.h>
 #include <ao_radio_cmac.h>
 
@@ -29,13 +31,13 @@ static uint8_t      ao_lco_debug;
 #define DEBUG_STATUS   2
 #define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
 #else
-#define PRINTD(l,...) 
+#define PRINTD(l,...)
 #endif
 
 #define AO_LCO_VALID_LAST      1
 #define AO_LCO_VALID_EVER      2
 
-static uint8_t ao_lco_selected;
+static uint8_t ao_lco_suspended;
 static uint8_t ao_lco_valid;
 static uint8_t ao_lco_channels;
 static uint16_t        ao_lco_tick_offset;
@@ -43,56 +45,87 @@ static uint16_t     ao_lco_tick_offset;
 /* UI values */
 static uint8_t ao_lco_armed;
 static uint8_t ao_lco_firing;
-static uint8_t ao_lco_fire_down;
-
-#define ao_lco_box     (ao_config.pad_box)
+static uint8_t ao_lco_box;
 
 static struct ao_pad_query     ao_pad_query;
 
-#define MASK_SIZE(n)   (((n) + 7) >> 3)
-#define MASK_ID(n)     ((n) >> 3)
-#define MASK_SHIFT(n)  ((n) & 7)
+/* TeleFireTwo boxes have a single pad */
+#define ao_lco_pad     0
+
+static void
+ao_lco_set_box(int box)
+{
+       ao_lco_box = ao_config.pad_box + box;
+       ao_lco_valid = 0;
+       ao_lco_armed = 0;
+       ao_wakeup(&ao_lco_armed);
+}
 
 static void
-ao_lco_set_armed(int pad, int armed)
+ao_lco_set_armed(int armed)
 {
-       uint8_t bit = (1 << pad);
+       uint8_t bit = (1 << ao_lco_pad);
 
        if (armed) {
-               ao_lco_selected |= bit;
-               ao_lco_armed |= bit;
+               ao_lco_armed = bit;
        } else {
-               ao_lco_selected &= ~bit;
-               ao_lco_armed &= ~bit;
+               ao_lco_armed = 0;
        }
-       PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_selected 0x%x ao_lco_armed 0x%x\n",
-              pad, bit, armed, ao_lco_selected, ao_lco_armed);
+       PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_armed 0x%x\n",
+              ao_lco_pad, bit, armed, ao_lco_armed);
        ao_wakeup(&ao_lco_armed);
 }
 
+static void
+ao_lco_suspend(void)
+{
+       if (!ao_lco_suspended) {
+               PRINTD(DEBUG_EVENT, "suspend\n");
+               ao_lco_suspended = 1;
+               ao_lco_armed = 0;
+               ao_wakeup(&ao_pad_query);
+       }
+}
+
+static void
+ao_lco_wakeup(void)
+{
+       if (ao_lco_suspended) {
+               ao_lco_suspended = 0;
+               ao_wakeup(&ao_lco_suspended);
+       }
+}
+
 static void
 ao_lco_input(void)
 {
        static struct ao_event  event;
+       uint8_t timeout;
 
        for (;;) {
-               ao_event_get(&event);
+               if (ao_config.pad_idle && !ao_lco_suspended) {
+                       timeout = ao_event_get_for(&event, AO_SEC_TO_TICKS(ao_config.pad_idle));
+                       if (timeout) {
+                               ao_lco_suspend();
+                               continue;
+                       }
+               } else {
+                       ao_event_get(&event);
+               }
+               ao_lco_wakeup();
                PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n",
                       event.type, event.unit, event.value);
                switch (event.type) {
                case AO_EVENT_BUTTON:
                        switch (event.unit) {
-                       case AO_BUTTON_ARM_0:
-                               ao_lco_set_armed(0, event.value);
+                       case AO_BUTTON_BOX:
+                               ao_lco_set_box(event.value);
                                break;
-#if AO_BUTTON_ARM_NUM > 1
-                       case AO_BUTTON_ARM_1:
-                               ao_lco_set_armed(1, event.value);
+                       case AO_BUTTON_ARM:
+                               ao_lco_set_armed(event.value);
                                break;
-#endif
                        case AO_BUTTON_FIRE:
                                if (ao_lco_armed) {
-                                       ao_lco_fire_down = 0;
                                        ao_lco_firing = event.value;
                                        PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
                                        ao_wakeup(&ao_lco_armed);
@@ -154,14 +187,22 @@ ao_lco_igniter_status(void)
        uint8_t         t = 0;
 
        for (;;) {
+               uint8_t all_status;
                ao_sleep(&ao_pad_query);
-               PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid);
+               while (ao_lco_suspended) {
+                       ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM);
+                       for (c = 0; c < AO_LED_CONTINUITY_NUM; c++)
+                               ao_led_off(continuity_led[c]);
+                       ao_sleep(&ao_lco_suspended);
+               }
+               PRINTD(DEBUG_STATUS, "RSSI %d VALID %d channels %d arm_status %d\n",
+                      ao_radio_cmac_rssi, ao_lco_valid,
+                      ao_lco_channels, ao_pad_query.arm_status);
                if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
                        ao_led_on(AO_LED_RED);
                        ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
-                       continue;
-               }
-               if (ao_radio_cmac_rssi < -90) {
+                       memset(&ao_pad_query, '\0', sizeof (ao_pad_query));
+               } else if (ao_radio_cmac_rssi < -90) {
                        ao_led_on(AO_LED_AMBER);
                        ao_led_off(AO_LED_RED|AO_LED_GREEN);
                } else {
@@ -173,15 +214,28 @@ ao_lco_igniter_status(void)
                else
                        ao_led_off(AO_LED_REMOTE_ARM);
 
+               all_status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+               for (c = 0; c < 8; c++) {
+                       if (ao_pad_query.channels & (1 << c)) {
+                               uint8_t status = ao_pad_query.igniter_status[c];
+                               if (status > all_status)
+                                       all_status = status;
+                               PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status);
+                       }
+               }
                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;
-                       PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status);
-                       if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
+                       uint8_t on = 0;
+                       if (c == (ao_lco_box - ao_config.pad_box) % AO_LED_CONTINUITY_NUM) {
+                               switch (all_status) {
+                               case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN:
+                                       on = 1;
+                                       break;
+                               case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED:
+                               case AO_PAD_IGNITER_STATUS_UNKNOWN:
+                                       on = t & 1;
+                               }
+                       }
+                       if (on)
                                ao_led_on(continuity_led[c]);
                        else
                                ao_led_off(continuity_led[c]);
@@ -195,6 +249,8 @@ ao_lco_arm_warn(void)
 {
        int     i;
        for (;;) {
+               while (ao_lco_suspended)
+                       ao_sleep(&ao_lco_suspended);
                while (!ao_lco_armed)
                        ao_sleep(&ao_lco_armed);
                for (i = 0; i < ao_lco_armed; i++) {
@@ -215,33 +271,39 @@ ao_lco_monitor(void)
 {
        uint16_t                delay;
 
+       ao_config_get();
+       ao_lco_set_box(ao_button_get(AO_BUTTON_BOX));
        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_led_on(~0);
        ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+       ao_led_off(~0);
        for (;;) {
+               while (ao_lco_suspended)
+                       ao_sleep(&ao_lco_suspended);
+
                PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n",
                       ao_lco_armed, ao_lco_firing);
 
                if (ao_lco_armed && ao_lco_firing) {
-                       ao_lco_ignite();
+                       ao_lco_ignite(AO_PAD_FIRE);
                } else {
                        ao_lco_get_channels();
                        if (ao_lco_armed) {
-                               if (ao_lco_selected) {
-                                       PRINTD(DEBUG_STATUS, "Arming pads %x\n",
-                                              ao_lco_selected);
-                                       if (ao_lco_valid & AO_LCO_VALID_EVER) {
-                                               ao_lco_arm(ao_lco_box, ao_lco_selected, ao_lco_tick_offset);
-                                               ao_delay(AO_MS_TO_TICKS(10));
-                                       }
+                               PRINTD(DEBUG_STATUS, "Arming pads %x\n",
+                                      ao_lco_armed);
+                               if (ao_lco_valid & AO_LCO_VALID_EVER) {
+                                       ao_lco_arm(ao_lco_box, ao_lco_armed, ao_lco_tick_offset);
+                                       ao_delay(AO_MS_TO_TICKS(10));
                                }
                        }
                }
                if (ao_lco_armed && ao_lco_firing)
                        delay = AO_MS_TO_TICKS(100);
-               else
+               else {
                        delay = AO_SEC_TO_TICKS(1);
+               }
                ao_sleep_for(&ao_lco_armed, delay);
        }
 }