altos: Remove 8051 address space specifiers
[fw/altos] / src / drivers / ao_pad.c
index b0ec21617d177005da40eba90d9e6192ee1d590c..7e139c7808d1504f09f375e2e39245aab9fa7197 100644 (file)
 #include <ao_74hc165.h>
 #include <ao_radio_cmac.h>
 
-static __xdata uint8_t ao_pad_ignite;
-static __xdata struct ao_pad_command   command;
-static __xdata struct ao_pad_query     query;
-static __pdata uint8_t ao_pad_armed;
-static __pdata uint16_t        ao_pad_arm_time;
-static __pdata uint8_t ao_pad_box;
-static __xdata uint8_t ao_pad_disabled;
-static __pdata uint16_t        ao_pad_packet_time;
+static uint8_t ao_pad_ignite;
+static struct ao_pad_command   command;
+static struct ao_pad_query     query;
+static uint8_t ao_pad_armed;
+static uint16_t        ao_pad_arm_time;
+static uint8_t ao_pad_box;
+static uint8_t ao_pad_disabled;
+static uint16_t        ao_pad_packet_time;
 
 #ifndef AO_PAD_RSSI_MINIMUM
 #define AO_PAD_RSSI_MINIMUM    -90
@@ -38,7 +38,7 @@ static __pdata uint16_t       ao_pad_packet_time;
 #define DEBUG  1
 
 #if DEBUG
-static __pdata uint8_t ao_pad_debug;
+static uint8_t ao_pad_debug;
 #define PRINTD(...) (ao_pad_debug ? (printf(__VA_ARGS__), 0) : 0)
 #define FLUSHD()    (ao_pad_debug ? (flush(), 0) : 0)
 #else
@@ -153,58 +153,75 @@ 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 uint8_t         beeping = 0;
-       __xdata volatile struct ao_data *packet;
-       __pdata uint16_t        arm_beep_time = 0;
+       AO_LED_TYPE     prev = 0, cur = 0;
+       uint8_t         beeping = 0;
+       volatile struct ao_data *packet;
+       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;
+               int16_t                 pyro;
+
                ao_arch_critical(
                        while (sample == ao_data_head)
-                               ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
+                               ao_sleep((void *) &ao_data_head);
                        );
 
 
                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 +234,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) {
@@ -360,7 +373,6 @@ ao_pad(void)
        int8_t  ret;
 
        ao_pad_box = 0;
-       ao_led_set(0);
        for (;;) {
                FLUSHD();
                while (ao_pad_disabled)
@@ -514,9 +526,9 @@ ao_pad_manual(void)
        }
 }
 
-static __xdata struct ao_task ao_pad_task;
-static __xdata struct ao_task ao_pad_ignite_task;
-static __xdata struct ao_task ao_pad_monitor_task;
+static struct ao_task ao_pad_task;
+static struct ao_task ao_pad_ignite_task;
+static struct ao_task ao_pad_monitor_task;
 
 #if DEBUG
 void
@@ -548,7 +560,7 @@ ao_pad_alarm_debug(void)
 }
 #endif
 
-__code struct ao_cmds ao_pad_cmds[] = {
+const struct ao_cmds ao_pad_cmds[] = {
        { ao_pad_test,  "t\0Test pad continuity" },
        { ao_pad_manual,        "i <key> <n>\0Fire igniter. <key> is doit with D&I" },
 #if DEBUG