first cut at turnon scripts for EasyTimer v2
[fw/altos] / src / drivers / ao_lco_bits.c
index b2124d1b533e786140b925b5b27bc7f97874bcc5..ebe3d0cb2989b12ca59ca15fefd4ab2081a9dea7 100644 (file)
 
 uint8_t                ao_lco_debug;
 
-uint8_t                ao_lco_pad;
+int8_t         ao_lco_pad;
 int16_t                ao_lco_box;
+
+uint8_t                ao_lco_armed;                                   /* arm active */
+uint8_t                ao_lco_firing;                                  /* fire active */
+
+int16_t                ao_lco_min_box, ao_lco_max_box;
+
+uint8_t                ao_lco_pretending;
+
+#if AO_LCO_DRAG
 uint8_t                ao_lco_drag_race;
+#endif
 
-uint8_t                ao_lco_armed;   /* arm active */
-uint8_t                ao_lco_firing;  /* fire active */
+struct ao_pad_query    ao_pad_query;                           /* latest query response */
 
-uint8_t                ao_lco_min_box, ao_lco_max_box;
-uint8_t                ao_lco_selected[AO_PAD_MAX_BOXES];
-uint8_t                ao_lco_valid[AO_PAD_MAX_BOXES];
-uint8_t                ao_lco_channels[AO_PAD_MAX_BOXES];
-uint16_t       ao_lco_tick_offset[AO_PAD_MAX_BOXES];
+static uint8_t         ao_lco_channels[AO_PAD_MAX_BOXES];      /* pad channels available on each box */
+static uint16_t                ao_lco_tick_offset[AO_PAD_MAX_BOXES];   /* 16 bit offset from local to remote tick count */
+static uint8_t         ao_lco_selected[AO_PAD_MAX_BOXES];      /* pads selected to fire */
 
-struct ao_pad_query    ao_pad_query;
+uint8_t                ao_lco_valid[AO_PAD_MAX_BOXES];         /* AO_LCO_VALID bits per box */
 
-static AO_LED_TYPE     continuity_led[AO_LED_CONTINUITY_NUM] = {
+static const AO_LED_TYPE       continuity_led[AO_LED_CONTINUITY_NUM] = {
 #ifdef AO_LED_CONTINUITY_0
        AO_LED_CONTINUITY_0,
 #endif
@@ -68,10 +75,16 @@ ao_lco_igniter_status(void)
        uint8_t         t = 0;
 
        for (;;) {
+#if AO_LCO_DRAG
                if (ao_lco_drag_race)
                        ao_sleep_for(&ao_pad_query, AO_MS_TO_TICKS(50));
                else
+#endif
                        ao_sleep(&ao_pad_query);
+               if (ao_lco_box_pseudo(ao_lco_box)) {
+                       ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED);
+                       continue;
+               }
                PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid[ao_lco_box]);
                if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) {
                        ao_led_on(AO_LED_RED);
@@ -98,6 +111,7 @@ ao_lco_igniter_status(void)
                        else
                                status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
 
+#if AO_LCO_DRAG
                        if (ao_lco_drag_race && (ao_lco_selected[ao_lco_box] & (1 << c))) {
                                uint8_t on = 0;
                                if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) {
@@ -111,7 +125,9 @@ ao_lco_igniter_status(void)
                                        ao_led_on(continuity_led[c]);
                                else
                                        ao_led_off(continuity_led[c]);
-                       } else {
+                       } else
+#endif
+                       {
                                if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
                                        ao_led_on(continuity_led[c]);
                                else
@@ -123,10 +139,10 @@ ao_lco_igniter_status(void)
 }
 
 uint8_t
-ao_lco_pad_present(uint8_t box, uint8_t pad)
+ao_lco_pad_present(int16_t box, int8_t pad)
 {
        /* voltage measurement is always valid */
-       if (pad == AO_LCO_PAD_VOLTAGE)
+       if (ao_lco_pad_pseudo(pad))
                return 1;
        if (!ao_lco_channels[box])
                return 0;
@@ -135,10 +151,10 @@ ao_lco_pad_present(uint8_t box, uint8_t pad)
        return (ao_lco_channels[box] >> (pad - 1)) & 1;
 }
 
-uint8_t
-ao_lco_pad_first(uint8_t box)
+int8_t
+ao_lco_pad_first(int16_t box)
 {
-       uint8_t pad;
+       int8_t  pad;
 
        for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++)
                if (ao_lco_pad_present(box, pad))
@@ -147,16 +163,16 @@ ao_lco_pad_first(uint8_t box)
 }
 
 static uint8_t
-ao_lco_get_channels(uint8_t box, struct ao_pad_query *query)
+ao_lco_get_channels(int16_t box, struct ao_pad_query *query)
 {
        int8_t                  r;
 
-       r = ao_lco_query(box, query, &ao_lco_tick_offset[box]);
+       r = ao_lco_query((uint16_t) box, query, &ao_lco_tick_offset[box]);
        if (r == AO_RADIO_CMAC_OK) {
                ao_lco_channels[box] = query->channels;
                ao_lco_valid[box] = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
        } else
-               ao_lco_valid[box] &= ~AO_LCO_VALID_LAST;
+               ao_lco_valid[box] &= (uint8_t) ~AO_LCO_VALID_LAST;
        PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box]);
        ao_wakeup(&ao_pad_query);
        return ao_lco_valid[box];
@@ -165,16 +181,20 @@ ao_lco_get_channels(uint8_t box, struct ao_pad_query *query)
 void
 ao_lco_update(void)
 {
+       if (ao_lco_box_pseudo(ao_lco_box)) {
+               ao_lco_show();
+               return;
+       }
+
        uint8_t previous_valid = ao_lco_valid[ao_lco_box];
 
        if (ao_lco_get_channels(ao_lco_box, &ao_pad_query) & AO_LCO_VALID_LAST) {
                if (!(previous_valid & AO_LCO_VALID_EVER)) {
-                       if (ao_lco_pad != AO_LCO_PAD_VOLTAGE)
-                               ao_lco_pad = ao_lco_pad_first(ao_lco_box);
-                       ao_lco_set_display();
+                       if (!ao_lco_pad_pseudo(ao_lco_pad))
+                               ao_lco_set_pad(ao_lco_pad_first(ao_lco_box));
                }
-               if (ao_lco_pad == AO_LCO_PAD_VOLTAGE)
-                       ao_lco_set_display();
+               if (ao_lco_pad_pseudo(ao_lco_pad))
+                       ao_lco_show();
        }
 }
 
@@ -185,11 +205,12 @@ ao_lco_box_reset_present(void)
 {
        ao_lco_min_box = 0xff;
        ao_lco_max_box = 0x00;
+       ao_lco_pretending = 0;
        memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask));
 }
 
 static void
-ao_lco_box_set_present(uint8_t box)
+ao_lco_box_set_present(int16_t box)
 {
        if (box < ao_lco_min_box)
                ao_lco_min_box = box;
@@ -197,45 +218,151 @@ ao_lco_box_set_present(uint8_t box)
                ao_lco_max_box = box;
        if (box >= AO_PAD_MAX_BOXES)
                return;
-       ao_lco_box_mask[AO_LCO_MASK_ID(box)] |= 1 << AO_LCO_MASK_SHIFT(box);
+       ao_lco_box_mask[AO_LCO_MASK_ID(box)] |= (uint8_t) (1 << AO_LCO_MASK_SHIFT(box));
+}
+
+void
+ao_lco_set_pad(int8_t new_pad)
+{
+       ao_lco_pad = new_pad;
+       ao_lco_show();
+}
+
+void
+ao_lco_set_box(int16_t new_box)
+{
+       ao_lco_box = new_box;
+       if (!ao_lco_box_pseudo(ao_lco_box)) {
+               if (ao_lco_box < AO_PAD_MAX_BOXES) {
+                       if (ao_lco_pretending)
+                               ao_lco_channels[ao_lco_box] = 0xff;
+                       else
+                               ao_lco_channels[ao_lco_box] = 0;
+               }
+       }
+       ao_lco_pad = 1;
+       ao_lco_show();
 }
 
 void
 ao_lco_step_pad(int8_t dir)
 {
-       int8_t  new_pad;
+       int16_t new_pad;
+
+       switch (ao_lco_box) {
+#ifdef AO_LCO_HAS_CONTRAST
+       case AO_LCO_CONTRAST: {
+               int32_t contrast = ao_lco_get_contrast();
+
+               contrast = (contrast + AO_LCO_CONTRAST_STEP - 1) / AO_LCO_CONTRAST_STEP;
+               contrast += dir;
+               contrast *= AO_LCO_CONTRAST_STEP;
+               if (contrast < AO_LCO_MIN_CONTRAST)
+                       contrast = AO_LCO_MIN_CONTRAST;
+               if (contrast > AO_LCO_MAX_CONTRAST)
+                       contrast = AO_LCO_MAX_CONTRAST;
+               ao_lco_set_contrast(contrast);
+               ao_lco_show();
+               break;
+       }
+#endif
+#ifdef AO_LCO_HAS_BACKLIGHT
+       case AO_LCO_BACKLIGHT: {
+               int32_t backlight = ao_lco_get_backlight();
+
+               backlight = (backlight + AO_LCO_BACKLIGHT_STEP - 1) / AO_LCO_BACKLIGHT_STEP;
+               backlight += dir;
+               backlight *= AO_LCO_BACKLIGHT_STEP;
+               if (backlight < AO_LCO_MIN_BACKLIGHT)
+                       backlight = AO_LCO_MIN_BACKLIGHT;
+               if (backlight > AO_LCO_MAX_BACKLIGHT)
+                       backlight = AO_LCO_MAX_BACKLIGHT;
+               ao_lco_set_backlight(backlight);
+               ao_lco_show();
+               break;
+       }
+#endif
+#ifdef AO_LCO_HAS_INFO
+       case AO_LCO_INFO: {
+#if AO_LCO_MIN_INFO_PAGE < AO_LCO_MAX_INFO_PAGE
+               int32_t info_page = ao_lco_get_info_page();
+
+               info += dir;
+               if (info_page < AO_LCO_MIN_INFO_PAGE)
+                       info_page = AO_LCO_MIN_INFO_PAGE;
+               if (info_page > AO_LCO_MAX_INFO_PAGE)
+                       info_page = AO_LCO_MAX_INFO_PAGE;
+               ao_lco_set_info_page();
+#endif
+               break;
+       }
+#endif
+       default:
+               new_pad = (int16_t) ao_lco_pad;
+               do {
+                       new_pad += dir;
+                       if (new_pad > AO_PAD_MAX_CHANNELS)
+                               new_pad = AO_LCO_PAD_FIRST;
+                       if (new_pad < AO_LCO_PAD_FIRST)
+                               new_pad = AO_PAD_MAX_CHANNELS;
+                       if (new_pad == ao_lco_pad)
+                               break;
+               } while (!ao_lco_pad_present(ao_lco_box, (int8_t) new_pad));
+               PRINTD("New pad %d\n", new_pad);
+               ao_lco_set_pad((int8_t) new_pad);
+               break;
+       }
+}
+
+uint8_t
+ao_lco_box_present(int16_t box)
+{
+       if (ao_lco_box_pseudo(box))
+               return 1;
+       if (box >= AO_PAD_MAX_BOXES)
+               return 0;
+       return (ao_lco_box_mask[AO_LCO_MASK_ID(box)] >> AO_LCO_MASK_SHIFT(box)) & 1;
+}
+
+void
+ao_lco_step_box(int8_t dir)
+{
+       int16_t new_box = ao_lco_box;
 
-       new_pad = ao_lco_pad;
        do {
-               new_pad += dir;
-               if (new_pad > AO_PAD_MAX_CHANNELS)
-                       new_pad = AO_LCO_PAD_VOLTAGE;
-               if (new_pad < 0)
-                       new_pad = AO_PAD_MAX_CHANNELS;
-               if (new_pad == ao_lco_pad)
+               new_box += dir;
+               if (new_box > ao_lco_max_box)
+                       new_box = AO_LCO_BOX_FIRST;
+               else if (new_box < AO_LCO_BOX_FIRST)
+                       new_box = ao_lco_max_box;
+               if (new_box == ao_lco_box)
                        break;
-       } 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();
-       }
+       } while (!ao_lco_box_present(new_box));
+       PRINTD("New box %d\n", new_box);
+       ao_lco_set_box(new_box);
 }
 
 void
 ao_lco_set_armed(uint8_t armed)
 {
+       if (ao_lco_box_pseudo(ao_lco_box))
+               return;
+
        ao_lco_armed = armed;
        PRINTD("Armed %d\n", ao_lco_armed);
        if (ao_lco_armed) {
+#if AO_LCO_DRAG
                if (ao_lco_drag_race) {
-                       uint8_t box;
+                       int16_t box;
 
                        for (box = ao_lco_min_box; box <= ao_lco_max_box; box++)
                                if (ao_lco_selected[box])
                                        break;
                        if (box > ao_lco_max_box)
                                ao_lco_armed = 0;
-               } else {
+               } else
+#endif
+               {
                        memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
                        if (ao_lco_pad != 0)
                                ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1));
@@ -254,38 +381,60 @@ ao_lco_set_firing(uint8_t firing)
        ao_wakeup(&ao_lco_armed);
 }
 
-void
-ao_lco_toggle_drag(void)
+#if 0
+static int16_t fake_boxes[] = {
+       1, 2, 3, 5, 8, 11, 13, 17, 19, 23, 29, 31, 37, 62, 97
+};
+#define ARRAYSIZE(a)   (sizeof(a) / sizeof((a)[0]))
+#define NFAKE ARRAYSIZE(fake_boxes)
+
+static bool
+is_fake(int16_t box)
 {
-       if (ao_lco_drag_race && ao_lco_pad != AO_LCO_PAD_VOLTAGE) {
-               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_add_beeps(ao_lco_pad);
-       }
+       unsigned i;
+       for (i = 0; i < NFAKE; i++)
+               if (fake_boxes[i] == box)
+                       return true;
+       return false;
 }
+#else
+#define is_fake(b)     false
+#endif
 
 void
 ao_lco_search(void)
 {
        int8_t          r;
        int8_t          try;
-       uint8_t         box;
-       uint8_t         boxes = 0;
+       int16_t         box;
+       uint16_t        boxes = 0;
 
        ao_lco_box_reset_present();
-       ao_lco_set_pad(0);
+#ifdef AO_LCO_SEARCH_API
+       ao_lco_search_start();
+#else
+       ao_lco_show_box(0);
+       ao_lco_show_pad(0);
+#endif
        for (box = 0; box < AO_PAD_MAX_BOXES; box++) {
+#ifdef AO_LCO_SEARCH_API
+               ao_lco_search_box_check(box);
+#else
                if ((box % 10) == 0)
-                       ao_lco_set_box(box);
+                       ao_lco_show_box(box);
+#endif
                for (try = 0; try < 3; try++) {
                        ao_lco_tick_offset[box] = 0;
-                       r = ao_lco_query(box, &ao_pad_query, &ao_lco_tick_offset[box]);
+                       r = ao_lco_query((uint16_t) box, &ao_pad_query, &ao_lco_tick_offset[box]);
                        PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]);
-                       if (r == AO_RADIO_CMAC_OK) {
+                       if (r == AO_RADIO_CMAC_OK || is_fake(box)) {
                                ++boxes;
                                ao_lco_box_set_present(box);
-                               ao_lco_set_pad(boxes % 10);
+#ifdef AO_LCO_SEARCH_API
+                               ao_lco_search_box_present(box);
+#else
+                               ao_lco_show_pad((int8_t) (boxes % 10));
+#endif
                                ao_delay(AO_MS_TO_TICKS(30));
                                break;
                        }
@@ -297,15 +446,33 @@ ao_lco_search(void)
                ao_lco_min_box = ao_lco_max_box = ao_lco_box = 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();
+#ifdef AO_LCO_SEARCH_API
+       ao_lco_search_done();
+#endif
+       ao_lco_set_box(ao_lco_min_box);
+}
+
+void
+ao_lco_pretend(void)
+{
+       int16_t box;
+
+       ao_lco_pretending = 1;
+       ao_lco_min_box = 1;
+       ao_lco_max_box = AO_PAD_MAX_BOXES - 1;
+       for (box = ao_lco_min_box; box <= ao_lco_max_box; box++)
+               ao_lco_box_set_present(box);
+       ao_lco_box = ao_lco_min_box;
+       memset(ao_lco_valid, 0, sizeof (ao_lco_valid));
+       memset(ao_lco_channels, 0, sizeof (ao_lco_channels));
+       ao_lco_set_box(ao_lco_min_box);
 }
 
 void
 ao_lco_monitor(void)
 {
-       uint16_t                delay;
-       uint8_t                 box;
+       AO_TICK_TYPE    delay;
+       int16_t         box;
 
        for (;;) {
                PRINTD("monitor armed %d firing %d\n",
@@ -321,7 +488,7 @@ ao_lco_monitor(void)
                                                PRINTD("Arming box %d pads %x\n",
                                                       box, ao_lco_selected[box]);
                                                if (ao_lco_valid[box] & AO_LCO_VALID_EVER) {
-                                                       ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]);
+                                                       ao_lco_arm((uint16_t) box, ao_lco_selected[box], ao_lco_tick_offset[box]);
                                                        ao_delay(AO_MS_TO_TICKS(10));
                                                }
                                        }
@@ -336,17 +503,19 @@ ao_lco_monitor(void)
        }
 }
 
-uint8_t                        ao_lco_drag_beep_count;
+#if AO_LCO_DRAG
+
+int8_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 AO_TICK_TYPE    ao_lco_drag_beep_time;
+static AO_TICK_TYPE    ao_lco_drag_warn_time;
 
 #define AO_LCO_DRAG_BEEP_TIME  AO_MS_TO_TICKS(50)
 #define AO_LCO_DRAG_WARN_TIME  AO_SEC_TO_TICKS(5)
 
 /* Request 'beeps' additional drag race beeps */
 void
-ao_lco_drag_add_beeps(uint8_t beeps)
+ao_lco_drag_add_beeps(int8_t beeps)
 {
        PRINTD("beep %d\n", beeps);
        if (ao_lco_drag_beep_count == 0)
@@ -355,18 +524,30 @@ ao_lco_drag_add_beeps(uint8_t beeps)
        ao_wakeup(&ao_lco_drag_beep_count);
 }
 
+/* Toggle current pad in drag set */
+void
+ao_lco_toggle_drag(void)
+{
+       if (ao_lco_drag_race && !ao_lco_pad_pseudo(ao_lco_pad) && !ao_lco_box_pseudo(ao_lco_box)) {
+               ao_lco_selected[ao_lco_box] ^= (uint8_t) (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_add_beeps(ao_lco_pad);
+       }
+}
+
 /* Check whether it's time to change the beeper status, then either
  * turn it on or off as necessary and bump the remaining beep counts
  */
 
-uint16_t
-ao_lco_drag_beep_check(uint16_t now, uint16_t delay)
+AO_TICK_TYPE
+ao_lco_drag_beep_check(AO_TICK_TYPE now, AO_TICK_TYPE delay)
 {
-       PRINTD("beep check count %d delta %d\n",
+       PRINTD("beep check count %d delta %ld\n",
               ao_lco_drag_beep_count,
-              (int16_t) (now - ao_lco_drag_beep_time));
+              (long) (AO_TICK_SIGNED) (now - ao_lco_drag_beep_time));
        if (ao_lco_drag_beep_count) {
-               if ((int16_t) (now - ao_lco_drag_beep_time) >= 0) {
+               if ((AO_TICK_SIGNED) (now - ao_lco_drag_beep_time) >= 0) {
                        if (ao_lco_drag_beep_on) {
                                ao_beep(0);
                                PRINTD("beep stop\n");
@@ -386,7 +567,7 @@ ao_lco_drag_beep_check(uint16_t now, uint16_t delay)
        }
 
        if (ao_lco_drag_beep_count) {
-               uint16_t beep_delay = 0;
+               AO_TICK_TYPE beep_delay = 0;
 
                if (ao_lco_drag_beep_time > now)
                        beep_delay = ao_lco_drag_beep_time - now;
@@ -408,7 +589,7 @@ ao_lco_drag_enable(void)
                ao_led_on(AO_LED_DRAG);
 #endif
                ao_lco_drag_add_beeps(5);
-               ao_lco_set_display();
+               ao_lco_show();
        }
 }
 
@@ -423,7 +604,7 @@ ao_lco_drag_disable(void)
 #endif
                memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
                ao_lco_drag_add_beeps(2);
-               ao_lco_set_display();
+               ao_lco_show();
        }
 }
 
@@ -431,13 +612,13 @@ ao_lco_drag_disable(void)
  * active
  */
 
-uint16_t
-ao_lco_drag_warn_check(uint16_t now, uint16_t delay)
+AO_TICK_TYPE
+ao_lco_drag_warn_check(AO_TICK_TYPE now, AO_TICK_TYPE delay)
 {
        if (ao_lco_drag_race) {
-               uint16_t        warn_delay;
+               AO_TICK_TYPE    warn_delay;
 
-               if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) {
+               if ((AO_TICK_SIGNED) (now - ao_lco_drag_warn_time) >= 0) {
                        ao_lco_drag_add_beeps(1);
                        ao_lco_drag_warn_time = now + AO_LCO_DRAG_WARN_TIME;
                }
@@ -447,6 +628,7 @@ ao_lco_drag_warn_check(uint16_t now, uint16_t delay)
        }
        return delay;
 }
+#endif /* AO_LCO_DRAG */
 
 /* task function for beeping while arm is active */
 void