From 96ee5257068a988db10097af8df72b0008bce978 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 May 2018 22:02:11 -0700 Subject: altos: Add TeleLCO v2.0 product New LCO design with a single rotary knob and lots more buttons. Signed-off-by: Keith Packard --- src/telelco-v2.0/.gitignore | 2 + src/telelco-v2.0/Makefile | 103 +++++ src/telelco-v2.0/ao_lco_v2.c | 713 +++++++++++++++++++++++++++++++ src/telelco-v2.0/ao_pins.h | 358 ++++++++++++++++ src/telelco-v2.0/ao_telelco.c | 71 +++ src/telelco-v2.0/flash-loader/.gitignore | 2 + src/telelco-v2.0/flash-loader/Makefile | 8 + src/telelco-v2.0/flash-loader/ao_pins.h | 35 ++ 8 files changed, 1292 insertions(+) create mode 100644 src/telelco-v2.0/.gitignore create mode 100644 src/telelco-v2.0/Makefile create mode 100644 src/telelco-v2.0/ao_lco_v2.c create mode 100644 src/telelco-v2.0/ao_pins.h create mode 100644 src/telelco-v2.0/ao_telelco.c create mode 100644 src/telelco-v2.0/flash-loader/.gitignore create mode 100644 src/telelco-v2.0/flash-loader/Makefile create mode 100644 src/telelco-v2.0/flash-loader/ao_pins.h (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/.gitignore b/src/telelco-v2.0/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelco-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelco-v2.0/Makefile b/src/telelco-v2.0/Makefile new file mode 100644 index 00000000..75c66abf --- /dev/null +++ b/src/telelco-v2.0/Makefile @@ -0,0 +1,103 @@ +# +# AltOS build for TeleLCO v2.0 +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_companion.h \ + ao_data.h \ + ao_sample.h \ + ao_pins.h \ + ao_product.h \ + ao_seven_segment.h \ + ao_lco.h \ + ao_lco_cmd.h \ + ao_lco_func.h \ + ao_radio_spi.h \ + ao_radio_cmac.h \ + ao_cc1200_CC1200.h \ + ao_cc1200.h \ + stm32l.h + +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_beep_stm.c \ + ao_eeprom_stm.c \ + ao_fast_timer.c \ + ao_lcd_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_cc1200.c \ + ao_radio_cmac.c \ + ao_aes.c \ + ao_aes_tables.c \ + ao_fec_tx.c \ + ao_fec_rx.c \ + ao_seven_segment.c \ + ao_quadrature.c \ + ao_button.c \ + ao_event.c \ + ao_lco_v2.c \ + ao_lco_cmd.c \ + ao_lco_func.c \ + ao_radio_cmac_cmd.c + +PRODUCT=TeleLCO-v2.0 +PRODUCT_DEF=-DTELELCO +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telelco-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telelco.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c new file mode 100644 index 00000000..6f2b618a --- /dev/null +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -0,0 +1,713 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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; 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 + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG 1 + +#if DEBUG +static uint8_t ao_lco_debug; +#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) +#else +#define PRINTD(...) +#endif + +#define AO_LCO_PAD_DIGIT 0 +#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) + +#define AO_LCO_VALID_LAST 1 +#define AO_LCO_VALID_EVER 2 + +static uint8_t ao_lco_min_box, ao_lco_max_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 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 int16_t ao_lco_box; +static uint8_t ao_lco_select_mode; +#define AO_LCO_SELECT_PAD 0 +#define AO_LCO_SELECT_BOX 1 +#define AO_LCO_SELECT_NONE 2 + +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_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); +} + +#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_box(uint16_t box) +{ + 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 +ao_lco_set_voltage(uint16_t decivolts) +{ + uint8_t tens, ones, tenths; + + 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 +ao_lco_set_display(void) +{ + if (ao_lco_pad == 0) { + ao_lco_set_voltage(ao_pad_query.battery); + } else { + ao_lco_set_pad(ao_lco_pad); + ao_lco_set_box(ao_lco_box); + } +} + +#define MASK_SIZE(n) (((n) + 7) >> 3) +#define MASK_ID(n) ((n) >> 3) +#define MASK_SHIFT(n) ((n) & 7) + +static uint8_t ao_lco_box_mask[MASK_SIZE(AO_PAD_MAX_BOXES)]; + +static uint8_t +ao_lco_box_present(uint16_t box) +{ + if (box >= AO_PAD_MAX_BOXES) + return 0; + return (ao_lco_box_mask[MASK_ID(box)] >> MASK_SHIFT(box)) & 1; +} + +static uint8_t +ao_lco_pad_present(uint8_t box, uint8_t pad) +{ + /* 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_lco_channels[box] >> (pad - 1)) & 1; +} + +static uint8_t +ao_lco_pad_first(uint8_t box) +{ + uint8_t pad; + + for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++) + if (ao_lco_pad_present(box, pad)) + return pad; + return 0; +} + +static void +ao_lco_set_select(void) +{ + switch (ao_lco_select_mode) { + case AO_LCO_SELECT_PAD: + ao_led_off(AO_LED_BOX); + ao_led_on(AO_LED_PAD); + break; + case AO_LCO_SELECT_BOX: + ao_led_off(AO_LED_PAD); + ao_led_on(AO_LED_BOX); + break; + default: + ao_led_off(AO_LED_PAD); + ao_led_off(AO_LED_BOX); + break; + } +} + +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; + +#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(); + ao_lco_fire_down = 0; +} + +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 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); + + /* 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) +{ + static struct ao_event event; + int8_t dir, new_pad; + int16_t new_box; + + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + for (;;) { + ao_event_get(&event); + PRINTD("event type %d unit %d value %d\n", + event.type, event.unit, event.value); + switch (event.type) { + case AO_EVENT_QUADRATURE: + switch (event.unit) { + case AO_QUADRATURE_SELECT: + if (!ao_lco_armed) { + switch (ao_lco_select_mode) { + case AO_LCO_SELECT_PAD: + dir = (int8_t) event.value; + new_pad = ao_lco_pad; + do { + new_pad += dir; + if (new_pad > AO_PAD_MAX_CHANNELS) + new_pad = 0; + if (new_pad < 0) + new_pad = AO_PAD_MAX_CHANNELS; + if (new_pad == ao_lco_pad) + 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(); + } + break; + case AO_LCO_SELECT_BOX: + dir = (int8_t) event.value; + new_box = ao_lco_box; + do { + new_box += dir; + if (new_box > ao_lco_max_box) + new_box = ao_lco_min_box; + else if (new_box < ao_lco_min_box) + new_box = ao_lco_max_box; + if (new_box == ao_lco_box) + break; + } while (!ao_lco_box_present(new_box)); + if (ao_lco_box != new_box) { + ao_lco_box = new_box; + ao_lco_pad = 1; + ao_lco_channels[ao_lco_box] = 0; + ao_lco_set_display(); + } + break; + default: + break; + } + } + break; + } + break; + case AO_EVENT_BUTTON: + switch (event.unit) { + 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 { + 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)); + else + ao_lco_armed = 0; + } + } + 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); + } + break; + case AO_BUTTON_DRAG_SELECT: + if (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); + } + } + break; + case AO_BUTTON_MODE_SELECT: + if (event.value) + ao_lco_drag_enable(); + else + ao_lco_drag_disable(); + break; + case AO_BUTTON_SELECT: + ao_lco_select_mode++; + if (ao_lco_select_mode > AO_LCO_SELECT_NONE) + ao_lco_select_mode = AO_LCO_SELECT_PAD; + ao_lco_set_select(); + break; + } + break; + } + } +} + +static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { +#ifdef AO_LED_CONTINUITY_0 + AO_LED_CONTINUITY_0, +#endif +#ifdef AO_LED_CONTINUITY_1 + AO_LED_CONTINUITY_1, +#endif +#ifdef AO_LED_CONTINUITY_2 + AO_LED_CONTINUITY_2, +#endif +#ifdef AO_LED_CONTINUITY_3 + AO_LED_CONTINUITY_3, +#endif +#ifdef AO_LED_CONTINUITY_4 + AO_LED_CONTINUITY_4, +#endif +#ifdef AO_LED_CONTINUITY_5 + AO_LED_CONTINUITY_5, +#endif +#ifdef AO_LED_CONTINUITY_6 + AO_LED_CONTINUITY_6, +#endif +#ifdef AO_LED_CONTINUITY_7 + AO_LED_CONTINUITY_7, +#endif +}; + +static uint8_t +ao_lco_get_channels(uint8_t box, struct ao_pad_query *query) +{ + int8_t r; + + r = ao_lco_query(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; + 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]; +} + +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) & AO_LCO_VALID_LAST) { + if (!(previous_valid & AO_LCO_VALID_EVER)) { + if (ao_lco_pad != 0) + ao_lco_pad = ao_lco_pad_first(ao_lco_box); + ao_lco_set_display(); + } + if (ao_lco_pad == 0) + ao_lco_set_display(); + } +} + +static void +ao_lco_box_reset_present(void) +{ + ao_lco_min_box = 0xff; + ao_lco_max_box = 0x00; + memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask)); +} + +static void +ao_lco_box_set_present(uint8_t box) +{ + if (box < ao_lco_min_box) + ao_lco_min_box = box; + if (box > ao_lco_max_box) + ao_lco_max_box = box; + if (box >= AO_PAD_MAX_BOXES) + return; + ao_lco_box_mask[MASK_ID(box)] |= 1 << MASK_SHIFT(box); +} + +static void +ao_lco_search(void) +{ + int8_t r; + int8_t try; + uint8_t box; + uint8_t boxes = 0; + + ao_lco_box_reset_present(); + ao_lco_set_pad(0); + for (box = 0; box < AO_PAD_MAX_BOXES; box++) { + if ((box % 10) == 0) + ao_lco_set_box(box); + 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]); + PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]); + if (r == AO_RADIO_CMAC_OK) { + ++boxes; + ao_lco_box_set_present(box); + ao_lco_set_pad(boxes % 10); + ao_delay(AO_MS_TO_TICKS(30)); + break; + } + } + } + if (ao_lco_min_box <= ao_lco_max_box) + ao_lco_box = ao_lco_min_box; + else + 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(); +} + +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[ao_lco_box]); + if (!(ao_lco_valid[ao_lco_box] & 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) { + ao_led_on(AO_LED_AMBER); + ao_led_off(AO_LED_RED|AO_LED_GREEN); + } else { + ao_led_on(AO_LED_GREEN); + ao_led_off(AO_LED_RED|AO_LED_AMBER); + } + if (ao_pad_query.arm_status) + 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_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; + } +} + +static void +ao_lco_arm_warn(void) +{ + for (;;) { + while (!ao_lco_armed) { + ao_led_off(AO_LED_FIRE); + ao_sleep(&ao_lco_armed); + } + ao_led_on(AO_LED_FIRE); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_delay(AO_MS_TO_TICKS(200)); + } +} + +static struct ao_task ao_lco_input_task; +static struct ao_task ao_lco_monitor_task; +static struct ao_task ao_lco_arm_warn_task; +static struct ao_task ao_lco_igniter_status_task; + +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\n", + ao_lco_armed, ao_lco_firing); + + if (ao_lco_armed && ao_lco_firing) { + ao_lco_ignite(AO_PAD_FIRE); + } 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_VALID_EVER) { + ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]); + ao_delay(AO_MS_TO_TICKS(10)); + } + } + } + } + } + if (ao_lco_armed && ao_lco_firing) + delay = AO_MS_TO_TICKS(100); + else + delay = AO_SEC_TO_TICKS(1); + ao_sleep_for(&ao_lco_armed, delay); + } +} + +#if DEBUG +void +ao_lco_set_debug(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) + ao_lco_debug = ao_cmd_lex_i != 0; +} + +__code struct ao_cmds ao_lco_cmds[] = { + { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" }, + { ao_lco_search, "s\0Search for pad boxes" }, + { 0, NULL } +}; +#endif + +void +ao_lco_init(void) +{ + ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); +#if DEBUG + ao_cmd_register(&ao_lco_cmds[0]); +#endif +} diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h new file mode 100644 index 00000000..d8cf4dec --- /dev/null +++ b/src/telelco-v2.0/ao_pins.h @@ -0,0 +1,358 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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; 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 + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC 40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 1 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 +#define HAS_AES 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 /* CC1200 */ +#define SPI_2_PB13_PB14_PB15 0 +#define SPI_2_PD1_PD3_PD4 1 +#define SPI_2_GPIO (&stm_gpiod) +#define SPI_2_SCK 1 +#define SPI_2_MISO 3 +#define SPI_2_MOSI 4 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_I2C_1 0 + +#define HAS_I2C_2 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 0 + +#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_CC1200_SPI_CS_PORT (&stm_gpiod) +#define AO_CC1200_SPI_CS_PIN 0 +#define AO_CC1200_SPI_BUS AO_SPI_2_PD1_PD3_PD4 +#define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST + +#define AO_CC1200_INT_PORT (&stm_gpiod) +#define AO_CC1200_INT_PIN (5) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PER_LED 1 +#define LED_TYPE uint16_t + +#define LED_ENABLE_BITS ((1 << STM_RCC_AHBENR_GPIOAEN) | \ + (1 << STM_RCC_AHBENR_GPIOCEN) | \ + (1 << STM_RCC_AHBENR_GPIODEN) | \ + (1 << STM_RCC_AHBENR_GPIOEEN)) + +/* PC7 - PC9, LED 0 - 2 */ +#define LED_0_PORT (&stm_gpioc) +#define LED_0_PIN 7 +#define LED_1_PORT (&stm_gpioc) +#define LED_1_PIN 8 +#define LED_2_PORT (&stm_gpioc) +#define LED_2_PIN 9 + +/* PD8 - PD10, LED 3 - 5 */ +#define LED_3_PORT (&stm_gpiod) +#define LED_3_PIN 8 +#define LED_4_PORT (&stm_gpiod) +#define LED_4_PIN 9 +#define LED_5_PORT (&stm_gpiod) +#define LED_5_PIN 10 + +/* PE2 - PE11 (not PE6), LED 6-14 */ +#define LED_6_PORT (&stm_gpioe) +#define LED_6_PIN 2 +#define LED_7_PORT (&stm_gpioe) +#define LED_7_PIN 3 +#define LED_8_PORT (&stm_gpioe) +#define LED_8_PIN 4 +#define LED_9_PORT (&stm_gpioe) +#define LED_9_PIN 5 +#define LED_10_PORT (&stm_gpioe) +#define LED_10_PIN 7 +#define LED_11_PORT (&stm_gpioe) +#define LED_11_PIN 8 +#define LED_12_PORT (&stm_gpioe) +#define LED_12_PIN 9 +#define LED_13_PORT (&stm_gpioe) +#define LED_13_PIN 10 +#define LED_14_PORT (&stm_gpioe) +#define LED_14_PIN 11 + +/* PA5, LED 15 */ +#define LED_15_PORT (&stm_gpioa) +#define LED_15_PIN 5 + +#define LED_PIN_RED 0 +#define LED_PIN_AMBER 1 +#define LED_PIN_GREEN 2 +#define LED_PIN_BOX 3 +#define LED_PIN_PAD 4 +#define LED_PIN_DRAG 5 +#define LED_PIN_CONTINUITY_7 6 +#define LED_PIN_CONTINUITY_6 7 +#define LED_PIN_CONTINUITY_5 8 +#define LED_PIN_CONTINUITY_4 9 +#define LED_PIN_CONTINUITY_3 10 +#define LED_PIN_CONTINUITY_2 11 +#define LED_PIN_CONTINUITY_1 12 +#define LED_PIN_CONTINUITY_0 13 +#define LED_PIN_REMOTE_ARM 14 +#define LED_PIN_FIRE 15 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_AMBER (1 << LED_PIN_AMBER) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) +#define AO_LED_BOX (1 << LED_PIN_BOX) +#define AO_LED_PAD (1 << LED_PIN_PAD) +#define AO_LED_DRAG (1 << LED_PIN_DRAG) +#define AO_LED_CONTINUITY_7 (1 << LED_PIN_CONTINUITY_7) +#define AO_LED_CONTINUITY_6 (1 << LED_PIN_CONTINUITY_6) +#define AO_LED_CONTINUITY_5 (1 << LED_PIN_CONTINUITY_5) +#define AO_LED_CONTINUITY_4 (1 << LED_PIN_CONTINUITY_4) +#define AO_LED_CONTINUITY_3 (1 << LED_PIN_CONTINUITY_3) +#define AO_LED_CONTINUITY_2 (1 << LED_PIN_CONTINUITY_2) +#define AO_LED_CONTINUITY_1 (1 << LED_PIN_CONTINUITY_1) +#define AO_LED_CONTINUITY_0 (1 << LED_PIN_CONTINUITY_0) +#define AO_LED_CONTINUITY_NUM 8 +#define AO_LED_REMOTE_ARM (1 << LED_PIN_REMOTE_ARM) +#define AO_LED_FIRE (1 << LED_PIN_FIRE) + +#define LEDS_AVAILABLE (AO_LED_RED | \ + AO_LED_AMBER | \ + AO_LED_GREEN | \ + AO_LED_BOX | \ + AO_LED_PAD | \ + AO_LED_DRAG | \ + AO_LED_CONTINUITY_7 | \ + AO_LED_CONTINUITY_6 | \ + AO_LED_CONTINUITY_5 | \ + AO_LED_CONTINUITY_4 | \ + AO_LED_CONTINUITY_3 | \ + AO_LED_CONTINUITY_2 | \ + AO_LED_CONTINUITY_1 | \ + AO_LED_CONTINUITY_0 | \ + AO_LED_REMOTE_ARM | \ + AO_LED_FIRE) + +/* LCD displays */ + +#define LCD_DEBUG 0 +#define SEVEN_SEGMENT_DEBUG 0 + +#define AO_LCD_STM_SEG_ENABLED_0 ( \ + (1 << 0) | /* PA1 */ \ + (1 << 1) | /* PA2 */ \ + (1 << 2) | /* PA3 */ \ + (1 << 3) | /* PA6 */ \ + (1 << 4) | /* PA7 */ \ + (1 << 5) | /* PB0 */ \ + (1 << 6) | /* PB1 */ \ + (1 << 7) | /* PB3 */ \ + (1 << 8) | /* PB4 */ \ + (1 << 9) | /* PB5 */ \ + (1 << 10) | /* PB10 */ \ + (1 << 11) | /* PB11 */ \ + (1 << 12) | /* PB12 */ \ + (1 << 13) | /* PB13 */ \ + (1 << 14) | /* PB14 */ \ + (1 << 15) | /* PB15 */ \ + (1 << 16) | /* PB8 */ \ + (1 << 17) | /* PA15 */ \ + (1 << 18) | /* PC0 */ \ + (1 << 19) | /* PC1 */ \ + (1 << 20) | /* PC2 */ \ + (1 << 21) | /* PC3 */ \ + (1 << 22) | /* PC4 */ \ + (1 << 23) | /* PC5 */ \ + (0 << 24) | /* PC6 */ \ + (0 << 25) | /* PC7 */ \ + (0 << 26) | /* PC8 */ \ + (0 << 27) | /* PC9 */ \ + (0 << 28) | /* PC10 or PD8 */ \ + (0 << 29) | /* PC11 or PD9 */ \ + (0 << 30) | /* PC12 or PD10 */ \ + (0 << 31)) /* PD2 or PD11 */ + +#define AO_LCD_STM_SEG_ENABLED_1 ( \ + (0 << 0) | /* PD12 */ \ + (0 << 1) | /* PD13 */ \ + (0 << 2) | /* PD14 */ \ + (0 << 3) | /* PD15 */ \ + (0 << 4) | /* PE0 */ \ + (0 << 5) | /* PE1 */ \ + (0 << 6) | /* PE2 */ \ + (0 << 7)) /* PE3 */ + +#define AO_LCD_STM_COM_ENABLED ( \ + (1 << 0) | /* PA8 */ \ + (0 << 1) | /* PA9 */ \ + (0 << 2) | /* PA10 */ \ + (0 << 3) | /* PB9 */ \ + (0 << 4) | /* PC10 */ \ + (0 << 5) | /* PC11 */ \ + (0 << 6)) /* PC12 */ + +#define AO_LCD_28_ON_C 0 + +#define AO_LCD_DUTY STM_LCD_CR_DUTY_STATIC + +#define AO_LCD_PER_DIGIT 1 + +#define AO_LCD_DIGITS 3 +#define AO_LCD_SEGMENTS 8 + +#define AO_SEGMENT_MAP { \ + /* pad segments */ \ + { 0, 14 }, \ + { 0, 13 }, \ + { 0, 15 }, \ + { 0, 17 }, \ + { 0, 16 }, \ + { 0, 8 }, \ + { 0, 9 }, \ + { 0, 7 }, \ + /* box1 segments */ \ + { 0, 10 }, \ + { 0, 6 }, \ + { 0, 11 }, \ + { 0, 12 }, \ + { 0, 21 }, \ + { 0, 19 }, \ + { 0, 20 }, \ + { 0, 18 }, \ + /* box0 segments */ \ + { 0, 22 }, \ + { 0, 4 }, \ + { 0, 23 }, \ + { 0, 5 }, \ + { 0, 3 }, \ + { 0, 1 }, \ + { 0, 2 }, \ + { 0, 0 }, \ +} + +/* + * Use event queue for input devices + */ + +#define AO_EVENT 1 + +/* + * Knobs + */ + +#define AO_QUADRATURE_COUNT 1 + +#define AO_QUADRATURE_0_PORT &stm_gpioe +#define AO_QUADRATURE_0_A 15 +#define AO_QUADRATURE_0_B 14 + +#define AO_QUADRATURE_SELECT 0 + +/* + * Buttons + */ + +#define AO_BUTTON_COUNT 9 +#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_MODE_SELECT 0 +#define AO_BUTTON_0_PORT &stm_gpioe +#define AO_BUTTON_0 1 + +#define AO_BUTTON_DRAG_SELECT 1 +#define AO_BUTTON_1_PORT &stm_gpioe +#define AO_BUTTON_1 1 + +#define AO_BUTTON_SPARE1 2 +#define AO_BUTTON_2_PORT &stm_gpiob +#define AO_BUTTON_2 9 + +#define AO_BUTTON_SPARE2 3 +#define AO_BUTTON_3_PORT &stm_gpiob +#define AO_BUTTON_3 7 + +#define AO_BUTTON_SPARE3 4 +#define AO_BUTTON_4_PORT &stm_gpiob +#define AO_BUTTON_4 6 + +#define AO_BUTTON_ARM 5 +#define AO_BUTTON_5_PORT &stm_gpioe +#define AO_BUTTON_5 12 + +#define AO_BUTTON_FIRE 6 +#define AO_BUTTON_6_PORT &stm_gpioa +#define AO_BUTTON_6 4 + +#define AO_BUTTON_SPARE4 7 +#define AO_BUTTON_7_PORT &stm_gpiod +#define AO_BUTTON_7 11 + +#define AO_BUTTON_SELECT 8 +#define AO_BUTTON_8_PORT &stm_gpioe +#define AO_BUTTON_8 13 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v2.0/ao_telelco.c b/src/telelco-v2.0/ao_telelco.c new file mode 100644 index 00000000..7b04d386 --- /dev/null +++ b/src/telelco-v2.0/ao_telelco.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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; 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 + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_task_init(); + + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_beep_init(); + ao_cmd_init(); + + ao_lcd_stm_init(); + ao_seven_segment_init(); + ao_quadrature_init(); + ao_button_init(); + + ao_eeprom_init(); + + ao_radio_init(); + + ao_usb_init(); + + ao_config_init(); + + ao_lco_init(); + ao_lco_cmd_init(); +// ao_radio_cmac_cmd_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/telelco-v2.0/flash-loader/.gitignore b/src/telelco-v2.0/flash-loader/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelco-v2.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelco-v2.0/flash-loader/Makefile b/src/telelco-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..b4ec2dad --- /dev/null +++ b/src/telelco-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telelco-v2.0 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telelco-v2.0/flash-loader/ao_pins.h b/src/telelco-v2.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..2292f03c --- /dev/null +++ b/src/telelco-v2.0/flash-loader/ao_pins.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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; 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 + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +/* Drag race select button. Press at power on to get boot loader */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioe +#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From eb70e334ffc77e737bb21ab3fe777a982d80ee3b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 11:12:36 -0700 Subject: altos/telelco-v2: Change select button to alternate box/pad mode Instead of a three-way, just make the select button two-way and have the arming switch disable it. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 79 ++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 55 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 6f2b618a..16903d78 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -52,15 +52,12 @@ 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 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 int16_t ao_lco_box; static uint8_t ao_lco_select_mode; #define AO_LCO_SELECT_PAD 0 #define AO_LCO_SELECT_BOX 1 -#define AO_LCO_SELECT_NONE 2 static struct ao_pad_query ao_pad_query; @@ -167,19 +164,22 @@ ao_lco_pad_first(uint8_t box) static void ao_lco_set_select(void) { - switch (ao_lco_select_mode) { - case AO_LCO_SELECT_PAD: - ao_led_off(AO_LED_BOX); - ao_led_on(AO_LED_PAD); - break; - case AO_LCO_SELECT_BOX: - ao_led_off(AO_LED_PAD); - ao_led_on(AO_LED_BOX); - break; - default: + if (ao_lco_armed) { ao_led_off(AO_LED_PAD); ao_led_off(AO_LED_BOX); - break; + } else { + switch (ao_lco_select_mode) { + case AO_LCO_SELECT_PAD: + ao_led_off(AO_LED_BOX); + ao_led_on(AO_LED_PAD); + break; + case AO_LCO_SELECT_BOX: + ao_led_off(AO_LED_PAD); + ao_led_on(AO_LED_BOX); + break; + default: + break; + } } } @@ -254,7 +254,6 @@ ao_lco_drag_enable(void) memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); ao_lco_drag_beep(5); ao_lco_set_display(); - ao_lco_fire_down = 0; } static void @@ -265,34 +264,6 @@ ao_lco_drag_disable(void) 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 @@ -330,12 +301,11 @@ ao_lco_drag_monitor(void) 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); /* 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) { + if (!ao_lco_drag_race && !ao_lco_drag_beep_count) { delay = ~0; ao_lco_drag_active = 0; } @@ -412,12 +382,11 @@ ao_lco_input(void) 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); + 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 { memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); if (ao_lco_pad != 0) @@ -426,11 +395,11 @@ ao_lco_input(void) ao_lco_armed = 0; } } + ao_lco_set_select(); 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); @@ -453,10 +422,10 @@ ao_lco_input(void) ao_lco_drag_disable(); break; case AO_BUTTON_SELECT: - ao_lco_select_mode++; - if (ao_lco_select_mode > AO_LCO_SELECT_NONE) - ao_lco_select_mode = AO_LCO_SELECT_PAD; - ao_lco_set_select(); + if (!ao_lco_armed) { + ao_lco_select_mode = 1 - ao_lco_select_mode; + ao_lco_set_select(); + } break; } break; -- cgit v1.2.3 From 7e2a2849f58e98adc1114bb8f3a6319408d93691 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 12:06:41 -0700 Subject: altos/telelco-v2.0: Only switch encoder mode on push, not release Was not checking event value. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 16903d78..1f38ec81 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -422,9 +422,11 @@ ao_lco_input(void) ao_lco_drag_disable(); break; case AO_BUTTON_SELECT: - if (!ao_lco_armed) { - ao_lco_select_mode = 1 - ao_lco_select_mode; - ao_lco_set_select(); + if (event.value) { + if (!ao_lco_armed) { + ao_lco_select_mode = 1 - ao_lco_select_mode; + ao_lco_set_select(); + } } break; } -- cgit v1.2.3 From f172b139ddc3fcc17cf89b57e5126264c0faa45e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 13:08:33 -0700 Subject: altos/telelco-v2.0: Reduce quadrature debounce time The optical encoders shouldn't bounce at all; let's try a minimal value. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_pins.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index d8cf4dec..46a766c1 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -305,6 +305,7 @@ */ #define AO_QUADRATURE_COUNT 1 +#define AO_QUADRATURE_DEBOUNCE 1 #define AO_QUADRATURE_0_PORT &stm_gpioe #define AO_QUADRATURE_0_A 15 -- cgit v1.2.3 From a26cf26e3416b1982abec249678a32a420bf8809 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 14:26:12 -0700 Subject: altos/telelco-v2.0: Use single-step quadrature code Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_pins.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index 46a766c1..cdca5c10 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -305,7 +305,8 @@ */ #define AO_QUADRATURE_COUNT 1 -#define AO_QUADRATURE_DEBOUNCE 1 +#define AO_QUADRATURE_DEBOUNCE 0 +#define AO_QUADRATURE_SINGLE_CODE 1 #define AO_QUADRATURE_0_PORT &stm_gpioe #define AO_QUADRATURE_0_A 15 -- cgit v1.2.3 From 2c94ba66d5b4c99b43ab965331bf1faa270a9768 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 14:26:47 -0700 Subject: altos/telelco-v2.0: Only look at drag select presses, not releases Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 1f38ec81..748b552f 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -406,7 +406,7 @@ ao_lco_input(void) } break; case AO_BUTTON_DRAG_SELECT: - if (ao_lco_drag_race) { + if (event.value && 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", -- cgit v1.2.3 From b1f1a4513391aa595eb64552f2aa4cfedd0cc0ff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 14:35:18 -0700 Subject: altos/telelco-v2.0: Mixed up the select_button pin (is E0, was set to E13) Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index cdca5c10..77caf254 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -355,6 +355,6 @@ #define AO_BUTTON_SELECT 8 #define AO_BUTTON_8_PORT &stm_gpioe -#define AO_BUTTON_8 13 +#define AO_BUTTON_8 0 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 98ea690cc7514f43254f3a6c72668c11820f657c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 14:41:51 -0700 Subject: altos/telelco-v2.0: Fix button names and pin mappings. Add drag LED. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 6 ++++-- src/telelco-v2.0/ao_pins.h | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 748b552f..cc6ab13a 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -252,6 +252,7 @@ ao_lco_drag_enable(void) PRINTD("Drag enable\n"); ao_lco_drag_race = 1; memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); + ao_led_on(AO_LED_DRAG); ao_lco_drag_beep(5); ao_lco_set_display(); } @@ -261,6 +262,7 @@ ao_lco_drag_disable(void) { PRINTD("Drag disable\n"); ao_lco_drag_race = 0; + ao_led_off(AO_LED_DRAG); memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); ao_lco_drag_beep(2); ao_lco_set_display(); @@ -415,13 +417,13 @@ ao_lco_input(void) } } break; - case AO_BUTTON_MODE_SELECT: + case AO_BUTTON_DRAG_MODE: if (event.value) ao_lco_drag_enable(); else ao_lco_drag_disable(); break; - case AO_BUTTON_SELECT: + case AO_BUTTON_ENCODER_SELECT: if (event.value) { if (!ao_lco_armed) { ao_lco_select_mode = 1 - ao_lco_select_mode; diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index 77caf254..73ce9d6c 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -321,13 +321,13 @@ #define AO_BUTTON_COUNT 9 #define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP -#define AO_BUTTON_MODE_SELECT 0 +#define AO_BUTTON_DRAG_MODE 0 #define AO_BUTTON_0_PORT &stm_gpioe #define AO_BUTTON_0 1 #define AO_BUTTON_DRAG_SELECT 1 #define AO_BUTTON_1_PORT &stm_gpioe -#define AO_BUTTON_1 1 +#define AO_BUTTON_1 0 #define AO_BUTTON_SPARE1 2 #define AO_BUTTON_2_PORT &stm_gpiob @@ -353,8 +353,8 @@ #define AO_BUTTON_7_PORT &stm_gpiod #define AO_BUTTON_7 11 -#define AO_BUTTON_SELECT 8 +#define AO_BUTTON_ENCODER_SELECT 8 #define AO_BUTTON_8_PORT &stm_gpioe -#define AO_BUTTON_8 0 +#define AO_BUTTON_8 13 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 29f9880f7b09bc135d34bf0dcb221bdede7726b3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 14:54:47 -0700 Subject: altos/telelco-v2.0: A bit fancier with the drag-mode LED show Continutity leds now show whether the pad is included in the drag race *and* the continutity using four different patterns: Drag select & igniter present: long on, short off Drag select & igniter missing: short on, long off Not select & igniter present: solid on Not select & igniter missing: solid off Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index cc6ab13a..d78f54d2 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -581,23 +581,32 @@ ao_lco_igniter_status(void) for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { uint8_t status; - if (ao_lco_drag_race) { - if (ao_lco_selected[ao_lco_box] & (1 << c) && t) + 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 (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) { + if (t) + on = 1; + } else { + if (!t) + on = 1; + } + if (on) 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; + t = (t + 1) & 3; } } -- cgit v1.2.3 From eb31a40b3499287e0a52324a9adc3728883ed957 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 15:07:06 -0700 Subject: altos/telelco-v2.0: Add debug output for pad voltage display Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index d78f54d2..371b978a 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -102,6 +102,7 @@ ao_lco_set_voltage(uint16_t decivolts) { uint8_t tens, ones, tenths; + PRINTD("voltage %d\n", decivolts); tenths = decivolts % 10; ones = (decivolts / 10) % 10; tens = (decivolts / 100) % 10; -- cgit v1.2.3 From dbeb9b91a48418c5bc9f6edccaef20c3ef77d45d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 15:12:26 -0700 Subject: altos/telelco-v2.0: Change drag race selected/no-continutity pattern Make it turn on at the same time as the pads with continuity, but turn off sooner Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 371b978a..45895908 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -593,7 +593,7 @@ ao_lco_igniter_status(void) if (t) on = 1; } else { - if (!t) + if (t == 1) on = 1; } if (on) -- cgit v1.2.3 From 42a261a56606be69b5fb90fd6017c70a1e5d72dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 16:10:51 -0700 Subject: altos/telelco-v2.0: Display local batt voltage at startup Show the battery voltage for a second at startup. Signed-off-by: Keith Packard --- src/telelco-v2.0/Makefile | 2 ++ src/telelco-v2.0/ao_lco_v2.c | 14 ++++++++++++++ src/telelco-v2.0/ao_pins.h | 36 ++++++++++++++++++++++++++++++++++++ src/telelco-v2.0/ao_telelco.c | 2 ++ 4 files changed, 54 insertions(+) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/Makefile b/src/telelco-v2.0/Makefile index 75c66abf..4871993d 100644 --- a/src/telelco-v2.0/Makefile +++ b/src/telelco-v2.0/Makefile @@ -50,6 +50,8 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_beep_stm.c \ ao_eeprom_stm.c \ + ao_adc_single_stm.c \ + ao_convert_volt.c \ ao_fast_timer.c \ ao_lcd_stm.c \ ao_usb_stm.c \ diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 45895908..140955da 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -23,6 +23,7 @@ #include #include #include +#include #define DEBUG 1 @@ -625,6 +626,18 @@ ao_lco_arm_warn(void) } } +static void +ao_lco_batt_voltage(void) +{ + struct ao_adc packet; + int16_t decivolt; + + ao_adc_single_get(&packet); + decivolt = ao_battery_decivolt(packet.v_batt); + ao_lco_set_voltage(decivolt); + ao_delay(AO_MS_TO_TICKS(1000)); +} + static struct ao_task ao_lco_input_task; static struct ao_task ao_lco_monitor_task; static struct ao_task ao_lco_arm_warn_task; @@ -636,6 +649,7 @@ ao_lco_monitor(void) uint16_t delay; uint8_t box; + ao_lco_batt_voltage(); 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"); diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index 73ce9d6c..4311bac8 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -357,4 +357,40 @@ #define AO_BUTTON_8_PORT &stm_gpioe #define AO_BUTTON_8 13 +/* ADC */ + +struct ao_adc { + int16_t v_batt; +}; + +#define AO_ADC_DUMP(p) \ + printf("batt: %5d\n", p.v_batt) + +#define HAS_ADC_TEMP 0 +#define HAS_BATTERY_REPORT 1 + +#define AO_ADC_V_BATT 0 +#define AO_ADC_V_BATT_PORT (&stm_gpioa) +#define AO_ADC_V_BATT_PIN 0 + +#define AO_ADC_RCC_AHBENR (1 << STM_RCC_AHBENR_GPIOAEN) + +#define AO_ADC_PIN0_PORT AO_ADC_V_BATT_PORT +#define AO_ADC_PIN0_PIN AO_ADC_V_BATT_PIN + +#define AO_ADC_SQ1 AO_ADC_V_BATT + +#define AO_NUM_ADC 1 + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS 15 /* 15k */ +#define AO_BATTERY_DIV_MINUS 27 /* 27k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV 33 + #endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v2.0/ao_telelco.c b/src/telelco-v2.0/ao_telelco.c index 7b04d386..9693c657 100644 --- a/src/telelco-v2.0/ao_telelco.c +++ b/src/telelco-v2.0/ao_telelco.c @@ -30,6 +30,7 @@ #include #include #include +#include int main(void) @@ -45,6 +46,7 @@ main(void) ao_spi_init(); ao_dma_init(); ao_exti_init(); + ao_adc_single_init(); ao_beep_init(); ao_cmd_init(); -- cgit v1.2.3 From 484ffebc54048bbe276e0e2c0e2ab52c6a1761c1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 19:19:43 -0700 Subject: altos/telelco-v2.0: Set HAS_ADC_SINGLE to enable HSI timer The ADC unit requires the HSI timer to run, so make sure it's enabled for this device. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_pins.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index 4311bac8..61a8676a 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -366,6 +366,7 @@ struct ao_adc { #define AO_ADC_DUMP(p) \ printf("batt: %5d\n", p.v_batt) +#define HAS_ADC_SINGLE 1 #define HAS_ADC_TEMP 0 #define HAS_BATTERY_REPORT 1 -- cgit v1.2.3 From f755181fd3ec82d7644591e2ed4b99a244acfd6e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 May 2018 22:42:13 -0700 Subject: altos/telelco-v2.0: Test displays at power on At boot, light up all LEDS and LCD segments for a second to let the user verify that things are working correctly. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 140955da..1be8ecb2 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -626,6 +626,23 @@ ao_lco_arm_warn(void) } } +/* + * Light up everything for a second at power on to let the user + * visually inspect the system for correct operation + */ +static void +ao_lco_display_test() +{ + ao_mutex_get(&ao_lco_display_mutex); + ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, 8 | 0x10); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 8 | 0x10); + ao_mutex_put(&ao_lco_display_mutex); + ao_led_on(LEDS_AVAILABLE); + ao_delay(AO_MS_TO_TICKS(1000)); + ao_led_off(LEDS_AVAILABLE); +} + static void ao_lco_batt_voltage(void) { @@ -649,6 +666,7 @@ ao_lco_monitor(void) uint16_t delay; uint8_t box; + ao_lco_display_test(); ao_lco_batt_voltage(); ao_lco_search(); ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); -- cgit v1.2.3 From 5d9881547706b49cc22b98cc5c94e01e8a7f5181 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 May 2018 22:45:49 -0700 Subject: altos/telelco: Remove STATIC_TEST code from stand-alone LCO boxes This command conflicts with the 'debug' command in these devices and so wasn't usable anyways. Signed-off-by: Keith Packard --- src/drivers/ao_lco_cmd.c | 11 ++++++++++- src/telelco-v0.3/ao_pins.h | 2 ++ src/telelco-v2.0/ao_pins.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src/telelco-v2.0') diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c index 8de21fb6..dba9a76a 100644 --- a/src/drivers/ao_lco_cmd.c +++ b/src/drivers/ao_lco_cmd.c @@ -22,6 +22,10 @@ #include #include +#ifndef HAS_STATIC_TEST +#define HAS_STATIC_TEST 1 +#endif + static __pdata uint16_t lco_box; static __pdata uint8_t lco_channels; static __pdata uint16_t tick_offset; @@ -150,6 +154,7 @@ lco_fire_cmd(void) __reentrant } } +#if HAS_STATIC_TEST static void lco_static_cmd(void) __reentrant { @@ -182,6 +187,7 @@ lco_static_cmd(void) __reentrant ao_delay(AO_MS_TO_TICKS(100)); } } +#endif static void lco_arm_cmd(void) __reentrant @@ -208,18 +214,21 @@ lco_ignite_cmd(void) __reentrant } +#if HAS_STATIC_TEST static void lco_endstatic_cmd(void) __reentrant { lco_ignite(AO_PAD_ENDSTATIC); } +#endif static __code struct ao_cmds ao_lco_cmds[] = { { lco_report_cmd, "l \0Get remote status" }, { lco_fire_cmd, "F \0Fire remote igniters" }, - { lco_fire_cmd, "F \0Fire remote igniters" }, +#if HAS_STATIC_TEST { lco_static_cmd, "S \0Initiate static test" }, { lco_endstatic_cmd, "D\0End static test (and download someday)" }, +#endif { lco_arm_cmd, "a \0Arm remote igniter" }, { lco_ignite_cmd, "i \0Pulse remote igniter" }, { 0, NULL }, diff --git a/src/telelco-v0.3/ao_pins.h b/src/telelco-v0.3/ao_pins.h index dd4aaafb..6fd897a0 100644 --- a/src/telelco-v0.3/ao_pins.h +++ b/src/telelco-v0.3/ao_pins.h @@ -54,6 +54,8 @@ #define HAS_RADIO_RATE 1 #define HAS_TELEMETRY 0 #define HAS_AES 1 +#define HAS_STATIC_TEST 0 + #define HAS_SPI_1 0 #define SPI_1_PA5_PA6_PA7 0 diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index 61a8676a..48aeabdf 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -54,6 +54,7 @@ #define HAS_RADIO_RATE 1 #define HAS_TELEMETRY 0 #define HAS_AES 1 +#define HAS_STATIC_TEST 0 #define HAS_SPI_1 0 #define SPI_1_PA5_PA6_PA7 0 -- cgit v1.2.3 From 290506129fb6cb664da3a5e3ca450a0dcdff0398 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2018 01:20:01 -0700 Subject: altos/telelco-v2.0: Fix AO_ADC_DUMP Was printing p.v_batt instead of (p)->v_batt. I don't know why the former even worked. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index 48aeabdf..95998dc7 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -365,7 +365,7 @@ struct ao_adc { }; #define AO_ADC_DUMP(p) \ - printf("batt: %5d\n", p.v_batt) + printf("batt: %5d\n", (p)->v_batt) #define HAS_ADC_SINGLE 1 #define HAS_ADC_TEMP 0 -- cgit v1.2.3 From 655fd8e1490b70061cd81edf1d019e0469843688 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 18 Jun 2018 10:53:35 -0700 Subject: altos/telelco-v2.0: Do all drag race beeping from the beeping thread Instead of starting the beep from the calling thread, just update some state and poke the beeping thread. Signed-off-by: Keith Packard --- src/telelco-v2.0/ao_lco_v2.c | 122 +++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 62 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 1be8ecb2..21b2c54d 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -186,7 +186,6 @@ ao_lco_set_select(void) } 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; @@ -195,37 +194,21 @@ static uint16_t 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 */ 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) +ao_lco_drag_add_beeps(uint8_t beeps) { PRINTD("beep %d\n", beeps); - if (!ao_lco_drag_beep_count) - ao_lco_drag_beep_start(); + if (ao_lco_drag_beep_count == 0) + ao_lco_drag_beep_time = ao_time(); ao_lco_drag_beep_count += beeps; + ao_wakeup(&ao_lco_drag_beep_count); } +/* 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 + */ + static uint16_t ao_lco_drag_beep_check(uint16_t now, uint16_t delay) { @@ -234,16 +217,32 @@ ao_lco_drag_beep_check(uint16_t now, uint16_t delay) (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_on) { + 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 = now + AO_LCO_DRAG_BEEP_TIME; + } + } else { + ao_beep(AO_BEEP_HIGH); + PRINTD("beep start\n"); + ao_lco_drag_beep_on = 1; + ao_lco_drag_beep_time = now + AO_LCO_DRAG_BEEP_TIME; + } } } if (ao_lco_drag_beep_count) { - if (delay > AO_LCO_DRAG_BEEP_TIME) - delay = AO_LCO_DRAG_BEEP_TIME; + uint16_t beep_delay = 0; + + if (ao_lco_drag_beep_time > now) + beep_delay = ao_lco_drag_beep_time - now; + + if (delay > beep_delay) + delay = beep_delay; } return delay; } @@ -251,39 +250,47 @@ ao_lco_drag_beep_check(uint16_t now, uint16_t 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_led_on(AO_LED_DRAG); - ao_lco_drag_beep(5); - ao_lco_set_display(); + if (!ao_lco_drag_race) { + PRINTD("Drag enable\n"); + ao_lco_drag_race = 1; + memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); + ao_led_on(AO_LED_DRAG); + ao_lco_drag_add_beeps(5); + ao_lco_set_display(); + } } static void ao_lco_drag_disable(void) { - PRINTD("Drag disable\n"); - ao_lco_drag_race = 0; - ao_led_off(AO_LED_DRAG); - memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); - ao_lco_drag_beep(2); - ao_lco_set_display(); + if (ao_lco_drag_race) { + PRINTD("Drag disable\n"); + ao_lco_drag_race = 0; + ao_led_off(AO_LED_DRAG); + memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); + ao_lco_drag_add_beeps(2); + ao_lco_set_display(); + } } +/* add a beep if it's time to warn the user that drag race mode is + * active + */ + static uint16_t ao_lco_drag_warn_check(uint16_t now, uint16_t delay) { - uint16_t warn_delay = ~0; - if (ao_lco_drag_race) { + uint16_t warn_delay; + if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) { - ao_lco_drag_beep(1); + ao_lco_drag_add_beeps(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; } - if (delay > warn_delay) - delay = warn_delay; return delay; } @@ -294,25 +301,16 @@ ao_lco_drag_monitor(void) uint16_t now; for (;;) { - PRINTD("Drag monitor active %d delay %d\n", ao_lco_drag_active, delay); + PRINTD("Drag monitor count %d delay %d\n", ao_lco_drag_beep_count, delay); if (delay == (uint16_t) ~0) - ao_sleep(&ao_lco_drag_active); + ao_sleep(&ao_lco_drag_beep_count); else - ao_sleep_for(&ao_lco_drag_active, delay); + ao_sleep_for(&ao_lco_drag_beep_count, delay); delay = ~0; - if (!ao_lco_drag_active) - continue; - now = ao_time(); delay = ao_lco_drag_warn_check(now, delay); delay = ao_lco_drag_beep_check(now, delay); - - /* check to see if there's anything left to do here */ - if (!ao_lco_drag_race && !ao_lco_drag_beep_count) { - delay = ~0; - ao_lco_drag_active = 0; - } } } @@ -415,7 +413,7 @@ ao_lco_input(void) 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_lco_drag_add_beeps(ao_lco_pad); } } break; -- cgit v1.2.3 From c48d4b60da8b23bf358e6c14d7332d3a360c2d2f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2018 01:00:15 -0700 Subject: altos: Share common LCO functions in ao_lco_bits.c Move common code out of ao_lco.c and ao_lco_v2.c into a shared file, ao_lco_bits.c. Update ao_lco.h to include shared functions. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 517 +++++---------------------------------- src/drivers/ao_lco.h | 116 +++++++++ src/drivers/ao_lco_bits.c | 468 +++++++++++++++++++++++++++++++++++ src/telelco-v0.2-cc1200/Makefile | 1 + src/telelco-v0.2/Makefile | 1 + src/telelco-v0.3/Makefile | 1 + src/telelco-v2.0/Makefile | 1 + src/telelco-v2.0/ao_lco_v2.c | 475 +++-------------------------------- 8 files changed, 679 insertions(+), 901 deletions(-) create mode 100644 src/drivers/ao_lco_bits.c (limited to 'src/telelco-v2.0') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 91a0593f..6b270042 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -27,15 +27,6 @@ #include #endif -#define DEBUG 1 - -#if DEBUG -static uint8_t ao_lco_debug; -#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) -#else -#define PRINTD(...) -#endif - #define AO_LCO_PAD_DIGIT 0 #define AO_LCO_BOX_DIGIT_1 1 #define AO_LCO_BOX_DIGIT_10 2 @@ -46,28 +37,15 @@ static uint8_t ao_lco_debug; #define AO_LCO_VALID_LAST 1 #define AO_LCO_VALID_EVER 2 -static uint8_t ao_lco_min_box, ao_lco_max_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 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 int16_t ao_lco_box; #define AO_LCO_BOX_DRAG 0x1000 -static struct ao_pad_query ao_pad_query; - static uint8_t ao_lco_display_mutex; -static void +void ao_lco_set_pad(uint8_t pad) { ao_mutex_get(&ao_lco_display_mutex); @@ -92,7 +70,7 @@ ao_lco_set_pad(uint8_t pad) (0 << 5) | \ (0 << 6)) -static void +void ao_lco_set_box(uint16_t box) { ao_mutex_get(&ao_lco_display_mutex); @@ -106,7 +84,7 @@ ao_lco_set_box(uint16_t box) ao_mutex_put(&ao_lco_display_mutex); } -static void +void ao_lco_set_voltage(uint16_t decivolts) { uint8_t tens, ones, tenths; @@ -121,7 +99,7 @@ ao_lco_set_voltage(uint16_t decivolts) ao_mutex_put(&ao_lco_display_mutex); } -static void +void ao_lco_set_display(void) { if (ao_lco_pad == 0 && ao_lco_box != AO_LCO_BOX_DRAG) { @@ -135,13 +113,7 @@ ao_lco_set_display(void) } } -#define MASK_SIZE(n) (((n) + 7) >> 3) -#define MASK_ID(n) ((n) >> 3) -#define MASK_SHIFT(n) ((n) & 7) - -static uint8_t ao_lco_box_mask[MASK_SIZE(AO_PAD_MAX_BOXES)]; - -static uint8_t +uint8_t ao_lco_box_present(uint16_t box) { if (box == AO_LCO_BOX_DRAG) @@ -149,117 +121,11 @@ ao_lco_box_present(uint16_t box) if (box >= AO_PAD_MAX_BOXES) return 0; - return (ao_lco_box_mask[MASK_ID(box)] >> MASK_SHIFT(box)) & 1; -} - -static uint8_t -ao_lco_pad_present(uint8_t box, uint8_t pad) -{ - /* 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_lco_channels[box] >> (pad - 1)) & 1; -} - -static uint8_t -ao_lco_pad_first(uint8_t box) -{ - uint8_t pad; - - for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++) - if (ao_lco_pad_present(box, pad)) - return pad; - return 0; + return (ao_lco_box_mask[AO_LCO_MASK_ID(box)] >> AO_LCO_MASK_SHIFT(box)) & 1; } 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; - -#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(); - ao_lco_fire_down = 0; -} - -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) @@ -272,13 +138,17 @@ ao_lco_drag_button_check(uint16_t now, uint16_t delay) */ if (ao_lco_fire_down) { if (ao_lco_drag_race) { - if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_STOP_TIME) + if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_STOP_TIME) { ao_lco_drag_disable(); + ao_lco_fire_down = 0; + } 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) + if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_START_TIME) { ao_lco_drag_enable(); + ao_lco_fire_down = 0; + } else button_delay = ao_lco_fire_tick + AO_LCO_DRAG_RACE_START_TIME - now; } @@ -288,35 +158,20 @@ ao_lco_drag_button_check(uint16_t now, uint16_t 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 void ao_lco_drag_monitor(void) { uint16_t delay = ~0; uint16_t now; + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { - PRINTD("Drag monitor active %d delay %d\n", ao_lco_drag_active, delay); + PRINTD("Drag monitor count %d active %d delay %d\n", + ao_lco_drag_beep_count, ao_lco_drag_active, delay); if (delay == (uint16_t) ~0) - ao_sleep(&ao_lco_drag_active); + ao_sleep(&ao_lco_drag_beep_count); else - ao_sleep_for(&ao_lco_drag_active, delay); + ao_sleep_for(&ao_lco_drag_beep_count, delay); delay = ~0; if (!ao_lco_drag_active) @@ -335,14 +190,40 @@ ao_lco_drag_monitor(void) } } +static void +ao_lco_step_box(int8_t dir) +{ + int16_t new_box = ao_lco_box; + do { + if (new_box == AO_LCO_BOX_DRAG) { + if (dir < 0) + new_box = ao_lco_max_box; + else + new_box = ao_lco_min_box; + } else { + new_box += dir; + if (new_box > ao_lco_max_box) + new_box = AO_LCO_BOX_DRAG; + else if (new_box < ao_lco_min_box) + new_box = AO_LCO_BOX_DRAG; + } + if (new_box == ao_lco_box) + break; + } while (!ao_lco_box_present(new_box)); + if (ao_lco_box != new_box) { + ao_lco_box = new_box; + ao_lco_pad = 1; + if (ao_lco_box != AO_LCO_BOX_DRAG) + ao_lco_channels[ao_lco_box] = 0; + ao_lco_set_display(); + } +} + static void ao_lco_input(void) { static struct ao_event event; - int8_t dir, new_pad; - int16_t new_box; - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { ao_event_get(&event); PRINTD("event type %d unit %d value %d\n", @@ -351,106 +232,38 @@ ao_lco_input(void) case AO_EVENT_QUADRATURE: switch (event.unit) { case AO_QUADRATURE_PAD: - if (!ao_lco_armed) { - dir = (int8_t) event.value; - new_pad = ao_lco_pad; - do { - new_pad += dir; - if (new_pad > AO_PAD_MAX_CHANNELS) - new_pad = 0; - if (new_pad < 0) - new_pad = AO_PAD_MAX_CHANNELS; - if (new_pad == ao_lco_pad) - 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(); - } - } + if (!ao_lco_armed) + ao_lco_step_pad((int8_t) event.value); break; case AO_QUADRATURE_BOX: - if (!ao_lco_armed) { - dir = (int8_t) event.value; - new_box = ao_lco_box; - do { - if (new_box == AO_LCO_BOX_DRAG) { - if (dir < 0) - new_box = ao_lco_max_box; - else - new_box = ao_lco_min_box; - } else { - new_box += dir; - if (new_box > ao_lco_max_box) - new_box = AO_LCO_BOX_DRAG; - else if (new_box < ao_lco_min_box) - new_box = AO_LCO_BOX_DRAG; - } - if (new_box == ao_lco_box) - break; - } while (!ao_lco_box_present(new_box)); - if (ao_lco_box != new_box) { - ao_lco_box = new_box; - ao_lco_pad = 1; - if (ao_lco_box != AO_LCO_BOX_DRAG) - ao_lco_channels[ao_lco_box] = 0; - ao_lco_set_display(); - } - } + if (!ao_lco_armed) + ao_lco_step_box((int8_t) event.value); break; } break; case AO_EVENT_BUTTON: switch (event.unit) { 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 { - memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); - if (ao_lco_pad != 0 && ao_lco_box != AO_LCO_BOX_DRAG) - ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1)); - else - ao_lco_armed = 0; - } - } - ao_wakeup(&ao_lco_armed); + ao_lco_set_armed(event.value); 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); + ao_lco_set_firing(event.value); } else { if (event.value) { if (ao_lco_box == AO_LCO_BOX_DRAG) { ao_lco_fire_down = 1; ao_lco_fire_tick = ao_time(); ao_lco_drag_active = 1; + ao_wakeup(&ao_lco_drag_beep_count); + } else { + ao_lco_toggle_drag(); } - if (ao_lco_drag_race) { - if (ao_lco_pad != 0 && ao_lco_box != AO_LCO_BOX_DRAG) { - 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); + ao_wakeup(&ao_lco_drag_beep_count); } } break; @@ -460,189 +273,6 @@ ao_lco_input(void) } } -static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { -#ifdef AO_LED_CONTINUITY_0 - AO_LED_CONTINUITY_0, -#endif -#ifdef AO_LED_CONTINUITY_1 - AO_LED_CONTINUITY_1, -#endif -#ifdef AO_LED_CONTINUITY_2 - AO_LED_CONTINUITY_2, -#endif -#ifdef AO_LED_CONTINUITY_3 - AO_LED_CONTINUITY_3, -#endif -#ifdef AO_LED_CONTINUITY_4 - AO_LED_CONTINUITY_4, -#endif -#ifdef AO_LED_CONTINUITY_5 - AO_LED_CONTINUITY_5, -#endif -#ifdef AO_LED_CONTINUITY_6 - AO_LED_CONTINUITY_6, -#endif -#ifdef AO_LED_CONTINUITY_7 - AO_LED_CONTINUITY_7, -#endif -}; - -static uint8_t -ao_lco_get_channels(uint8_t box, struct ao_pad_query *query) -{ - int8_t r; - - r = ao_lco_query(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; - 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]; -} - -static void -ao_lco_update(void) -{ - if (ao_lco_box != AO_LCO_BOX_DRAG) { - 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 != 0) - ao_lco_pad = ao_lco_pad_first(ao_lco_box); - ao_lco_set_display(); - } - if (ao_lco_pad == 0) - ao_lco_set_display(); - } - } -} - -static void -ao_lco_box_reset_present(void) -{ - ao_lco_min_box = 0xff; - ao_lco_max_box = 0x00; - memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask)); -} - -static void -ao_lco_box_set_present(uint8_t box) -{ - if (box < ao_lco_min_box) - ao_lco_min_box = box; - if (box > ao_lco_max_box) - ao_lco_max_box = box; - if (box >= AO_PAD_MAX_BOXES) - return; - ao_lco_box_mask[MASK_ID(box)] |= 1 << MASK_SHIFT(box); -} - -static void -ao_lco_search(void) -{ - int8_t r; - int8_t try; - uint8_t box; - uint8_t boxes = 0; - - ao_lco_box_reset_present(); - ao_lco_set_pad(0); - for (box = 0; box < AO_PAD_MAX_BOXES; box++) { - if ((box % 10) == 0) - ao_lco_set_box(box); - 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]); - PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]); - if (r == AO_RADIO_CMAC_OK) { - ++boxes; - ao_lco_box_set_present(box); - ao_lco_set_pad(boxes % 10); - ao_delay(AO_MS_TO_TICKS(30)); - break; - } - } - } - if (ao_lco_min_box <= ao_lco_max_box) - ao_lco_box = ao_lco_min_box; - else - 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(); -} - -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_box == AO_LCO_BOX_DRAG ? -1 : ao_lco_valid[ao_lco_box]); - if (ao_lco_box == AO_LCO_BOX_DRAG) { - ao_led_off(AO_LED_RED|AO_LED_GREEN|AO_LED_AMBER); - for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) - ao_led_off(continuity_led[c]); - } else { - if (!(ao_lco_valid[ao_lco_box] & 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) { - ao_led_on(AO_LED_AMBER); - ao_led_off(AO_LED_RED|AO_LED_GREEN); - } else { - ao_led_on(AO_LED_GREEN); - ao_led_off(AO_LED_RED|AO_LED_AMBER); - } - if (ao_pad_query.arm_status) - 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_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; - } - } -} - -static void -ao_lco_arm_warn(void) -{ - for (;;) { - while (!ao_lco_armed) - ao_sleep(&ao_lco_armed); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - ao_delay(AO_MS_TO_TICKS(200)); - } -} - /* * Light up everything for a second at power on to let the user * visually inspect the system for correct operation @@ -680,11 +310,8 @@ static struct ao_task ao_lco_arm_warn_task; static struct ao_task ao_lco_igniter_status_task; static void -ao_lco_monitor(void) +ao_lco_main(void) { - uint16_t delay; - uint8_t box; - ao_lco_display_test(); #if HAS_ADC_SINGLE ao_lco_batt_voltage(); @@ -694,33 +321,7 @@ ao_lco_monitor(void) 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\n", - ao_lco_armed, ao_lco_firing); - - if (ao_lco_armed && ao_lco_firing) { - ao_lco_ignite(AO_PAD_FIRE); - } 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_VALID_EVER) { - ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]); - ao_delay(AO_MS_TO_TICKS(10)); - } - } - } - } - } - if (ao_lco_armed && ao_lco_firing) - delay = AO_MS_TO_TICKS(100); - else - delay = AO_SEC_TO_TICKS(1); - ao_sleep_for(&ao_lco_armed, delay); - } + ao_lco_monitor(); } #if DEBUG @@ -742,7 +343,7 @@ __code struct ao_cmds ao_lco_cmds[] = { void ao_lco_init(void) { - ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); + ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor"); #if DEBUG ao_cmd_register(&ao_lco_cmds[0]); #endif diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h index 5721eed5..d5aace0d 100644 --- a/src/drivers/ao_lco.h +++ b/src/drivers/ao_lco.h @@ -19,7 +19,123 @@ #ifndef _AO_LCO_H_ #define _AO_LCO_H_ +#include + +#define DEBUG 1 + +#if DEBUG +extern uint8_t ao_lco_debug; +#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) +#else +#define PRINTD(...) +#endif + +extern uint8_t ao_lco_drag_race; /* TRUE when drag race mode enabled */ +extern uint8_t ao_lco_pad; /* Currently selected pad */ +extern int16_t ao_lco_box; /* Currently selected box */ + +extern uint8_t ao_lco_armed; +extern uint8_t ao_lco_firing; + +extern struct ao_pad_query ao_pad_query; /* Last received QUERY from pad */ + +#define AO_LCO_VALID_LAST 1 +#define AO_LCO_VALID_EVER 2 + +#define AO_LCO_PAD_VOLTAGE 0 /* Pad number to show box voltage */ + +extern uint8_t ao_lco_min_box, ao_lco_max_box; +extern uint8_t ao_lco_selected[AO_PAD_MAX_BOXES]; +extern uint8_t ao_lco_valid[AO_PAD_MAX_BOXES]; +extern uint8_t ao_lco_channels[AO_PAD_MAX_BOXES]; +extern uint16_t ao_lco_tick_offset[AO_PAD_MAX_BOXES]; + +#define AO_LCO_MASK_SIZE(n) (((n) + 7) >> 3) +#define AO_LCO_MASK_ID(n) ((n) >> 3) +#define AO_LCO_MASK_SHIFT(n) ((n) & 7) + +extern uint8_t ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)]; + +/* + * Shared functions + */ + +void +ao_lco_igniter_status(void); + +void +ao_lco_update(void); + +uint8_t +ao_lco_pad_present(uint8_t box, uint8_t pad); + +uint8_t +ao_lco_pad_first(uint8_t box); + +void +ao_lco_step_pad(int8_t dir); + +void +ao_lco_set_armed(uint8_t armed); + +void +ao_lco_set_firing(uint8_t firing); + +void +ao_lco_toggle_drag(void); + +void +ao_lco_search(void); + +void +ao_lco_monitor(void); + +extern uint8_t ao_lco_drag_beep_count; + +/* enable drag race mode */ +void +ao_lco_drag_enable(void); + +/* disable drag race mode */ +void +ao_lco_drag_disable(void); + +/* Handle drag beeps, return new delay */ +uint16_t +ao_lco_drag_beep_check(uint16_t now, uint16_t delay); + +/* Check if it's time to beep during drag race. Return new delay */ +uint16_t +ao_lco_drag_warn_check(uint16_t now, uint16_t delay); + +/* Request 'beeps' additional drag race beeps */ +void +ao_lco_drag_add_beeps(uint8_t beeps); + +/* task function for beeping while arm is active */ +void +ao_lco_arm_warn(void); + +/* + * Provided by the hw-specific driver code + */ + +void +ao_lco_set_pad(uint8_t pad); + +void +ao_lco_set_box(uint16_t box); + +void +ao_lco_set_voltage(uint16_t decivolts); + +void +ao_lco_set_display(void); + void ao_lco_init(void); +uint8_t +ao_lco_box_present(uint16_t box); + #endif /* _AO_LCO_H_ */ diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c new file mode 100644 index 00000000..b2124d1b --- /dev/null +++ b/src/drivers/ao_lco_bits.c @@ -0,0 +1,468 @@ +/* + * Copyright © 2018 Keith Packard + * + * 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, 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 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include + +uint8_t ao_lco_debug; + +uint8_t ao_lco_pad; +int16_t ao_lco_box; +uint8_t ao_lco_drag_race; + +uint8_t ao_lco_armed; /* arm active */ +uint8_t ao_lco_firing; /* fire active */ + +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]; + +struct ao_pad_query ao_pad_query; + +static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { +#ifdef AO_LED_CONTINUITY_0 + AO_LED_CONTINUITY_0, +#endif +#ifdef AO_LED_CONTINUITY_1 + AO_LED_CONTINUITY_1, +#endif +#ifdef AO_LED_CONTINUITY_2 + AO_LED_CONTINUITY_2, +#endif +#ifdef AO_LED_CONTINUITY_3 + AO_LED_CONTINUITY_3, +#endif +#ifdef AO_LED_CONTINUITY_4 + AO_LED_CONTINUITY_4, +#endif +#ifdef AO_LED_CONTINUITY_5 + AO_LED_CONTINUITY_5, +#endif +#ifdef AO_LED_CONTINUITY_6 + AO_LED_CONTINUITY_6, +#endif +#ifdef AO_LED_CONTINUITY_7 + AO_LED_CONTINUITY_7, +#endif +}; + +/* Set LEDs to match remote box status */ +void +ao_lco_igniter_status(void) +{ + uint8_t c; + uint8_t t = 0; + + for (;;) { + if (ao_lco_drag_race) + ao_sleep_for(&ao_pad_query, AO_MS_TO_TICKS(50)); + else + ao_sleep(&ao_pad_query); + 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); + ao_led_off(AO_LED_GREEN|AO_LED_AMBER); + continue; + } + if (ao_radio_cmac_rssi < -90) { + ao_led_on(AO_LED_AMBER); + ao_led_off(AO_LED_RED|AO_LED_GREEN); + } else { + ao_led_on(AO_LED_GREEN); + ao_led_off(AO_LED_RED|AO_LED_AMBER); + } + if (ao_pad_query.arm_status) + 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 (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) { + if (t) + on = 1; + } else { + if (t == 1) + on = 1; + } + if (on) + ao_led_on(continuity_led[c]); + else + ao_led_off(continuity_led[c]); + } else { + if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) + ao_led_on(continuity_led[c]); + else + ao_led_off(continuity_led[c]); + } + } + t = (t + 1) & 3; + } +} + +uint8_t +ao_lco_pad_present(uint8_t box, uint8_t pad) +{ + /* voltage measurement is always valid */ + if (pad == AO_LCO_PAD_VOLTAGE) + return 1; + if (!ao_lco_channels[box]) + return 0; + if (pad > AO_PAD_MAX_CHANNELS) + return 0; + return (ao_lco_channels[box] >> (pad - 1)) & 1; +} + +uint8_t +ao_lco_pad_first(uint8_t box) +{ + uint8_t pad; + + for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++) + if (ao_lco_pad_present(box, pad)) + return pad; + return 0; +} + +static uint8_t +ao_lco_get_channels(uint8_t box, struct ao_pad_query *query) +{ + int8_t r; + + r = ao_lco_query(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; + 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]; +} + +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) & 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 == AO_LCO_PAD_VOLTAGE) + ao_lco_set_display(); + } +} + +uint8_t ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)]; + +static void +ao_lco_box_reset_present(void) +{ + ao_lco_min_box = 0xff; + ao_lco_max_box = 0x00; + memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask)); +} + +static void +ao_lco_box_set_present(uint8_t box) +{ + if (box < ao_lco_min_box) + ao_lco_min_box = box; + if (box > ao_lco_max_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); +} + +void +ao_lco_step_pad(int8_t dir) +{ + int8_t new_pad; + + 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) + 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(); + } +} + +void +ao_lco_set_armed(uint8_t armed) +{ + ao_lco_armed = armed; + 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]) + break; + if (box > ao_lco_max_box) + ao_lco_armed = 0; + } else { + 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)); + else + ao_lco_armed = 0; + } + } + ao_wakeup(&ao_lco_armed); +} + +void +ao_lco_set_firing(uint8_t firing) +{ + ao_lco_firing = firing; + PRINTD("Firing %d\n", ao_lco_firing); + ao_wakeup(&ao_lco_armed); +} + +void +ao_lco_toggle_drag(void) +{ + 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); + } +} + +void +ao_lco_search(void) +{ + int8_t r; + int8_t try; + uint8_t box; + uint8_t boxes = 0; + + ao_lco_box_reset_present(); + ao_lco_set_pad(0); + for (box = 0; box < AO_PAD_MAX_BOXES; box++) { + if ((box % 10) == 0) + ao_lco_set_box(box); + 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]); + PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]); + if (r == AO_RADIO_CMAC_OK) { + ++boxes; + ao_lco_box_set_present(box); + ao_lco_set_pad(boxes % 10); + ao_delay(AO_MS_TO_TICKS(30)); + break; + } + } + } + if (ao_lco_min_box <= ao_lco_max_box) + ao_lco_box = ao_lco_min_box; + else + 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(); +} + +void +ao_lco_monitor(void) +{ + uint16_t delay; + uint8_t box; + + for (;;) { + PRINTD("monitor armed %d firing %d\n", + ao_lco_armed, ao_lco_firing); + + if (ao_lco_armed && ao_lco_firing) { + ao_lco_ignite(AO_PAD_FIRE); + } 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_VALID_EVER) { + ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]); + ao_delay(AO_MS_TO_TICKS(10)); + } + } + } + } + } + if (ao_lco_armed && ao_lco_firing) + delay = AO_MS_TO_TICKS(100); + else + delay = AO_SEC_TO_TICKS(1); + ao_sleep_for(&ao_lco_armed, delay); + } +} + +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; + +#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) +{ + PRINTD("beep %d\n", beeps); + if (ao_lco_drag_beep_count == 0) + ao_lco_drag_beep_time = ao_time(); + ao_lco_drag_beep_count += beeps; + ao_wakeup(&ao_lco_drag_beep_count); +} + +/* 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) +{ + 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_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 = now + AO_LCO_DRAG_BEEP_TIME; + } + } else { + ao_beep(AO_BEEP_HIGH); + PRINTD("beep start\n"); + ao_lco_drag_beep_on = 1; + ao_lco_drag_beep_time = now + AO_LCO_DRAG_BEEP_TIME; + } + } + } + + if (ao_lco_drag_beep_count) { + uint16_t beep_delay = 0; + + if (ao_lco_drag_beep_time > now) + beep_delay = ao_lco_drag_beep_time - now; + + if (delay > beep_delay) + delay = beep_delay; + } + return delay; +} + +void +ao_lco_drag_enable(void) +{ + if (!ao_lco_drag_race) { + PRINTD("Drag enable\n"); + ao_lco_drag_race = 1; + memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); +#ifdef AO_LED_DRAG + ao_led_on(AO_LED_DRAG); +#endif + ao_lco_drag_add_beeps(5); + ao_lco_set_display(); + } +} + +void +ao_lco_drag_disable(void) +{ + if (ao_lco_drag_race) { + PRINTD("Drag disable\n"); + ao_lco_drag_race = 0; +#ifdef AO_LED_DRAG + ao_led_off(AO_LED_DRAG); +#endif + memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); + ao_lco_drag_add_beeps(2); + ao_lco_set_display(); + } +} + +/* add a beep if it's time to warn the user that drag race mode is + * active + */ + +uint16_t +ao_lco_drag_warn_check(uint16_t now, uint16_t delay) +{ + if (ao_lco_drag_race) { + uint16_t warn_delay; + + if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) { + ao_lco_drag_add_beeps(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; +} + +/* task function for beeping while arm is active */ +void +ao_lco_arm_warn(void) +{ + for (;;) { + while (!ao_lco_armed) { +#ifdef AO_LED_FIRE + ao_led_off(AO_LED_FIRE); +#endif + ao_sleep(&ao_lco_armed); + } +#ifdef AO_LED_FIRE + ao_led_on(AO_LED_FIRE); +#endif + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_delay(AO_MS_TO_TICKS(200)); + } +} diff --git a/src/telelco-v0.2-cc1200/Makefile b/src/telelco-v0.2-cc1200/Makefile index f29e2930..4ccf494c 100644 --- a/src/telelco-v0.2-cc1200/Makefile +++ b/src/telelco-v0.2-cc1200/Makefile @@ -67,6 +67,7 @@ ALTOS_SRC = \ ao_button.c \ ao_event.c \ ao_lco.c \ + ao_lco_bits.c \ ao_lco_cmd.c \ ao_lco_func.c \ ao_radio_cmac_cmd.c diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 8c1ced6c..8279cac1 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -64,6 +64,7 @@ ALTOS_SRC = \ ao_button.c \ ao_event.c \ ao_lco.c \ + ao_lco_bits.c \ ao_lco_cmd.c \ ao_lco_func.c \ ao_radio_cmac_cmd.c diff --git a/src/telelco-v0.3/Makefile b/src/telelco-v0.3/Makefile index 0bb0f9dc..c2592bf8 100644 --- a/src/telelco-v0.3/Makefile +++ b/src/telelco-v0.3/Makefile @@ -65,6 +65,7 @@ ALTOS_SRC = \ ao_button.c \ ao_event.c \ ao_lco.c \ + ao_lco_bits.c \ ao_lco_cmd.c \ ao_lco_func.c \ ao_radio_cmac_cmd.c diff --git a/src/telelco-v2.0/Makefile b/src/telelco-v2.0/Makefile index 4871993d..43295fd3 100644 --- a/src/telelco-v2.0/Makefile +++ b/src/telelco-v2.0/Makefile @@ -66,6 +66,7 @@ ALTOS_SRC = \ ao_quadrature.c \ ao_button.c \ ao_event.c \ + ao_lco_bits.c \ ao_lco_v2.c \ ao_lco_cmd.c \ ao_lco_func.c \ diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 21b2c54d..9fefde3b 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -21,19 +21,9 @@ #include #include #include -#include #include #include -#define DEBUG 1 - -#if DEBUG -static uint8_t ao_lco_debug; -#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) -#else -#define PRINTD(...) -#endif - #define AO_LCO_PAD_DIGIT 0 #define AO_LCO_BOX_DIGIT_1 1 #define AO_LCO_BOX_DIGIT_10 2 @@ -41,30 +31,14 @@ static uint8_t ao_lco_debug; #define AO_LCO_DRAG_RACE_START_TIME AO_SEC_TO_TICKS(5) #define AO_LCO_DRAG_RACE_STOP_TIME AO_SEC_TO_TICKS(2) -#define AO_LCO_VALID_LAST 1 -#define AO_LCO_VALID_EVER 2 - -static uint8_t ao_lco_min_box, ao_lco_max_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_drag_race; -static uint8_t ao_lco_pad; -static int16_t ao_lco_box; static uint8_t ao_lco_select_mode; #define AO_LCO_SELECT_PAD 0 #define AO_LCO_SELECT_BOX 1 -static struct ao_pad_query ao_pad_query; - static uint8_t ao_lco_display_mutex; -static void +void ao_lco_set_pad(uint8_t pad) { ao_mutex_get(&ao_lco_display_mutex); @@ -89,7 +63,7 @@ ao_lco_set_pad(uint8_t pad) (0 << 5) | \ (0 << 6)) -static void +void ao_lco_set_box(uint16_t box) { ao_mutex_get(&ao_lco_display_mutex); @@ -98,7 +72,7 @@ ao_lco_set_box(uint16_t box) ao_mutex_put(&ao_lco_display_mutex); } -static void +void ao_lco_set_voltage(uint16_t decivolts) { uint8_t tens, ones, tenths; @@ -114,7 +88,7 @@ ao_lco_set_voltage(uint16_t decivolts) ao_mutex_put(&ao_lco_display_mutex); } -static void +void ao_lco_set_display(void) { if (ao_lco_pad == 0) { @@ -125,42 +99,12 @@ ao_lco_set_display(void) } } -#define MASK_SIZE(n) (((n) + 7) >> 3) -#define MASK_ID(n) ((n) >> 3) -#define MASK_SHIFT(n) ((n) & 7) - -static uint8_t ao_lco_box_mask[MASK_SIZE(AO_PAD_MAX_BOXES)]; - -static uint8_t +uint8_t ao_lco_box_present(uint16_t box) { if (box >= AO_PAD_MAX_BOXES) return 0; - return (ao_lco_box_mask[MASK_ID(box)] >> MASK_SHIFT(box)) & 1; -} - -static uint8_t -ao_lco_pad_present(uint8_t box, uint8_t pad) -{ - /* 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_lco_channels[box] >> (pad - 1)) & 1; -} - -static uint8_t -ao_lco_pad_first(uint8_t box) -{ - uint8_t pad; - - for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++) - if (ao_lco_pad_present(box, pad)) - return pad; - return 0; + return (ao_lco_box_mask[AO_LCO_MASK_ID(box)] >> AO_LCO_MASK_SHIFT(box)) & 1; } static void @@ -185,114 +129,29 @@ ao_lco_set_select(void) } } -static struct ao_task ao_lco_drag_task; -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; - -#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 */ -static void -ao_lco_drag_add_beeps(uint8_t beeps) -{ - PRINTD("beep %d\n", beeps); - if (ao_lco_drag_beep_count == 0) - ao_lco_drag_beep_time = ao_time(); - ao_lco_drag_beep_count += beeps; - ao_wakeup(&ao_lco_drag_beep_count); -} - -/* 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 - */ - -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_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 = now + AO_LCO_DRAG_BEEP_TIME; - } - } else { - ao_beep(AO_BEEP_HIGH); - PRINTD("beep start\n"); - ao_lco_drag_beep_on = 1; - ao_lco_drag_beep_time = now + AO_LCO_DRAG_BEEP_TIME; - } - } - } - - if (ao_lco_drag_beep_count) { - uint16_t beep_delay = 0; - - if (ao_lco_drag_beep_time > now) - beep_delay = ao_lco_drag_beep_time - now; - - if (delay > beep_delay) - delay = beep_delay; - } - return delay; -} - static void -ao_lco_drag_enable(void) +ao_lco_step_box(int8_t dir) { - if (!ao_lco_drag_race) { - PRINTD("Drag enable\n"); - ao_lco_drag_race = 1; - memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); - ao_led_on(AO_LED_DRAG); - ao_lco_drag_add_beeps(5); - ao_lco_set_display(); - } -} - -static void -ao_lco_drag_disable(void) -{ - if (ao_lco_drag_race) { - PRINTD("Drag disable\n"); - ao_lco_drag_race = 0; - ao_led_off(AO_LED_DRAG); - memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); - ao_lco_drag_add_beeps(2); + int16_t new_box = ao_lco_box; + + do { + new_box += dir; + if (new_box > ao_lco_max_box) + new_box = ao_lco_min_box; + else if (new_box < ao_lco_min_box) + new_box = ao_lco_max_box; + if (new_box == ao_lco_box) + break; + } while (!ao_lco_box_present(new_box)); + if (ao_lco_box != new_box) { + ao_lco_box = new_box; + ao_lco_pad = 1; + ao_lco_channels[ao_lco_box] = 0; ao_lco_set_display(); } } -/* add a beep if it's time to warn the user that drag race mode is - * active - */ - -static uint16_t -ao_lco_drag_warn_check(uint16_t now, uint16_t delay) -{ - if (ao_lco_drag_race) { - uint16_t warn_delay; - - if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) { - ao_lco_drag_add_beeps(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 struct ao_task ao_lco_drag_task; static void ao_lco_drag_monitor(void) @@ -300,6 +159,7 @@ ao_lco_drag_monitor(void) uint16_t delay = ~0; uint16_t now; + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { PRINTD("Drag monitor count %d delay %d\n", ao_lco_drag_beep_count, delay); if (delay == (uint16_t) ~0) @@ -318,10 +178,7 @@ static void ao_lco_input(void) { static struct ao_event event; - int8_t dir, new_pad; - int16_t new_box; - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { ao_event_get(&event); PRINTD("event type %d unit %d value %d\n", @@ -333,40 +190,10 @@ ao_lco_input(void) if (!ao_lco_armed) { switch (ao_lco_select_mode) { case AO_LCO_SELECT_PAD: - dir = (int8_t) event.value; - new_pad = ao_lco_pad; - do { - new_pad += dir; - if (new_pad > AO_PAD_MAX_CHANNELS) - new_pad = 0; - if (new_pad < 0) - new_pad = AO_PAD_MAX_CHANNELS; - if (new_pad == ao_lco_pad) - 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(); - } + ao_lco_step_pad((int8_t) event.value); break; case AO_LCO_SELECT_BOX: - dir = (int8_t) event.value; - new_box = ao_lco_box; - do { - new_box += dir; - if (new_box > ao_lco_max_box) - new_box = ao_lco_min_box; - else if (new_box < ao_lco_min_box) - new_box = ao_lco_max_box; - if (new_box == ao_lco_box) - break; - } while (!ao_lco_box_present(new_box)); - if (ao_lco_box != new_box) { - ao_lco_box = new_box; - ao_lco_pad = 1; - ao_lco_channels[ao_lco_box] = 0; - ao_lco_set_display(); - } + ao_lco_step_box((int8_t) event.value); break; default: break; @@ -378,34 +205,12 @@ ao_lco_input(void) case AO_EVENT_BUTTON: switch (event.unit) { 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]) - break; - if (box > ao_lco_max_box) - ao_lco_armed = 0; - } else { - 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)); - else - ao_lco_armed = 0; - } - } + ao_lco_set_armed(event.value); ao_lco_set_select(); - ao_wakeup(&ao_lco_armed); break; case AO_BUTTON_FIRE: - if (ao_lco_armed) { - ao_lco_firing = event.value; - PRINTD("Firing %d\n", ao_lco_firing); - ao_wakeup(&ao_lco_armed); - } + if (ao_lco_armed) + ao_lco_set_firing(event.value); break; case AO_BUTTON_DRAG_SELECT: if (event.value && ao_lco_drag_race) { @@ -437,193 +242,6 @@ ao_lco_input(void) } } -static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { -#ifdef AO_LED_CONTINUITY_0 - AO_LED_CONTINUITY_0, -#endif -#ifdef AO_LED_CONTINUITY_1 - AO_LED_CONTINUITY_1, -#endif -#ifdef AO_LED_CONTINUITY_2 - AO_LED_CONTINUITY_2, -#endif -#ifdef AO_LED_CONTINUITY_3 - AO_LED_CONTINUITY_3, -#endif -#ifdef AO_LED_CONTINUITY_4 - AO_LED_CONTINUITY_4, -#endif -#ifdef AO_LED_CONTINUITY_5 - AO_LED_CONTINUITY_5, -#endif -#ifdef AO_LED_CONTINUITY_6 - AO_LED_CONTINUITY_6, -#endif -#ifdef AO_LED_CONTINUITY_7 - AO_LED_CONTINUITY_7, -#endif -}; - -static uint8_t -ao_lco_get_channels(uint8_t box, struct ao_pad_query *query) -{ - int8_t r; - - r = ao_lco_query(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; - 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]; -} - -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) & AO_LCO_VALID_LAST) { - if (!(previous_valid & AO_LCO_VALID_EVER)) { - if (ao_lco_pad != 0) - ao_lco_pad = ao_lco_pad_first(ao_lco_box); - ao_lco_set_display(); - } - if (ao_lco_pad == 0) - ao_lco_set_display(); - } -} - -static void -ao_lco_box_reset_present(void) -{ - ao_lco_min_box = 0xff; - ao_lco_max_box = 0x00; - memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask)); -} - -static void -ao_lco_box_set_present(uint8_t box) -{ - if (box < ao_lco_min_box) - ao_lco_min_box = box; - if (box > ao_lco_max_box) - ao_lco_max_box = box; - if (box >= AO_PAD_MAX_BOXES) - return; - ao_lco_box_mask[MASK_ID(box)] |= 1 << MASK_SHIFT(box); -} - -static void -ao_lco_search(void) -{ - int8_t r; - int8_t try; - uint8_t box; - uint8_t boxes = 0; - - ao_lco_box_reset_present(); - ao_lco_set_pad(0); - for (box = 0; box < AO_PAD_MAX_BOXES; box++) { - if ((box % 10) == 0) - ao_lco_set_box(box); - 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]); - PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]); - if (r == AO_RADIO_CMAC_OK) { - ++boxes; - ao_lco_box_set_present(box); - ao_lco_set_pad(boxes % 10); - ao_delay(AO_MS_TO_TICKS(30)); - break; - } - } - } - if (ao_lco_min_box <= ao_lco_max_box) - ao_lco_box = ao_lco_min_box; - else - 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(); -} - -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[ao_lco_box]); - if (!(ao_lco_valid[ao_lco_box] & 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) { - ao_led_on(AO_LED_AMBER); - ao_led_off(AO_LED_RED|AO_LED_GREEN); - } else { - ao_led_on(AO_LED_GREEN); - ao_led_off(AO_LED_RED|AO_LED_AMBER); - } - if (ao_pad_query.arm_status) - 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 (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) { - if (t) - on = 1; - } else { - if (t == 1) - on = 1; - } - if (on) - ao_led_on(continuity_led[c]); - else - ao_led_off(continuity_led[c]); - } else { - if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) - ao_led_on(continuity_led[c]); - else - ao_led_off(continuity_led[c]); - } - } - t = (t + 1) & 3; - } -} - -static void -ao_lco_arm_warn(void) -{ - for (;;) { - while (!ao_lco_armed) { - ao_led_off(AO_LED_FIRE); - ao_sleep(&ao_lco_armed); - } - ao_led_on(AO_LED_FIRE); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - ao_delay(AO_MS_TO_TICKS(200)); - } -} - /* * Light up everything for a second at power on to let the user * visually inspect the system for correct operation @@ -659,11 +277,8 @@ static struct ao_task ao_lco_arm_warn_task; static struct ao_task ao_lco_igniter_status_task; static void -ao_lco_monitor(void) +ao_lco_main(void) { - uint16_t delay; - uint8_t box; - ao_lco_display_test(); ao_lco_batt_voltage(); ao_lco_search(); @@ -671,33 +286,7 @@ ao_lco_monitor(void) 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\n", - ao_lco_armed, ao_lco_firing); - - if (ao_lco_armed && ao_lco_firing) { - ao_lco_ignite(AO_PAD_FIRE); - } 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_VALID_EVER) { - ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]); - ao_delay(AO_MS_TO_TICKS(10)); - } - } - } - } - } - if (ao_lco_armed && ao_lco_firing) - delay = AO_MS_TO_TICKS(100); - else - delay = AO_SEC_TO_TICKS(1); - ao_sleep_for(&ao_lco_armed, delay); - } + ao_lco_monitor(); } #if DEBUG @@ -719,7 +308,7 @@ __code struct ao_cmds ao_lco_cmds[] = { void ao_lco_init(void) { - ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); + ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor"); #if DEBUG ao_cmd_register(&ao_lco_cmds[0]); #endif -- cgit v1.2.3 From 81355cd08a22502d47637f2505b6089d226d0889 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2018 01:06:09 -0700 Subject: altos: A bit more LCO code sharing Missed drag race pad toggling in ao_lco_v2.c Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 2 +- src/telelco-v2.0/ao_lco_v2.c | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 6b270042..f73fb43f 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -102,7 +102,7 @@ ao_lco_set_voltage(uint16_t decivolts) void ao_lco_set_display(void) { - if (ao_lco_pad == 0 && ao_lco_box != AO_LCO_BOX_DRAG) { + if (ao_lco_pad == AO_LCO_PAD_VOLTAGE && ao_lco_box != AO_LCO_BOX_DRAG) { ao_lco_set_voltage(ao_pad_query.battery); } else { if (ao_lco_box == AO_LCO_BOX_DRAG) diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 9fefde3b..d5d3d5e4 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -91,7 +91,7 @@ ao_lco_set_voltage(uint16_t decivolts) void ao_lco_set_display(void) { - if (ao_lco_pad == 0) { + if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) { ao_lco_set_voltage(ao_pad_query.battery); } else { ao_lco_set_pad(ao_lco_pad); @@ -213,14 +213,8 @@ ao_lco_input(void) ao_lco_set_firing(event.value); break; case AO_BUTTON_DRAG_SELECT: - if (event.value && 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_add_beeps(ao_lco_pad); - } - } + if (event.value) + ao_lco_toggle_drag(); break; case AO_BUTTON_DRAG_MODE: if (event.value) -- cgit v1.2.3 From 3b53a69e47816ee987a409b05a6b0b47891ca816 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Jul 2018 11:18:12 -0700 Subject: altos: Fix telelcotwo build for new ao_lco_bits.c file Lots of code motion; shouldn't have any functional changes. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 28 ++---- src/drivers/ao_lco.h | 22 +++- src/drivers/ao_lco_bits.c | 65 ++++++++---- src/drivers/ao_lco_two.c | 226 +++--------------------------------------- src/telelco-v2.0/ao_lco_v2.c | 23 ++--- src/telelcotwo-v0.1/Makefile | 1 + src/telelcotwo-v0.1/ao_pins.h | 2 + 7 files changed, 96 insertions(+), 271 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index f73fb43f..2c8c729f 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -41,12 +41,10 @@ static uint16_t ao_lco_fire_tick; static uint8_t ao_lco_fire_down; -#define AO_LCO_BOX_DRAG 0x1000 - static uint8_t ao_lco_display_mutex; void -ao_lco_set_pad(uint8_t pad) +ao_lco_show_pad(uint8_t pad) { ao_mutex_get(&ao_lco_display_mutex); ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad | (ao_lco_drag_race << 4)); @@ -71,7 +69,7 @@ ao_lco_set_pad(uint8_t pad) (0 << 6)) void -ao_lco_set_box(uint16_t box) +ao_lco_show_box(uint16_t box) { ao_mutex_get(&ao_lco_display_mutex); if (box == AO_LCO_BOX_DRAG) { @@ -85,7 +83,7 @@ ao_lco_set_box(uint16_t box) } void -ao_lco_set_voltage(uint16_t decivolts) +ao_lco_show_voltage(uint16_t decivolts) { uint8_t tens, ones, tenths; @@ -100,16 +98,16 @@ ao_lco_set_voltage(uint16_t decivolts) } void -ao_lco_set_display(void) +ao_lco_show_display(void) { if (ao_lco_pad == AO_LCO_PAD_VOLTAGE && ao_lco_box != AO_LCO_BOX_DRAG) { - ao_lco_set_voltage(ao_pad_query.battery); + ao_lco_show_voltage(ao_pad_query.battery); } else { if (ao_lco_box == AO_LCO_BOX_DRAG) - ao_lco_set_pad(ao_lco_drag_race); + ao_lco_show_pad(ao_lco_drag_race); else - ao_lco_set_pad(ao_lco_pad); - ao_lco_set_box(ao_lco_box); + ao_lco_show_pad(ao_lco_pad); + ao_lco_show_box(ao_lco_box); } } @@ -210,13 +208,7 @@ ao_lco_step_box(int8_t dir) if (new_box == ao_lco_box) break; } while (!ao_lco_box_present(new_box)); - if (ao_lco_box != new_box) { - ao_lco_box = new_box; - ao_lco_pad = 1; - if (ao_lco_box != AO_LCO_BOX_DRAG) - ao_lco_channels[ao_lco_box] = 0; - ao_lco_set_display(); - } + ao_lco_set_box(new_box); } static void @@ -299,7 +291,7 @@ ao_lco_batt_voltage(void) ao_adc_single_get(&packet); decivolt = ao_battery_decivolt(packet.v_batt); - ao_lco_set_voltage(decivolt); + ao_lco_show_voltage(decivolt); ao_delay(AO_MS_TO_TICKS(1000)); } #endif diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h index d5aace0d..c1b101d2 100644 --- a/src/drivers/ao_lco.h +++ b/src/drivers/ao_lco.h @@ -21,6 +21,14 @@ #include +#ifndef AO_LCO_DRAG +#define AO_LCO_DRAG 1 +#endif + +#if AO_LCO_DRAG +#define AO_LCO_BOX_DRAG 0x1000 +#endif + #define DEBUG 1 #if DEBUG @@ -72,9 +80,15 @@ ao_lco_pad_present(uint8_t box, uint8_t pad); uint8_t ao_lco_pad_first(uint8_t box); +void +ao_lco_set_pad(uint8_t new_pad); + void ao_lco_step_pad(int8_t dir); +void +ao_lco_set_box(uint16_t new_box); + void ao_lco_set_armed(uint8_t armed); @@ -121,16 +135,16 @@ ao_lco_arm_warn(void); */ void -ao_lco_set_pad(uint8_t pad); +ao_lco_show_pad(uint8_t pad); void -ao_lco_set_box(uint16_t box); +ao_lco_show_box(uint16_t box); void -ao_lco_set_voltage(uint16_t decivolts); +ao_lco_show_voltage(uint16_t decivolts); void -ao_lco_set_display(void); +ao_lco_show_display(void); void ao_lco_init(void); diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c index b2124d1b..9492cf59 100644 --- a/src/drivers/ao_lco_bits.c +++ b/src/drivers/ao_lco_bits.c @@ -170,11 +170,10 @@ ao_lco_update(void) 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(); + ao_lco_set_pad(ao_lco_pad_first(ao_lco_box)); } if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) - ao_lco_set_display(); + ao_lco_show_display(); } } @@ -200,6 +199,28 @@ ao_lco_box_set_present(uint8_t box) ao_lco_box_mask[AO_LCO_MASK_ID(box)] |= 1 << AO_LCO_MASK_SHIFT(box); } +void +ao_lco_set_pad(uint8_t new_pad) +{ + if (new_pad != ao_lco_pad) { + ao_lco_pad = new_pad; + ao_lco_show_display(); + } +} + +void +ao_lco_set_box(uint16_t new_box) +{ + if (ao_lco_box != new_box) { + ao_lco_box = new_box; +#if AO_LCO_DRAG + if (ao_lco_box != AO_LCO_BOX_DRAG) +#endif + ao_lco_channels[ao_lco_box] = 0; + ao_lco_set_pad(1); + } +} + void ao_lco_step_pad(int8_t dir) { @@ -215,10 +236,7 @@ ao_lco_step_pad(int8_t dir) if (new_pad == ao_lco_pad) 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(); - } + ao_lco_set_pad(new_pad); } void @@ -254,17 +272,6 @@ ao_lco_set_firing(uint8_t firing) ao_wakeup(&ao_lco_armed); } -void -ao_lco_toggle_drag(void) -{ - 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); - } -} - void ao_lco_search(void) { @@ -297,8 +304,7 @@ 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(); + ao_lco_set_pad(1); } void @@ -336,6 +342,8 @@ ao_lco_monitor(void) } } +#if AO_LCO_DRAG + uint8_t ao_lco_drag_beep_count; static uint8_t ao_lco_drag_beep_on; static uint16_t ao_lco_drag_beep_time; @@ -355,6 +363,18 @@ 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 != 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); + } +} + /* 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 */ @@ -408,7 +428,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_display(); } } @@ -423,7 +443,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_display(); } } @@ -447,6 +467,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 diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c index e2f86745..2fa0a21f 100644 --- a/src/drivers/ao_lco_two.c +++ b/src/drivers/ao_lco_two.c @@ -23,64 +23,13 @@ #include #include -#define DEBUG 1 - -#if DEBUG -static uint8_t ao_lco_debug; -#define DEBUG_EVENT 1 -#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,...) -#endif - -#define AO_LCO_VALID_LAST 1 -#define AO_LCO_VALID_EVER 2 - 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; - -/* UI values */ -static uint8_t ao_lco_armed; -static uint8_t ao_lco_firing; -static uint8_t ao_lco_box; - -static struct ao_pad_query ao_pad_query; - -/* 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 armed) -{ - uint8_t bit = (1 << ao_lco_pad); - - if (armed) { - ao_lco_armed = bit; - } else { - ao_lco_armed = 0; - } - 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"); + PRINTD("suspend\n"); ao_lco_suspended = 1; ao_lco_armed = 0; ao_wakeup(&ao_pad_query); @@ -96,6 +45,11 @@ ao_lco_wakeup(void) } } +void +ao_lco_show_display(void) +{ +} + static void ao_lco_input(void) { @@ -113,23 +67,21 @@ ao_lco_input(void) ao_event_get(&event); } ao_lco_wakeup(); - PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n", + PRINTD("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_BOX: ao_lco_set_box(event.value); + ao_lco_set_armed(0); break; case AO_BUTTON_ARM: ao_lco_set_armed(event.value); break; 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); - } + if (ao_lco_armed) + ao_lco_set_firing(event.value); break; } break; @@ -137,140 +89,14 @@ ao_lco_input(void) } } -static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { -#ifdef AO_LED_CONTINUITY_0 - AO_LED_CONTINUITY_0, -#endif -#ifdef AO_LED_CONTINUITY_1 - AO_LED_CONTINUITY_1, -#endif -#ifdef AO_LED_CONTINUITY_2 - AO_LED_CONTINUITY_2, -#endif -#ifdef AO_LED_CONTINUITY_3 - AO_LED_CONTINUITY_3, -#endif -#ifdef AO_LED_CONTINUITY_4 - AO_LED_CONTINUITY_4, -#endif -#ifdef AO_LED_CONTINUITY_5 - AO_LED_CONTINUITY_5, -#endif -#ifdef AO_LED_CONTINUITY_6 - AO_LED_CONTINUITY_6, -#endif -#ifdef AO_LED_CONTINUITY_7 - AO_LED_CONTINUITY_7, -#endif -}; - -static uint8_t -ao_lco_get_channels(void) -{ - int8_t r; - - r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); - if (r == AO_RADIO_CMAC_OK) { - ao_lco_channels = ao_pad_query.channels; - ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER; - } else - ao_lco_valid &= ~AO_LCO_VALID_LAST; - PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset); - ao_wakeup(&ao_pad_query); - return ao_lco_valid; -} - -static void -ao_lco_igniter_status(void) -{ - uint8_t c; - uint8_t t = 0; - - for (;;) { - uint8_t all_status; - 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 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); - 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 { - ao_led_on(AO_LED_GREEN); - ao_led_off(AO_LED_RED|AO_LED_AMBER); - } - if (ao_pad_query.arm_status) - ao_led_on(AO_LED_REMOTE_ARM); - 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 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]); - } - t = 1-t; - } -} - -static void -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++) { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); - ao_delay(AO_MS_TO_TICKS(100)); - } - ao_delay(AO_MS_TO_TICKS(300)); - } -} - static struct ao_task ao_lco_input_task; static struct ao_task ao_lco_monitor_task; static struct ao_task ao_lco_arm_warn_task; static struct ao_task ao_lco_igniter_status_task; static void -ao_lco_monitor(void) +ao_lco_main(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"); @@ -279,33 +105,7 @@ ao_lco_monitor(void) 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_PAD_FIRE); - } else { - ao_lco_get_channels(); - if (ao_lco_armed) { - 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 { - delay = AO_SEC_TO_TICKS(1); - } - ao_sleep_for(&ao_lco_armed, delay); - } + ao_lco_monitor(); } #if DEBUG @@ -326,7 +126,7 @@ __code struct ao_cmds ao_lco_cmds[] = { void ao_lco_init(void) { - ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); + ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor"); #if DEBUG ao_cmd_register(&ao_lco_cmds[0]); #endif diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index d5d3d5e4..f64a7745 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -39,7 +39,7 @@ static uint8_t ao_lco_select_mode; static uint8_t ao_lco_display_mutex; void -ao_lco_set_pad(uint8_t pad) +ao_lco_show_pad(uint8_t pad) { ao_mutex_get(&ao_lco_display_mutex); ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad | (ao_lco_drag_race << 4)); @@ -64,7 +64,7 @@ ao_lco_set_pad(uint8_t pad) (0 << 6)) void -ao_lco_set_box(uint16_t box) +ao_lco_show_box(uint16_t box) { ao_mutex_get(&ao_lco_display_mutex); ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10 | (ao_lco_drag_race << 4)); @@ -73,7 +73,7 @@ ao_lco_set_box(uint16_t box) } void -ao_lco_set_voltage(uint16_t decivolts) +ao_lco_show_voltage(uint16_t decivolts) { uint8_t tens, ones, tenths; @@ -89,13 +89,13 @@ ao_lco_set_voltage(uint16_t decivolts) } void -ao_lco_set_display(void) +ao_lco_show_display(void) { if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) { - ao_lco_set_voltage(ao_pad_query.battery); + ao_lco_show_voltage(ao_pad_query.battery); } else { - ao_lco_set_pad(ao_lco_pad); - ao_lco_set_box(ao_lco_box); + ao_lco_show_pad(ao_lco_pad); + ao_lco_show_box(ao_lco_box); } } @@ -143,12 +143,7 @@ ao_lco_step_box(int8_t dir) if (new_box == ao_lco_box) break; } while (!ao_lco_box_present(new_box)); - if (ao_lco_box != new_box) { - ao_lco_box = new_box; - ao_lco_pad = 1; - ao_lco_channels[ao_lco_box] = 0; - ao_lco_set_display(); - } + ao_lco_set_box(new_box); } static struct ao_task ao_lco_drag_task; @@ -261,7 +256,7 @@ ao_lco_batt_voltage(void) ao_adc_single_get(&packet); decivolt = ao_battery_decivolt(packet.v_batt); - ao_lco_set_voltage(decivolt); + ao_lco_show_voltage(decivolt); ao_delay(AO_MS_TO_TICKS(1000)); } diff --git a/src/telelcotwo-v0.1/Makefile b/src/telelcotwo-v0.1/Makefile index 42188bb2..c68f3eb5 100644 --- a/src/telelcotwo-v0.1/Makefile +++ b/src/telelcotwo-v0.1/Makefile @@ -58,6 +58,7 @@ ALTOS_SRC = \ ao_button.c \ ao_event.c \ ao_lco_two.c \ + ao_lco_bits.c \ ao_lco_func.c \ ao_lco_cmd.c \ ao_radio_cmac_cmd.c diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h index 60e94c67..1941e03d 100644 --- a/src/telelcotwo-v0.1/ao_pins.h +++ b/src/telelcotwo-v0.1/ao_pins.h @@ -141,6 +141,8 @@ AO_LED_CONTINUITY_0 | \ AO_LED_REMOTE_ARM) +#define AO_LCO_DRAG 0 + /* * Use event queue for input devices */ -- cgit v1.2.3 From 38fb80e5e6af87f8c734448e4aa69b2c39854903 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Jul 2018 11:58:40 -0700 Subject: altos: Make LCO search directly drive pad/box displays Don't use ao_lco_show as that has other logic too. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 4 ++-- src/drivers/ao_lco.h | 5 +---- src/drivers/ao_lco_bits.c | 21 ++++++++++----------- src/drivers/ao_lco_two.c | 14 +++++++++++++- src/telelco-v2.0/ao_lco_v2.c | 4 ++-- 5 files changed, 28 insertions(+), 20 deletions(-) (limited to 'src/telelco-v2.0') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 2c8c729f..47752f1f 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -82,7 +82,7 @@ ao_lco_show_box(uint16_t box) ao_mutex_put(&ao_lco_display_mutex); } -void +static void ao_lco_show_voltage(uint16_t decivolts) { uint8_t tens, ones, tenths; @@ -98,7 +98,7 @@ ao_lco_show_voltage(uint16_t decivolts) } void -ao_lco_show_display(void) +ao_lco_show(void) { if (ao_lco_pad == AO_LCO_PAD_VOLTAGE && ao_lco_box != AO_LCO_BOX_DRAG) { ao_lco_show_voltage(ao_pad_query.battery); diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h index c1b101d2..e528c2ad 100644 --- a/src/drivers/ao_lco.h +++ b/src/drivers/ao_lco.h @@ -141,10 +141,7 @@ void ao_lco_show_box(uint16_t box); void -ao_lco_show_voltage(uint16_t decivolts); - -void -ao_lco_show_display(void); +ao_lco_show(void); void ao_lco_init(void); diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c index 6c5182f2..197bf8aa 100644 --- a/src/drivers/ao_lco_bits.c +++ b/src/drivers/ao_lco_bits.c @@ -173,7 +173,7 @@ ao_lco_update(void) ao_lco_set_pad(ao_lco_pad_first(ao_lco_box)); } if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) - ao_lco_show_display(); + ao_lco_show(); } } @@ -203,7 +203,7 @@ void ao_lco_set_pad(uint8_t new_pad) { ao_lco_pad = new_pad; - ao_lco_show_display(); + ao_lco_show(); } void @@ -215,7 +215,7 @@ ao_lco_set_box(uint16_t new_box) #endif ao_lco_channels[ao_lco_box] = 0; ao_lco_pad = 1; - ao_lco_show_display(); + ao_lco_show(); } void @@ -278,12 +278,11 @@ ao_lco_search(void) uint8_t boxes = 0; ao_lco_box_reset_present(); - ao_lco_set_pad(0); + ao_lco_show_box(0); + ao_lco_show_pad(0); for (box = 0; box < AO_PAD_MAX_BOXES; box++) { - if ((box % 10) == 0) { - ao_lco_box = box; - ao_lco_show_display(); - } + if ((box % 10) == 0) + ao_lco_show_box(box); 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]); @@ -291,7 +290,7 @@ ao_lco_search(void) if (r == AO_RADIO_CMAC_OK) { ++boxes; ao_lco_box_set_present(box); - ao_lco_set_pad(boxes % 10); + ao_lco_show_pad(boxes % 10); ao_delay(AO_MS_TO_TICKS(30)); break; } @@ -427,7 +426,7 @@ ao_lco_drag_enable(void) ao_led_on(AO_LED_DRAG); #endif ao_lco_drag_add_beeps(5); - ao_lco_show_display(); + ao_lco_show(); } } @@ -442,7 +441,7 @@ ao_lco_drag_disable(void) #endif memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); ao_lco_drag_add_beeps(2); - ao_lco_show_display(); + ao_lco_show(); } } diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c index 2fa0a21f..6f2d81ff 100644 --- a/src/drivers/ao_lco_two.c +++ b/src/drivers/ao_lco_two.c @@ -46,7 +46,19 @@ ao_lco_wakeup(void) } void -ao_lco_show_display(void) +ao_lco_show_pad(uint8_t pad) +{ + (void) pad; +} + +void +ao_lco_show_box(uint16_t box) +{ + (void) box; +} + +void +ao_lco_show(void) { } diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index f64a7745..a9933d59 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -72,7 +72,7 @@ ao_lco_show_box(uint16_t box) ao_mutex_put(&ao_lco_display_mutex); } -void +static void ao_lco_show_voltage(uint16_t decivolts) { uint8_t tens, ones, tenths; @@ -89,7 +89,7 @@ ao_lco_show_voltage(uint16_t decivolts) } void -ao_lco_show_display(void) +ao_lco_show(void) { if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) { ao_lco_show_voltage(ao_pad_query.battery); -- cgit v1.2.3