altos: Require sequencing through 'main' state before landing
[fw/altos] / src / ao_report.c
index e52b29281a3a1d46d614fd8c282b294b6afc22cc..3cf558e1d97ff9d72018fe0f14167f2c6702d9e1 100644 (file)
 
 #include "ao.h"
 
-static const char * __xdata flight_reports[] = {
-       "...",          /* startup, 'S' */
-       "..",           /* idle 'I' */
-       ".--.",         /* launchpad 'P' */
-       "-...",         /* boost 'B' */
-       "-.-.",         /* coast 'C' */
-       ".-",           /* apogee 'A' */
-       "-..",          /* drogue 'D' */
-       "--",           /* main 'M' */
-       ".-..",         /* landed 'L' */
-       ".-.-.-",       /* invalid */
+#define BIT(i,x)          ((x) ? (1 << (i)) : 0)
+#define MORSE1(a)          (1 | BIT(3,a))
+#define MORSE2(a,b)        (2 | BIT(3,a) | BIT(4,b))
+#define MORSE3(a,b,c)      (3 | BIT(3,a) | BIT(4,b) | BIT(5,c))
+#define MORSE4(a,b,c,d)    (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d))
+#define MORSE5(a,b,c,d,e)  (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e))
+
+static const uint8_t flight_reports[] = {
+       MORSE3(0,0,0),          /* startup, 'S' */
+       MORSE2(0,0),            /* idle 'I' */
+       MORSE4(0,1,1,0),        /* pad 'P' */
+       MORSE4(1,0,0,0),        /* boost 'B' */
+       MORSE4(0,0,1,0),        /* fast 'F' */
+       MORSE4(1,0,1,0),        /* coast 'C' */
+       MORSE3(1,0,0),          /* drogue 'D' */
+       MORSE2(1,1),            /* main 'M' */
+       MORSE4(0,1,0,0),        /* landed 'L' */
+       MORSE4(1,0,0,1),        /* invalid 'X' */
 };
 
-#if 1
-#define signal(time)   ao_beep_for(AO_BEEP_MID, time)
+#if HAS_BEEP
+#define low(time)      ao_beep_for(AO_BEEP_LOW, time)
+#define mid(time)      ao_beep_for(AO_BEEP_MID, time)
+#define high(time)     ao_beep_for(AO_BEEP_HIGH, time)
 #else
-#define signal(time)   ao_led_for(AO_LED_RED, time)
+#define low(time)      ao_led_for(AO_LED_GREEN, time)
+#define mid(time)      ao_led_for(AO_LED_RED, time)
+#define high(time)     ao_led_for(AO_LED_GREEN|AO_LED_RED, time)
 #endif
 #define pause(time)    ao_delay(time)
 
-static __xdata enum ao_flight_state ao_report_state;
+static __pdata enum ao_flight_state ao_report_state;
 
 static void
 ao_report_beep(void) __reentrant
 {
-       char *r = flight_reports[ao_flight_state];
-       char c;
+       uint8_t r = flight_reports[ao_flight_state];
+       uint8_t l = r & 7;
 
        if (!r)
                return;
-       while (c = *r++) {
-               if (c == '.')
-                       signal(AO_MS_TO_TICKS(200));
+       while (l--) {
+               if (r & 8)
+                       mid(AO_MS_TO_TICKS(600));
                else
-                       signal(AO_MS_TO_TICKS(600));
+                       mid(AO_MS_TO_TICKS(200));
                pause(AO_MS_TO_TICKS(200));
+               r >>= 1;
        }
        pause(AO_MS_TO_TICKS(400));
 }
@@ -61,11 +73,11 @@ static void
 ao_report_digit(uint8_t digit) __reentrant
 {
        if (!digit) {
-               signal(AO_MS_TO_TICKS(500));
+               mid(AO_MS_TO_TICKS(500));
                pause(AO_MS_TO_TICKS(200));
        } else {
                while (digit--) {
-                       signal(AO_MS_TO_TICKS(200));
+                       mid(AO_MS_TO_TICKS(200));
                        pause(AO_MS_TO_TICKS(200));
                }
        }
@@ -75,9 +87,9 @@ ao_report_digit(uint8_t digit) __reentrant
 static void
 ao_report_altitude(void)
 {
-       __xdata int16_t agl = ao_pres_to_altitude(ao_min_pres) - ao_pres_to_altitude(ao_ground_pres);
+       __pdata int16_t agl = ao_max_height;
        __xdata uint8_t digits[10];
-       __xdata uint8_t ndigits, i;
+       __pdata uint8_t ndigits, i;
 
        if (agl < 0)
                agl = 0;
@@ -97,6 +109,46 @@ ao_report_altitude(void)
        }
 }
 
+#if HAS_IGNITE
+static uint8_t
+ao_report_igniter_ready(enum ao_igniter igniter)
+{
+       return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0;
+}
+
+static void
+ao_report_continuity(void) __reentrant
+{
+       uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) |
+                    (ao_report_igniter_ready(ao_igniter_main) << 1));
+       if (c) {
+               while (c--) {
+                       high(AO_MS_TO_TICKS(25));
+                       pause(AO_MS_TO_TICKS(100));
+               }
+       } else {
+               c = 10;
+               while (c--) {
+                       high(AO_MS_TO_TICKS(20));
+                       low(AO_MS_TO_TICKS(20));
+               }
+       }
+       if (ao_log_full()) {
+               pause(AO_MS_TO_TICKS(100));
+               c = 2;
+               while (c--) {
+                       low(AO_MS_TO_TICKS(100));
+                       mid(AO_MS_TO_TICKS(100));
+                       high(AO_MS_TO_TICKS(100));
+                       mid(AO_MS_TO_TICKS(100));
+               }
+       }
+       c = 50;
+       while (c-- && ao_flight_state == ao_flight_pad)
+               pause(AO_MS_TO_TICKS(100));
+}
+#endif
+
 void
 ao_report(void)
 {
@@ -105,6 +157,12 @@ ao_report(void)
                if (ao_flight_state == ao_flight_landed)
                        ao_report_altitude();
                ao_report_beep();
+#if HAS_IGNITE
+               if (ao_flight_state == ao_flight_idle)
+                       ao_report_continuity();
+               while (ao_flight_state == ao_flight_pad)
+                       ao_report_continuity();
+#endif
                __critical {
                        while (ao_report_state == ao_flight_state)
                                ao_sleep(DATA_TO_XDATA(&ao_flight_state));