Puts TeleLCOTwo in a low power state (drawing about 80µA) after a
timeout (default two minutes) to keep from killing the battery if the
device is left turned on.
Signed-off-by: Keith Packard <keithp@keithp.com>
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout)
+{
+ uint8_t empty = 1;
+ ao_arch_critical(
+ while ((empty = ao_event_queue_empty()))
+ if (ao_sleep_for(&ao_event_queue, timeout))
+ break;
+ if (!empty) {
+ *ev = ao_event_queue[ao_event_queue_remove];
+ ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove);
+ }
+ );
+ return empty;
+}
+
/* called with interrupts disabled */
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value)
/* called with interrupts disabled */
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value)
void
ao_event_get(struct ao_event *ev);
void
ao_event_get(struct ao_event *ev);
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout);
+
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value);
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value);
#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 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
#endif
#define AO_LCO_VALID_LAST 1
#define AO_LCO_VALID_EVER 2
#endif
#define AO_LCO_VALID_LAST 1
#define AO_LCO_VALID_EVER 2
+static uint8_t ao_lco_suspended;
static uint8_t ao_lco_selected;
static uint8_t ao_lco_valid;
static uint8_t ao_lco_channels;
static uint8_t ao_lco_selected;
static uint8_t ao_lco_valid;
static uint8_t ao_lco_channels;
/* UI values */
static uint8_t ao_lco_armed;
static uint8_t ao_lco_firing;
/* 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)
#define ao_lco_box (ao_config.pad_box)
ao_wakeup(&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_selected = 0;
+ 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;
static void
ao_lco_input(void)
{
static struct ao_event 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) {
PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n",
event.type, event.unit, event.value);
switch (event.type) {
#endif
case AO_BUTTON_FIRE:
if (ao_lco_armed) {
#endif
case AO_BUTTON_FIRE:
if (ao_lco_armed) {
ao_lco_firing = event.value;
PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
ao_wakeup(&ao_lco_armed);
ao_lco_firing = event.value;
PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
ao_wakeup(&ao_lco_armed);
for (;;) {
ao_sleep(&ao_pad_query);
for (;;) {
ao_sleep(&ao_pad_query);
+ 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\n", ao_radio_cmac_rssi, ao_lco_valid);
if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
ao_led_on(AO_LED_RED);
PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid);
if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
ao_led_on(AO_LED_RED);
+ 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++) {
while (!ao_lco_armed)
ao_sleep(&ao_lco_armed);
for (i = 0; i < ao_lco_armed; i++) {
ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
for (;;) {
ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
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);
PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n",
ao_lco_armed, ao_lco_firing);
}
if (ao_lco_armed && ao_lco_firing)
delay = AO_MS_TO_TICKS(100);
}
if (ao_lco_armed && ao_lco_firing)
delay = AO_MS_TO_TICKS(100);
delay = AO_SEC_TO_TICKS(1);
delay = AO_SEC_TO_TICKS(1);
ao_sleep_for(&ao_lco_armed, delay);
}
}
ao_sleep_for(&ao_lco_armed, delay);
}
}
#if HAS_FIXED_PAD_BOX
if (minor < 22)
ao_config.pad_box = 1;
#if HAS_FIXED_PAD_BOX
if (minor < 22)
ao_config.pad_box = 1;
+ if (minor < 23)
+ ao_config.pad_idle = 120;
#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
ao_config.pad_box = ao_cmd_lex_i;
_ao_config_edit_finish();
}
ao_config.pad_box = ao_cmd_lex_i;
_ao_config_edit_finish();
}
+
+void
+ao_config_pad_idle_show(void)
+{
+ printf ("Idle timeout: %d\n", ao_config.pad_idle);
+}
+
+void
+ao_config_pad_idle_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_idle = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
#endif
struct ao_config_var {
#endif
struct ao_config_var {
#if HAS_FIXED_PAD_BOX
{ "B <box>\0Set pad box (1-99)",
ao_config_pad_box_set, ao_config_pad_box_show },
#if HAS_FIXED_PAD_BOX
{ "B <box>\0Set pad box (1-99)",
ao_config_pad_box_set, ao_config_pad_box_show },
+ { "i <seconds>\0Set idle timeout (0 disable)",
+ ao_config_pad_idle_set, ao_config_pad_idle_show },
#endif
{ "s\0Show",
ao_config_show, 0 },
#endif
{ "s\0Show",
ao_config_show, 0 },
#endif
#define AO_CONFIG_MAJOR 1
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 22
+#define AO_CONFIG_MINOR 23
#endif
#if HAS_FIXED_PAD_BOX
uint8_t pad_box; /* minor version 22 */
#endif
#if HAS_FIXED_PAD_BOX
uint8_t pad_box; /* minor version 22 */
+ uint8_t pad_idle; /* minor version 23 */