From 58eda1736d8cffa6e3b5afce6f5faabbb179045e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2018 17:34:23 -0600 Subject: altos/ao_cc1120: Only call ao_packet_slave_stop when HAS_SLAVE Don't try to disable packet slave mode when the product doesn't support packet slave mode. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index efe5f996..2f091485 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -1447,7 +1447,9 @@ ao_radio_test_recv(void) static void ao_radio_aprs(void) { +#if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif ao_aprs_send(); } #endif -- cgit v1.2.3 From e272f6a66881b6904037ee7b1afeb9a8a3ec5b2a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 May 2018 22:32:38 -0700 Subject: altos/drivers: Pads with multi-port firing and pad selector DIP switch TeleFire 8 scrambles GPIOs to make layout cleaner, placing the 8 firing outputs across two GPIO ports. We're also adding an 8-unit selector for box number so that boards can be re-configured in the field. These override any ROM-configuration value; you can select the rom value by setting all switches to 'off'. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 120 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 14 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 16b4ae60..b0ec2161 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -69,10 +70,20 @@ ao_strobe(uint8_t v) #endif } +#ifdef AO_PAD_PORT_0 +#define pins_pad(pad) (*((AO_PAD_ ## pad ## _PORT) == AO_PAD_PORT_0 ? (&pins0) : (&pins1))) +#else +#define pins_pad(pad) pins0 +#define AO_PAD_PORT_0 AO_PAD_PORT +#endif + static void ao_pad_run(void) { - AO_PORT_TYPE pins; + AO_PORT_TYPE pins0; +#ifdef AO_PAD_PORT_1 + AO_PORT_TYPE pins1; +#endif for (;;) { while (!ao_pad_ignite) @@ -80,32 +91,63 @@ ao_pad_run(void) /* * Actually set the pad bits */ - pins = 0; + pins0 = 0; +#ifdef AO_PAD_PORT_1 + pins1 = 0; +#endif #if AO_PAD_NUM > 0 if (ao_pad_ignite & (1 << 0)) - pins |= (1 << AO_PAD_PIN_0); + pins_pad(0) |= (1 << AO_PAD_PIN_0); #endif #if AO_PAD_NUM > 1 if (ao_pad_ignite & (1 << 1)) - pins |= (1 << AO_PAD_PIN_1); + pins_pad(1) |= (1 << AO_PAD_PIN_1); #endif #if AO_PAD_NUM > 2 if (ao_pad_ignite & (1 << 2)) - pins |= (1 << AO_PAD_PIN_2); + pins_pad(2) |= (1 << AO_PAD_PIN_2); #endif #if AO_PAD_NUM > 3 if (ao_pad_ignite & (1 << 3)) - pins |= (1 << AO_PAD_PIN_3); + pins_pad(3) |= (1 << AO_PAD_PIN_3); +#endif +#if AO_PAD_NUM > 4 + if (ao_pad_ignite & (1 << 4)) + pins_pad(4) |= (1 << AO_PAD_PIN_4); +#endif +#if AO_PAD_NUM > 5 + if (ao_pad_ignite & (1 << 5)) + pins_pad(5) |= (1 << AO_PAD_PIN_5); +#endif +#if AO_PAD_NUM > 6 + if (ao_pad_ignite & (1 << 6)) + pins_pad(6) |= (1 << AO_PAD_PIN_6); +#endif +#if AO_PAD_NUM > 7 + if (ao_pad_ignite & (1 << 7)) + pins_pad(7) |= (1 << AO_PAD_PIN_7); +#endif +#ifdef AO_PAD_PORT_1 + PRINTD("ignite pins 0x%x 0x%x\n", pins0, pins1); + ao_gpio_set_bits(AO_PAD_PORT_0, pins0); + ao_gpio_set_bits(AO_PAD_PORT_1, pins1); +#else + PRINTD("ignite pins 0x%x\n", pins0); + ao_gpio_set_bits(AO_PAD_PORT_0, pins0); #endif - PRINTD("ignite pins 0x%x\n", pins); - ao_gpio_set_bits(AO_PAD_PORT, pins); while (ao_pad_ignite) { ao_pad_ignite = 0; ao_delay(AO_PAD_FIRE_TIME); } - ao_gpio_clr_bits(AO_PAD_PORT, pins); - PRINTD("turn off pins 0x%x\n", pins); +#ifdef AO_PAD_PORT_1 + ao_gpio_clr_bits(AO_PAD_PORT_0, pins0); + ao_gpio_clr_bits(AO_PAD_PORT_1, pins1); + PRINTD("turn off pins 0x%x 0x%x\n", pins0, pins1); +#else + ao_gpio_set_bits(AO_PAD_PORT_0, pins0); + PRINTD("turn off pins 0x%x\n", pins0); +#endif } } @@ -284,6 +326,23 @@ ao_pad_read_box(void) } #endif +#ifdef AO_PAD_SELECTOR_PORT +static int ao_pad_read_box(void) { + AO_PORT_TYPE value = ao_gpio_get_all(AO_PAD_SELECTOR_PORT); + unsigned pin; + int select = 1; + + for (pin = 0; pin < sizeof (AO_PORT_TYPE) * 8; pin++) { + if (AO_PAD_SELECTOR_PINS & (1 << pin)) { + if ((value & (1 << pin)) == 0) + return select; + select++; + } + } + return ao_config.pad_box; +} +#else + #if HAS_FIXED_PAD_BOX #define ao_pad_read_box() ao_config.pad_box #endif @@ -292,6 +351,8 @@ ao_pad_read_box(void) #define ao_pad_read_box() PAD_BOX #endif +#endif + static void ao_pad(void) { @@ -497,20 +558,51 @@ __code struct ao_cmds ao_pad_cmds[] = { { 0, NULL } }; +#ifndef AO_PAD_PORT_1 +#define AO_PAD_0_PORT AO_PAD_PORT +#define AO_PAD_1_PORT AO_PAD_PORT +#define AO_PAD_2_PORT AO_PAD_PORT +#define AO_PAD_3_PORT AO_PAD_PORT +#define AO_PAD_4_PORT AO_PAD_PORT +#define AO_PAD_5_PORT AO_PAD_PORT +#define AO_PAD_6_PORT AO_PAD_PORT +#define AO_PAD_7_PORT AO_PAD_PORT +#endif + void ao_pad_init(void) { +#ifdef AO_PAD_SELECTOR_PORT + unsigned pin; + + for (pin = 0; pin < sizeof (AO_PORT_TYPE) * 8; pin++) { + if (AO_PAD_SELECTOR_PINS & (1 << pin)) + ao_enable_input(AO_PAD_SELECTOR_PORT, pin, AO_EXTI_MODE_PULL_UP); + } +#endif #if AO_PAD_NUM > 0 - ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0); + ao_enable_output(AO_PAD_0_PORT, AO_PAD_PIN_0, AO_PAD_0, 0); #endif #if AO_PAD_NUM > 1 - ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0); + ao_enable_output(AO_PAD_1_PORT, AO_PAD_PIN_1, AO_PAD_1, 0); #endif #if AO_PAD_NUM > 2 - ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0); + ao_enable_output(AO_PAD_2_PORT, AO_PAD_PIN_2, AO_PAD_2, 0); #endif #if AO_PAD_NUM > 3 - ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); + ao_enable_output(AO_PAD_3_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); +#endif +#if AO_PAD_NUM > 4 + ao_enable_output(AO_PAD_4_PORT, AO_PAD_PIN_4, AO_PAD_4, 0); +#endif +#if AO_PAD_NUM > 5 + ao_enable_output(AO_PAD_5_PORT, AO_PAD_PIN_5, AO_PAD_5, 0); +#endif +#if AO_PAD_NUM > 5 + ao_enable_output(AO_PAD_6_PORT, AO_PAD_PIN_6, AO_PAD_6, 0); +#endif +#if AO_PAD_NUM > 7 + ao_enable_output(AO_PAD_7_PORT, AO_PAD_PIN_7, AO_PAD_7, 0); #endif #ifdef AO_STROBE ao_enable_output(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, 0); -- cgit v1.2.3 From 863a9d523b26a8a5f8fbd5b516bd7dd914ee079e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 11:23:03 -0700 Subject: altos/ao_button.c: Support up to 16 buttons TeleLCO v2.0 has more than 4 Signed-off-by: Keith Packard --- src/drivers/ao_button.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index 07e92c67..f6a9676b 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -68,6 +68,39 @@ _ao_button_get(uint8_t b) #endif #if AO_BUTTON_COUNT > 4 case 4: return ao_button_value(4); +#endif +#if AO_BUTTON_COUNT > 5 + case 5: return ao_button_value(5); +#endif +#if AO_BUTTON_COUNT > 6 + case 6: return ao_button_value(6); +#endif +#if AO_BUTTON_COUNT > 7 + case 7: return ao_button_value(7); +#endif +#if AO_BUTTON_COUNT > 8 + case 8: return ao_button_value(8); +#endif +#if AO_BUTTON_COUNT > 9 + case 9: return ao_button_value(9); +#endif +#if AO_BUTTON_COUNT > 10 + case 10: return ao_button_value(10); +#endif +#if AO_BUTTON_COUNT > 11 + case 11: return ao_button_value(11); +#endif +#if AO_BUTTON_COUNT > 12 + case 12: return ao_button_value(12); +#endif +#if AO_BUTTON_COUNT > 13 + case 13: return ao_button_value(13); +#endif +#if AO_BUTTON_COUNT > 14 + case 14: return ao_button_value(14); +#endif +#if AO_BUTTON_COUNT > 15 + case 15: return ao_button_value(15); #endif } return 0; @@ -144,4 +177,40 @@ ao_button_init(void) #if AO_BUTTON_COUNT > 4 init(4); #endif +#if AO_BUTTON_COUNT > 5 + init(5); +#endif +#if AO_BUTTON_COUNT > 6 + init(6); +#endif +#if AO_BUTTON_COUNT > 7 + init(7); +#endif +#if AO_BUTTON_COUNT > 8 + init(8); +#endif +#if AO_BUTTON_COUNT > 9 + init(9); +#endif +#if AO_BUTTON_COUNT > 10 + init(10); +#endif +#if AO_BUTTON_COUNT > 11 + init(11); +#endif +#if AO_BUTTON_COUNT > 12 + init(12); +#endif +#if AO_BUTTON_COUNT > 13 + init(13); +#endif +#if AO_BUTTON_COUNT > 14 + init(14); +#endif +#if AO_BUTTON_COUNT > 15 + init(15); +#endif +#if AO_BUTTON_COUNT > 16 + #error too many buttons +#endif } -- cgit v1.2.3 From a4dbc940cc6c8ff5565e8af21f2dcb4ae090380c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 13:07:06 -0700 Subject: altos/drivers: Make quadrature debounce longer by default. Fix state tracking This increases the default debounce time for quadrature encoders to 30ms, which cleans up the mechanical encoders on TeleLCO v0.2. Also change state tracking to explicitly check for expected state values to avoid mis-triggering. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index deecfb79..d9cdfe7c 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -39,20 +39,24 @@ static struct ao_debounce ao_debounce_state[AO_QUADRATURE_COUNT][2]; #define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN #define isr(q) ao_quadrature_isr_ ## q -#define DEBOUNCE 10 +#ifndef AO_QUADRATURE_DEBOUNCE +#define AO_QUADRATURE_DEBOUNCE 30 +#endif static uint8_t ao_debounce(uint8_t cur, struct ao_debounce *debounce) { - if (cur == debounce->state) - debounce->count = 0; - else { - if (++debounce->count == DEBOUNCE) { - debounce->state = cur; - debounce->count = 0; - } +#if AO_QUADRATURE_DEBOUNCE > 0 + if (debounce->count > 0) { + debounce->count--; + } else if (cur != debounce->state) { + debounce->state = cur; + debounce->count = AO_QUADRATURE_DEBOUNCE; } return debounce->state; +#else + return cur; +#endif } static uint16_t @@ -84,9 +88,9 @@ _ao_quadrature_set(uint8_t q, uint8_t new) { uint8_t old = ao_quadrature_state[q]; if (old != new && new == 0) { - if (old & 2) + if (old == 2) _ao_quadrature_queue(q, 1); - else if (old & 1) + else if (old == 1) _ao_quadrature_queue(q, -1); } ao_quadrature_state[q] = new; -- cgit v1.2.3 From ccad6e970c5c7416561443f1e6e2fa8f80698957 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2018 14:15:34 -0700 Subject: altos/driver: Add support for one-step-per-click quadrature encoder The mechanical encoders go through all four steps per click while the optical ones have a single step per click. Support both kinds. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index d9cdfe7c..98bd7c08 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -55,6 +55,7 @@ ao_debounce(uint8_t cur, struct ao_debounce *debounce) } return debounce->state; #else + (void) debounce; return cur; #endif } @@ -83,16 +84,38 @@ _ao_quadrature_queue(uint8_t q, int8_t step) ao_wakeup(&ao_quadrature_count[q]); } +#if AO_QUADRATURE_SINGLE_CODE +struct ao_quadrature_step { + uint8_t inc; + uint8_t dec; +}; + +static struct ao_quadrature_step ao_quadrature_steps[4] = { + [0] = { .inc = 1, .dec = 2 }, + [1] = { .inc = 3, .dec = 0 }, + [3] = { .inc = 2, .dec = 1 }, + [2] = { .inc = 0, .dec = 3 }, +}; +#endif + static void _ao_quadrature_set(uint8_t q, uint8_t new) { uint8_t old = ao_quadrature_state[q]; +#ifdef AO_QUADRATURE_SINGLE_CODE + if (new == ao_quadrature_steps[old].inc) { + _ao_quadrature_queue(q, 1); + } else if (new == ao_quadrature_steps[old].dec) { + _ao_quadrature_queue(q, -1); + } +#else if (old != new && new == 0) { if (old == 2) _ao_quadrature_queue(q, 1); else if (old == 1) _ao_quadrature_queue(q, -1); } +#endif ao_quadrature_state[q] = new; } -- cgit v1.2.3 From 99642f9c4f89aa5577376a9cd118e7cff26e2762 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 May 2018 22:39:45 -0700 Subject: altos/telefire*: Do voltage tests in decivolts instead of ADC units This requires that each pad device specify the ADC reference voltage and all relevant voltage divider resistor values explicitly so that the ADC values can be converted to decivolts and compared with one another. This should be easier to understand in the future when reading the code. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 128 +++++++++++++++++++++------------------ src/telefire-v0.1/ao_pins.h | 15 +++-- src/telefire-v0.2/ao_pins.h | 17 ++++-- src/telefireeight-v1.0/ao_pins.h | 17 ++++-- src/telefiretwo-v0.1/ao_pins.h | 13 ++++ 5 files changed, 118 insertions(+), 72 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index b0ec2161..ed749d1c 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -153,13 +153,36 @@ ao_pad_run(void) #define AO_PAD_ARM_SIREN_INTERVAL 200 -#ifndef AO_PYRO_R_PYRO_SENSE -#define AO_PYRO_R_PYRO_SENSE 100 -#define AO_PYRO_R_SENSE_GND 27 -#define AO_FIRE_R_POWER_FET 100 -#define AO_FIRE_R_FET_SENSE 100 -#define AO_FIRE_R_SENSE_GND 27 -#endif +/* Resistor values needed for various voltage test ratios: + * + * Net names involved: + * + * V_BATT Battery power, after the initial power switch + * V_PYRO Pyro power, after the pyro power switch (and initial power switch) + * PYRO_SENSE ADC input to sense V_PYRO voltage + * BATT_SENSE ADC input to sense V_BATT voltage + * IGNITER FET output to pad (the other pad lead hooks to V_PYRO) + * IGNITER_SENSE ADC input to sense igniter voltage + * + * AO_PAD_R_V_BATT_BATT_SENSE Resistor from battery rail to battery sense input + * AO_PAD_R_BATT_SENSE_GND Resistor from battery sense input to ground + * + * AO_PAD_R_V_BATT_V_PYRO Resistor from battery rail to pyro rail + * AO_PAD_R_V_PYRO_PYRO_SENSE Resistor from pyro rail to pyro sense input + * AO_PAD_R_PYRO_SENSE_GND Resistor from pyro sense input to ground + * + * AO_PAD_R_V_PYRO_IGNITER Optional resistors from pyro rail to FET igniter output + * AO_PAD_R_IGNITER_IGNITER_SENSE Resistors from FET igniter output to igniter sense ADC inputs + * AO_PAD_R_IGNITER_SENSE_GND Resistors from igniter sense ADC inputs to ground + */ + +int16_t +ao_pad_decivolt(int16_t adc, int16_t r_plus, int16_t r_minus) +{ + int32_t mul = (int32_t) AO_ADC_REFERENCE_DV * (r_plus + r_minus); + int32_t div = (int32_t) AO_ADC_MAX * r_minus; + return ((int32_t) adc * mul + mul/2) / div; +} static void ao_pad_monitor(void) @@ -174,6 +197,7 @@ ao_pad_monitor(void) sample = ao_data_head; for (;;) { __pdata int16_t pyro; + ao_arch_critical( while (sample == ao_data_head) ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); @@ -183,28 +207,18 @@ ao_pad_monitor(void) packet = &ao_data_ring[sample]; sample = ao_data_ring_next(sample); - pyro = packet->adc.pyro; + /* Reply battery voltage */ + query.battery = ao_pad_decivolt(packet->adc.batt, AO_PAD_R_V_BATT_BATT_SENSE, AO_PAD_R_BATT_SENSE_GND); -#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \ - (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX))) + /* Current pyro voltage */ + pyro = ao_pad_decivolt(packet->adc.pyro, + AO_PAD_R_V_PYRO_PYRO_SENSE, + AO_PAD_R_PYRO_SENSE_GND); - -#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \ - (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX))) - - /* convert ADC value to voltage in tenths, then add .2 for the diode drop */ - query.battery = (packet->adc.batt + 96) / 192 + 2; cur = 0; - if (pyro > VOLTS_TO_PYRO(10)) { + if (pyro > query.battery * 7 / 8) { query.arm_status = AO_PAD_ARM_STATUS_ARMED; cur |= AO_LED_ARMED; -#if AO_FIRE_R_POWER_FET - } else if (pyro > VOLTS_TO_PYRO(5)) { - if ((ao_time() % 100) < 50) - cur |= AO_LED_ARMED; - query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN; - arm_beep_time = 0; -#endif } else { query.arm_status = AO_PAD_ARM_STATUS_DISARMED; arm_beep_time = 0; @@ -217,54 +231,50 @@ ao_pad_monitor(void) cur |= AO_LED_GREEN; for (c = 0; c < AO_PAD_NUM; c++) { - int16_t sense = packet->adc.sense[c]; + int16_t sense = ao_pad_decivolt(packet->adc.sense[c], + AO_PAD_R_IGNITER_IGNITER_SENSE, + AO_PAD_R_IGNITER_SENSE_GND); uint8_t status = AO_PAD_IGNITER_STATUS_UNKNOWN; /* - * pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20 - * v_pyro = pyro * 127 / 27 - * - * v_pyro \ - * 100k igniter - * output / - * 100k \ - * sense relay - * 27k / - * gnd --- + * Here's the resistor stack on each + * igniter channel. Note that + * AO_PAD_R_V_PYRO_IGNITER is optional * - * v_pyro \ - * 200k igniter - * output / - * 200k \ - * sense relay - * 22k / - * gnd --- + * v_pyro \ + * AO_PAD_R_V_PYRO_IGNITER igniter + * output / + * AO_PAD_R_IGNITER_IGNITER_SENSE \ + * sense relay + * AO_PAD_R_IGNITER_SENSE_GND / + * gnd --- * - * If the relay is closed, then sense will be 0 - * If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2 - * If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro */ -#if AO_FIRE_R_POWER_FET +#ifdef AO_PAD_R_V_PYRO_IGNITER if (sense <= pyro / 8) { + /* close to zero → relay is closed */ status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED; if ((ao_time() % 100) < 50) cur |= AO_LED_CONTINUITY(c); - } else - if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) - status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; - else if (pyro / 8 * 7 <= sense) { - status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; - cur |= AO_LED_CONTINUITY(c); - } -#else - if (sense >= pyro / 8 * 5) { - status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; - cur |= AO_LED_CONTINUITY(c); - } else { - status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; } + else #endif + { + if (sense >= (pyro * 7) / 8) { + + /* sense close to pyro voltage; igniter is good + */ + status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; + cur |= AO_LED_CONTINUITY(c); + } else { + + /* relay not shorted (if we can tell), + * and igniter not obviously present + */ + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + } + } query.igniter_status[c] = status; } if (cur != prev) { diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index ee0ca716..8266589e 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -100,10 +100,17 @@ #define AO_STROBE_PIN 1 #define AO_STROBE P1_1 -/* test these values with real igniters */ -#define AO_PAD_RELAY_CLOSED 3524 -#define AO_PAD_NO_IGNITER 16904 -#define AO_PAD_GOOD_IGNITER 22514 +#define AO_ADC_REFERENCE_DV 33 +#define AO_PAD_R_V_BATT_BATT_SENSE 100 +#define AO_PAD_R_BATT_SENSE_GND 27 + +#define AO_PAD_R_V_BATT_V_PYRO 100 +#define AO_PAD_R_V_PYRO_PYRO_SENSE 100 +#define AO_PAD_R_PYRO_SENSE_GND 27 + +#define AO_PAD_R_V_PYRO_IGNITER 100 +#define AO_PAD_R_IGNITER_IGNITER_SENSE 100 +#define AO_PAD_R_IGNITER_SENSE_GND 27 #define AO_PAD_ADC_PYRO 4 #define AO_PAD_ADC_BATT 5 diff --git a/src/telefire-v0.2/ao_pins.h b/src/telefire-v0.2/ao_pins.h index 4faeb65f..65f5bdcc 100644 --- a/src/telefire-v0.2/ao_pins.h +++ b/src/telefire-v0.2/ao_pins.h @@ -111,15 +111,24 @@ #define AO_STROBE P2_4 /* test these values with real igniters */ -#define AO_PAD_RELAY_CLOSED 3524 -#define AO_PAD_NO_IGNITER 16904 -#define AO_PAD_GOOD_IGNITER 22514 - #define AO_PAD_ADC_PYRO 4 #define AO_PAD_ADC_BATT 5 #define AO_ADC_FIRST_PIN 0 +#define AO_ADC_REFERENCE_DV 33 +#define AO_PAD_R_V_BATT_BATT_SENSE 100 +#define AO_PAD_R_BATT_SENSE_GND 27 + +#define AO_PAD_R_V_BATT_V_PYRO 100 +#define AO_PAD_R_V_PYRO_PYRO_SENSE 100 +#define AO_PAD_R_PYRO_SENSE_GND 27 + +#define AO_PAD_R_V_PYRO_IGNITER 100 +#define AO_PAD_R_IGNITER_IGNITER_SENSE 100 +#define AO_PAD_R_IGNITER_SENSE_GND 27 + + struct ao_adc { int16_t sense[AO_PAD_NUM]; int16_t pyro; diff --git a/src/telefireeight-v1.0/ao_pins.h b/src/telefireeight-v1.0/ao_pins.h index 271d2cbe..15e1fa11 100644 --- a/src/telefireeight-v1.0/ao_pins.h +++ b/src/telefireeight-v1.0/ao_pins.h @@ -295,16 +295,23 @@ #define AO_ADC_SQ9 AO_ADC_PYRO #define AO_ADC_SQ10 AO_ADC_BATT +#define AO_ADC_REFERENCE_DV 33 + #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ (1 << STM_RCC_AHBENR_GPIOBEN) | \ (1 << STM_RCC_AHBENR_GPIOCEN)) -#define AO_PYRO_R_PYRO_SENSE 200 -#define AO_PYRO_R_SENSE_GND 22 -#define AO_FIRE_R_POWER_FET 0 -#define AO_FIRE_R_FET_SENSE 200 -#define AO_FIRE_R_SENSE_GND 22 +#define AO_PAD_R_V_BATT_BATT_SENSE 200 +#define AO_PAD_R_BATT_SENSE_GND 22 + +#define AO_PAD_R_V_BATT_V_PYRO 200 +#define AO_PAD_R_V_PYRO_PYRO_SENSE 200 +#define AO_PAD_R_PYRO_SENSE_GND 22 + +#undef AO_PAD_R_V_PYRO_IGNITER +#define AO_PAD_R_IGNITER_IGNITER_SENSE 200 +#define AO_PAD_R_IGNITER_SENSE_GND 22 #define HAS_ADC_TEMP 0 diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h index 1e5c0d09..dedd0fad 100644 --- a/src/telefiretwo-v0.1/ao_pins.h +++ b/src/telefiretwo-v0.1/ao_pins.h @@ -191,6 +191,19 @@ #define HAS_ADC_TEMP 0 +#define AO_ADC_REFERENCE_DV 33 + +#define AO_PAD_R_V_BATT_BATT_SENSE 200 +#define AO_PAD_R_BATT_SENSE_GND 22 + +#define AO_PAD_R_V_BATT_V_PYRO 200 +#define AO_PAD_R_V_PYRO_PYRO_SENSE 200 +#define AO_PAD_R_PYRO_SENSE_GND 22 + +#undef AO_PAD_R_V_PYRO_IGNITER +#define AO_PAD_R_IGNITER_IGNITER_SENSE 200 +#define AO_PAD_R_IGNITER_SENSE_GND 22 + struct ao_adc { int16_t sense[AO_PAD_NUM]; int16_t pyro; -- 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/drivers') 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 abac6c59d6b004d52a7b782865d2d987732cd61e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2018 00:17:29 -0700 Subject: altos/telelco-v0: Test display, show batt voltage at boot Just like telelco v2 Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index e1806ca3..91a0593f 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -23,6 +23,9 @@ #include #include #include +#if HAS_ADC_SINGLE +#include +#endif #define DEBUG 1 @@ -640,6 +643,37 @@ 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); +} + +#if HAS_ADC_SINGLE +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)); +} +#endif + 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; @@ -651,6 +685,10 @@ ao_lco_monitor(void) uint16_t delay; uint8_t box; + ao_lco_display_test(); +#if HAS_ADC_SINGLE + ao_lco_batt_voltage(); +#endif 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"); -- cgit v1.2.3 From 16482bf5d63eafc5256f14a218d3a374f6584e0a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jun 2018 23:51:26 -0700 Subject: altos/driver: Improve quadrature debouncing for mechanical encoders Track state of encoder better and only bump values when the full motion is detected (all four states). Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 81 +++++++++++++++++++++++++++------------------ src/telelco-v0.2/ao_pins.h | 1 + src/telelco-v0.3/ao_pins.h | 1 + 3 files changed, 51 insertions(+), 32 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 98bd7c08..59e84518 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -23,6 +23,10 @@ #include __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; +#ifndef AO_QUADRATURE_SINGLE_CODE +static int8_t ao_quadrature_step[AO_QUADRATURE_COUNT]; +#endif + static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT]; struct ao_debounce { @@ -40,7 +44,7 @@ static struct ao_debounce ao_debounce_state[AO_QUADRATURE_COUNT][2]; #define isr(q) ao_quadrature_isr_ ## q #ifndef AO_QUADRATURE_DEBOUNCE -#define AO_QUADRATURE_DEBOUNCE 30 +#error must define AO_QUADRATURE_DEBOUNCE #endif static uint8_t @@ -75,8 +79,21 @@ ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b, struct a #define _ao_quadrature_get(q) ao_quadrature_read(port(q), bita(q), bitb(q), ao_debounce_state[q]) static void -_ao_quadrature_queue(uint8_t q, int8_t step) +_ao_quadrature_step(uint8_t q, int8_t step) { +#ifndef AO_QUADRATURE_SINGLE_CODE + ao_quadrature_step[q] += step; + if (ao_quadrature_state[q] != 0) + return; + if (ao_quadrature_step[q] >= 4) { + ao_quadrature_step[q] = 0; + step = 1; + } else if (ao_quadrature_step[q] <= -4) { + ao_quadrature_step[q] = 0; + step = -1; + } else + return; +#endif ao_quadrature_count[q] += step; #if AO_EVENT ao_event_put_isr(AO_EVENT_QUADRATURE, q, step); @@ -84,39 +101,28 @@ _ao_quadrature_queue(uint8_t q, int8_t step) ao_wakeup(&ao_quadrature_count[q]); } -#if AO_QUADRATURE_SINGLE_CODE -struct ao_quadrature_step { - uint8_t inc; - uint8_t dec; +static const struct { + uint8_t prev, next; +} ao_quadrature_steps[4] = { + [0] { .prev = 2, .next = 1 }, + [1] { .prev = 0, .next = 3 }, + [3] { .prev = 1, .next = 2 }, + [2] { .prev = 3, .next = 0 }, }; -static struct ao_quadrature_step ao_quadrature_steps[4] = { - [0] = { .inc = 1, .dec = 2 }, - [1] = { .inc = 3, .dec = 0 }, - [3] = { .inc = 2, .dec = 1 }, - [2] = { .inc = 0, .dec = 3 }, -}; -#endif - static void _ao_quadrature_set(uint8_t q, uint8_t new) { - uint8_t old = ao_quadrature_state[q]; + uint8_t old; -#ifdef AO_QUADRATURE_SINGLE_CODE - if (new == ao_quadrature_steps[old].inc) { - _ao_quadrature_queue(q, 1); - } else if (new == ao_quadrature_steps[old].dec) { - _ao_quadrature_queue(q, -1); - } -#else - if (old != new && new == 0) { - if (old == 2) - _ao_quadrature_queue(q, 1); - else if (old == 1) - _ao_quadrature_queue(q, -1); - } -#endif + ao_arch_block_interrupts(); + old = ao_quadrature_state[q]; ao_quadrature_state[q] = new; + ao_arch_release_interrupts(); + + if (new == ao_quadrature_steps[old].next) + _ao_quadrature_step(q, 1); + else if (new == ao_quadrature_steps[old].prev) + _ao_quadrature_step(q, -1); } static void @@ -151,21 +157,32 @@ ao_quadrature_test(void) uint8_t q; int32_t c; uint8_t s; +#ifndef AO_QUADRATURE_SINGLE_CODE + int8_t t = 0; +#endif ao_cmd_decimal(); q = ao_cmd_lex_i; - if (q >= AO_QUADRATURE_COUNT) { + if (q >= AO_QUADRATURE_COUNT) ao_cmd_status = ao_cmd_syntax_error; + if (ao_cmd_status != ao_cmd_success) return; - } c = -10000; s = 0; while (ao_quadrature_count[q] != 10) { if (ao_quadrature_count[q] != c || - ao_quadrature_state[q] != s) { +#ifndef AO_QUADRATURE_SINGLE_CODE + ao_quadrature_step[q] != t || +#endif + ao_quadrature_state[q] != s) + { c = ao_quadrature_count[q]; s = ao_quadrature_state[q]; +#ifndef AO_QUADRATURE_SINGLE_CODE + t = ao_quadrature_step[q]; + printf("step %3d ", t); +#endif printf ("count %3d state %2x\n", c, s); flush(); } diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index b90fca8b..f0da4fe4 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -253,6 +253,7 @@ #define AO_QUADRATURE_1_B 0 #define AO_QUADRATURE_BOX 1 +#define AO_QUADRATURE_DEBOUNCE 10 /* * Buttons diff --git a/src/telelco-v0.3/ao_pins.h b/src/telelco-v0.3/ao_pins.h index 6fd897a0..6023739c 100644 --- a/src/telelco-v0.3/ao_pins.h +++ b/src/telelco-v0.3/ao_pins.h @@ -252,6 +252,7 @@ #define AO_QUADRATURE_1_B 0 #define AO_QUADRATURE_BOX 1 +#define AO_QUADRATURE_DEBOUNCE 10 /* * Buttons -- cgit v1.2.3 From 731ba39a22719a8c431eb63895cd8ba553975114 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2018 12:29:36 -0700 Subject: altos/ao_pad: Use AO_LED_TYPE for computing active LEDs. instead of uint8_t Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index ed749d1c..499b5238 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -189,7 +189,7 @@ ao_pad_monitor(void) { uint8_t c; uint8_t sample; - __pdata uint8_t prev = 0, cur = 0; + __pdata AO_LED_TYPE prev = 0, cur = 0; __pdata uint8_t beeping = 0; __xdata volatile struct ao_data *packet; __pdata uint16_t arm_beep_time = 0; -- cgit v1.2.3 From cef5a5725e3bf2c17965599bd76eb93cb05a0f80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2018 12:30:09 -0700 Subject: altos/ao_pad: Turn on all LEDs for a moment at power up Allow validation of all LED connections. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 499b5238..d2b22b95 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -370,6 +370,8 @@ ao_pad(void) int8_t ret; ao_pad_box = 0; + ao_led_set(LEDS_AVAILABLE); + ao_delay(AO_MS_TO_TICKS(500)); ao_led_set(0); for (;;) { FLUSHD(); -- cgit v1.2.3 From 9ece56e3ad76af6ae623ad7a6782c0c933839be8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2018 12:35:23 -0700 Subject: altos/ao_pad: Move LED test to the monitor task It sets the LEDs, so it's best to not start doing that until we've tested them. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index d2b22b95..c6efc311 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -195,6 +195,9 @@ ao_pad_monitor(void) __pdata uint16_t arm_beep_time = 0; sample = ao_data_head; + ao_led_set(LEDS_AVAILABLE); + ao_delay(AO_MS_TO_TICKS(1000)); + ao_led_set(0); for (;;) { __pdata int16_t pyro; @@ -370,9 +373,6 @@ ao_pad(void) int8_t ret; ao_pad_box = 0; - ao_led_set(LEDS_AVAILABLE); - ao_delay(AO_MS_TO_TICKS(500)); - ao_led_set(0); for (;;) { FLUSHD(); while (ao_pad_disabled) -- 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/drivers') 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/drivers') 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/drivers') 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 2214ad7c0f268be76c0b027eef9d1dc406f23b28 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Jul 2018 11:27:31 -0700 Subject: altos: Fix LCO display while searching Use lower level functions to control the display more directly Signed-off-by: Keith Packard --- src/drivers/ao_lco_bits.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c index 9492cf59..6c5182f2 100644 --- a/src/drivers/ao_lco_bits.c +++ b/src/drivers/ao_lco_bits.c @@ -202,23 +202,20 @@ ao_lco_box_set_present(uint8_t 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(); - } + 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; + ao_lco_box = new_box; #if AO_LCO_DRAG - if (ao_lco_box != AO_LCO_BOX_DRAG) + if (ao_lco_box != AO_LCO_BOX_DRAG) #endif - ao_lco_channels[ao_lco_box] = 0; - ao_lco_set_pad(1); - } + ao_lco_channels[ao_lco_box] = 0; + ao_lco_pad = 1; + ao_lco_show_display(); } void @@ -283,8 +280,10 @@ ao_lco_search(void) 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); + if ((box % 10) == 0) { + ao_lco_box = box; + ao_lco_show_display(); + } 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]); @@ -304,7 +303,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_set_pad(1); + ao_lco_set_box(ao_lco_min_box); } void -- 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/drivers') 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 From ad9d6677231ccbfa09a528387f306f5364f9d608 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Jul 2018 12:34:38 -0700 Subject: altos: Make fewer LCO variables public The lco common code doesn't need to share its internal values with the world; make most of them static. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 3 +-- src/drivers/ao_lco.h | 18 +++++------------- src/drivers/ao_lco_bits.c | 42 ++++++++++++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 29 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 47752f1f..e892c8c0 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -34,8 +34,7 @@ #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 +#define AO_LCO_BOX_DRAG 0x1000 /* UI values */ static uint16_t ao_lco_fire_tick; diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h index e528c2ad..2958fbcc 100644 --- a/src/drivers/ao_lco.h +++ b/src/drivers/ao_lco.h @@ -25,10 +25,6 @@ #define AO_LCO_DRAG 1 #endif -#if AO_LCO_DRAG -#define AO_LCO_BOX_DRAG 0x1000 -#endif - #define DEBUG 1 #if DEBUG @@ -38,25 +34,21 @@ extern uint8_t ao_lco_debug; #define PRINTD(...) #endif +#if AO_LCO_DRAG extern uint8_t ao_lco_drag_race; /* TRUE when drag race mode enabled */ +#endif + 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 uint8_t ao_lco_armed; /* armed mode active */ +extern uint8_t ao_lco_firing; /* fire button pressed */ 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) diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c index 197bf8aa..6e50e44d 100644 --- a/src/drivers/ao_lco_bits.c +++ b/src/drivers/ao_lco_bits.c @@ -20,20 +20,28 @@ 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_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; +#if AO_LCO_DRAG +uint8_t ao_lco_drag_race; +#endif + +struct ao_pad_query ao_pad_query; /* latest query response */ -static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { +static uint8_t ao_lco_channels[AO_PAD_MAX_BOXES]; /* pad channels available on each box */ +static uint16_t ao_lco_tick_offset[AO_PAD_MAX_BOXES]; /* offset from local to remote tick count */ +static uint8_t ao_lco_selected[AO_PAD_MAX_BOXES]; /* pads selected to fire */ + +#define AO_LCO_VALID_LAST 1 +#define AO_LCO_VALID_EVER 2 + +static uint8_t ao_lco_valid[AO_PAD_MAX_BOXES]; /* AO_LCO_VALID bits per box */ + +static const AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { #ifdef AO_LED_CONTINUITY_0 AO_LED_CONTINUITY_0, #endif @@ -68,9 +76,11 @@ ao_lco_igniter_status(void) uint8_t t = 0; for (;;) { +#if AO_LCO_DRAG if (ao_lco_drag_race) ao_sleep_for(&ao_pad_query, AO_MS_TO_TICKS(50)); else +#endif ao_sleep(&ao_pad_query); 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)) { @@ -98,6 +108,7 @@ ao_lco_igniter_status(void) else status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; +#if AO_LCO_DRAG if (ao_lco_drag_race && (ao_lco_selected[ao_lco_box] & (1 << c))) { uint8_t on = 0; if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) { @@ -111,7 +122,9 @@ ao_lco_igniter_status(void) ao_led_on(continuity_led[c]); else ao_led_off(continuity_led[c]); - } else { + } else +#endif + { if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) ao_led_on(continuity_led[c]); else @@ -210,9 +223,7 @@ void ao_lco_set_box(uint16_t new_box) { ao_lco_box = new_box; -#if AO_LCO_DRAG - if (ao_lco_box != AO_LCO_BOX_DRAG) -#endif + if (ao_lco_box < AO_PAD_MAX_BOXES) ao_lco_channels[ao_lco_box] = 0; ao_lco_pad = 1; ao_lco_show(); @@ -242,6 +253,7 @@ 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 if (ao_lco_drag_race) { uint8_t box; @@ -250,7 +262,9 @@ ao_lco_set_armed(uint8_t armed) break; if (box > ao_lco_max_box) ao_lco_armed = 0; - } else { + } else +#endif + { memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); if (ao_lco_pad != 0) ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1)); -- cgit v1.2.3 From 323a79e6ed3dfdd2afadfc2a464bb0610380b03b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Jul 2018 16:08:31 -0700 Subject: altos: Fetch current quadrature status at startup time This avoids having the state appear to change the first time we look at the device. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 59e84518..250e035f 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -111,7 +111,8 @@ static const struct { }; static void -_ao_quadrature_set(uint8_t q, uint8_t new) { +_ao_quadrature_set(uint8_t q, uint8_t new) +{ uint8_t old; ao_arch_block_interrupts(); @@ -136,6 +137,14 @@ ao_quadrature_isr(void) #endif } +static void +_ao_quadrature_start_one(uint8_t q, uint8_t new) +{ + ao_arch_block_interrupts(); + ao_quadrature_state[q] = new; + ao_arch_release_interrupts(); +} + int32_t ao_quadrature_poll(uint8_t q) { @@ -204,9 +213,10 @@ static const struct ao_cmds ao_quadrature_cmds[] = { { 0, NULL } }; -#define init(q) do { \ - ao_enable_input(port(q), bita(q), 0); \ - ao_enable_input(port(q), bitb(q), 0); \ +#define init(q) do { \ + ao_enable_input(port(q), bita(q), 0); \ + ao_enable_input(port(q), bitb(q), 0); \ + _ao_quadrature_start_one(q, _ao_quadrature_get(q)); \ } while (0) void -- cgit v1.2.3