X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fdrivers%2Fao_pad.c;h=f3975dbc1b21b42d9e0265b51e79d0388fb71b08;hb=12c8bea85ceb822d0764711b6e03f910b3faae3c;hp=b0ec21617d177005da40eba90d9e6192ee1d590c;hpb=e272f6a66881b6904037ee7b1afeb9a8a3ec5b2a;p=fw%2Faltos diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index b0ec2161..f3975dbc 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -39,8 +39,8 @@ static __pdata uint16_t ao_pad_packet_time; #if DEBUG static __pdata uint8_t ao_pad_debug; -#define PRINTD(...) (ao_pad_debug ? (printf(__VA_ARGS__), 0) : 0) -#define FLUSHD() (ao_pad_debug ? (flush(), 0) : 0) +#define PRINTD(...) do { if (ao_pad_debug) { printf(__VA_ARGS__); flush(); } } while(0) +#define FLUSHD() #else #define PRINTD(...) #define FLUSHD() @@ -139,13 +139,14 @@ ao_pad_run(void) ao_pad_ignite = 0; ao_delay(AO_PAD_FIRE_TIME); + PRINTD("ao_pad_ignite now %d\n", ao_pad_ignite); } #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); + ao_gpio_clr_bits(AO_PAD_PORT_0, pins0); PRINTD("turn off pins 0x%x\n", pins0); #endif } @@ -153,27 +154,54 @@ 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) { 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; 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; + ao_arch_critical( while (sample == ao_data_head) ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); @@ -183,28 +211,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,60 +235,56 @@ 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 + * Here's the resistor stack on each + * igniter channel. Note that + * AO_PAD_R_V_PYRO_IGNITER is optional * - * v_pyro \ - * 100k igniter - * output / - * 100k \ - * sense relay - * 27k / - * 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 --- * - * v_pyro \ - * 200k igniter - * output / - * 200k \ - * sense relay - * 22k / - * 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) { - PRINTD("change leds from %02x to %02x\n", - prev, cur); - FLUSHD(); +// PRINTD("change leds from %02x to %02x\n", +// prev, cur); +// FLUSHD(); ao_led_set(cur); prev = cur; } @@ -320,6 +334,7 @@ ao_pad_read_box(void) uint8_t byte = ao_74hc165_read(); uint8_t h, l; + PRINTD("box %02x\n", byte); h = byte >> 4; l = byte & 0xf; return h * 10 + l; @@ -343,10 +358,6 @@ static int ao_pad_read_box(void) { } #else -#if HAS_FIXED_PAD_BOX -#define ao_pad_read_box() ao_config.pad_box -#endif - #ifdef PAD_BOX #define ao_pad_read_box() PAD_BOX #endif @@ -360,7 +371,6 @@ ao_pad(void) int8_t ret; ao_pad_box = 0; - ao_led_set(0); for (;;) { FLUSHD(); while (ao_pad_disabled) @@ -371,7 +381,11 @@ ao_pad(void) continue; ao_pad_packet_time = ao_time(); - ao_pad_box = ao_pad_read_box(); + ao_pad_box = ao_config.pad_box; +#ifndef HAS_FIXED_PAD_BOX + if (ao_pad_box == 0 || ao_pad_box == 0xff) + ao_pad_box = ao_pad_read_box(); +#endif PRINTD ("tick %d box %d (me %d) cmd %d channels %02x\n", command.tick, command.box, ao_pad_box, command.cmd, command.channels);