From 427335c5264794d980623f0aa308d6e0b3ff0042 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 29 May 2009 17:55:31 +0200 Subject: pressure-control: Fix APIs for multiple sensors Signed-off-by: Michael Buesch --- pressure_control/firmware/main.c | 36 +++++++------ pressure_control/firmware/main.h | 6 +++ pressure_control/firmware/remote.c | 16 +++--- pressure_control/firmware/sensor.c | 53 +++++++----------- pressure_control/firmware/sensor.h | 29 ++++++++-- pressure_control/firmware/util.c | 5 ++ pressure_control/firmware/util.h | 10 ++++ pressure_control/firmware/valves.c | 107 ++++++++++++++++--------------------- pressure_control/firmware/valves.h | 56 ++++++++++++++----- 9 files changed, 187 insertions(+), 131 deletions(-) (limited to 'pressure_control/firmware') diff --git a/pressure_control/firmware/main.c b/pressure_control/firmware/main.c index 01933ce..ec2335d 100644 --- a/pressure_control/firmware/main.c +++ b/pressure_control/firmware/main.c @@ -1,7 +1,7 @@ /* * Pneumatic pressure controller. * - * Copyright (C) 2008 Michael Buesch + * Copyright (C) 2008-2009 Michael Buesch * * 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 @@ -43,6 +43,11 @@ struct pressure_state state; /* The 1000Hz jiffies counter */ static jiffies_t jiffies_counter; +DEFINE_VALVE(xy_control_valves, D, 6, 7, 4, 5); +DEFINE_VALVE(z_control_valves, C, 2, 3, 4, 5); +static DEFINE_SENSOR(xy_control_sensor, 0, 245, 4400, 10000); +static DEFINE_SENSOR(z_control_sensor, (1<= 0); - cur_state = valves_get_global_state(); + cur_state = valves_get_global_state(&xy_control_valves); if (abs_offset > cfg.hysteresis) { /* Adjust the pressure */ report_change = (cur_state == VALVES_IDLE); if (is_too_big) - valves_global_switch(VALVES_FLOW_OUT); + valves_global_switch(&xy_control_valves, VALVES_FLOW_OUT); else - valves_global_switch(VALVES_FLOW_IN); + valves_global_switch(&xy_control_valves, VALVES_FLOW_IN); } else if (abs_offset > cfg.hysteresis / 4) { /* If we're idle, stay idle. * If we're increasing or decreasing pressure, @@ -167,15 +172,16 @@ static void check_pressure(void) * The pressure is OK. Make sure the valves are * all idle. */ report_change = (cur_state != VALVES_IDLE); - valves_global_switch(VALVES_IDLE); + valves_global_switch(&xy_control_valves, VALVES_IDLE); } if (state.mbar < 800) { /* If the pressure in the reservoir is low, * the feedforward of the pneumatic valve for * flow-out might not work correctly. So force poke * the valves again until we reach a good pressure. */ - __valves_global_switch(valves_get_global_state()); - valves_disarm_auto_idle(); + __valves_global_switch(&xy_control_valves, + valves_get_global_state(&xy_control_valves)); + valves_disarm_auto_idle(&xy_control_valves); } } if (abs((int32_t)state.mbar - (int32_t)state.reported_mbar) >= 100) @@ -220,7 +226,7 @@ int main(void) wdt_disable(); if (mcucsr & (1 << BORF)) { /* If we have a brownout, try to enter valve emergency state. */ - valves_emergency_state(); + valves_emergency_state(&xy_control_valves); mdelay(500); /* This wasn't a real brownout, if we're still alife. * Go on with initialization. */ @@ -236,8 +242,8 @@ int main(void) if (!(mcucsr & (1 << PORF)) && (mcucsr & (1 << WDRF))) print("WATCHDOG RESET!\n"); - valves_init(); - sensor_init(); + valves_init(&xy_control_valves); + sensor_init(&xy_control_sensor); eeprom_load_config(); system_timer_init(); @@ -246,7 +252,7 @@ int main(void) print("Monitoring...\n"); remote_work(); remote_notify_restart(); - sensor_trigger_read(); + sensor_trigger_read(&xy_control_sensor); while (1) { static jiffies_t next_sensor_trigger; static bool need_sensor_trigger; @@ -269,10 +275,10 @@ int main(void) /* It's time for triggering another * sensor measurement. */ need_sensor_trigger = 0; - sensor_trigger_read(); + sensor_trigger_read(&xy_control_sensor); } remote_work(); - valves_work(); + valves_work(&xy_control_valves); wdt_reset(); } } diff --git a/pressure_control/firmware/main.h b/pressure_control/firmware/main.h index d8cb6aa..7a9dbf2 100644 --- a/pressure_control/firmware/main.h +++ b/pressure_control/firmware/main.h @@ -59,4 +59,10 @@ void get_pressure_state(struct pressure_state *state); void prepare_turn_on(void); void prepare_shutdown(void); + +struct valves; +extern struct valves xy_control_valves; +extern struct valves z_control_valves; + + #endif /* MAIN_H_ */ diff --git a/pressure_control/firmware/remote.c b/pressure_control/firmware/remote.c index 6383339..c640067 100644 --- a/pressure_control/firmware/remote.c +++ b/pressure_control/firmware/remote.c @@ -183,7 +183,7 @@ static void handle_received_message(void) if (conf.autoadjust_enable != flag) { conf.autoadjust_enable = flag; /* Make sure the values are idle. */ - valves_global_switch(VALVES_IDLE); + valves_global_switch(&xy_control_valves, VALVES_IDLE); } set_pressure_config(&conf); sei(); @@ -198,22 +198,22 @@ static void handle_received_message(void) break; } if (rx_msg.valve.nr == 0) { - valve0_switch(rx_msg.valve.state == 0 ? + valve0_switch(&xy_control_valves, rx_msg.valve.state == 0 ? VALVE_STATE_12 : VALVE_STATE_14); - valve_wait_toggle(); - valve0_switch(VALVE_STATE_IDLE); + valve_wait_toggle(&xy_control_valves); + valve0_switch(&xy_control_valves, VALVE_STATE_IDLE); } else if (rx_msg.valve.nr == 1) { - valve1_switch(rx_msg.valve.state == 0 ? + valve1_switch(&xy_control_valves, rx_msg.valve.state == 0 ? VALVE_STATE_12 : VALVE_STATE_14); - valve_wait_toggle(); - valve0_switch(VALVE_STATE_IDLE); + valve_wait_toggle(&xy_control_valves); + valve0_switch(&xy_control_valves, VALVE_STATE_IDLE); } else err = MSG_ERR_INVAL; break; } case MSG_SHUTDOWN: prepare_shutdown(); - valves_shutdown(); + valves_shutdown(&xy_control_valves); break; case MSG_TURNON: prepare_turn_on(); diff --git a/pressure_control/firmware/sensor.c b/pressure_control/firmware/sensor.c index 475cc6e..bf48fb2 100644 --- a/pressure_control/firmware/sensor.c +++ b/pressure_control/firmware/sensor.c @@ -26,54 +26,40 @@ #include -/* The sensor value offset, in millivolts. - * This value is subtracted from the measured voltage before - * processing. */ -#define SENSOR_MV_OFFSET 245 - -/* The Full Scale Output (maximum) output value of the sensor, - * in millivolts. */ -#define SENSOR_FULL_SCALE_MV U32(4400) - -/* The pressure at Full Scale Output, in millibar. */ -#define SENSOR_FULL_SCALE_MBAR U32(10000) - -/* The sensor enable signal pin. */ -#define SENSOR_ENABLE_DDR DDRC -#define SENSOR_ENABLE_PORT PORTC -#define SENSOR_ENABLE_BIT 1 - - +static struct sensor *active_sensor; #define ADC_MAX U32(0x3FF) ISR(ADC_vect) { - const uint16_t full_scale_adc = ADC_MAX * SENSOR_FULL_SCALE_MV / 5000; - + struct sensor *s = active_sensor; + const uint16_t full_scale_adc = ADC_MAX * (uint32_t)s->full_scale_mv / 5000; uint16_t adc, mv, mbar; + BUG_ON(!active_sensor); + /* Convert the ADC value to millivolts. */ adc = ADC; if (adc > full_scale_adc) adc = full_scale_adc; - mv = SENSOR_FULL_SCALE_MV * (uint32_t)adc / full_scale_adc; + mv = (uint32_t)s->full_scale_mv * (uint32_t)adc / full_scale_adc; /* Subtract the sensor voltage offset, so 0 mBar results in 0 mV. */ - if (mv > SENSOR_MV_OFFSET) - mv -= SENSOR_MV_OFFSET; + if (mv > s->mv_offset) + mv -= s->mv_offset; else mv = 0; - mbar = SENSOR_FULL_SCALE_MBAR * (uint32_t)mv / SENSOR_FULL_SCALE_MV; + mbar = (uint32_t)s->full_scale_mbar * (uint32_t)mv / (uint32_t)s->full_scale_mv; - sensor_result(mbar); + sensor_result(active_sensor, mbar); + active_sensor = NULL; } -static inline void adc_trigger(bool with_irq) +static inline void adc_trigger(uint8_t mux, bool with_irq) { /* Set the multiplexer to ADC-0, AVcc Ref. */ - ADMUX = (1 << REFS0); + ADMUX = (1 << REFS0) | mux; /* Start ADC with a prescaler of 128. That's a ADC freq * of 125kHz on a 16MHz crystal. */ ADCSRA = (1 << ADEN) | (1 << ADSC) | @@ -81,19 +67,20 @@ static inline void adc_trigger(bool with_irq) (with_irq ? (1 << ADIE) : 0); } -void sensor_trigger_read(void) +void sensor_trigger_read(struct sensor *s) { + BUG_ON(active_sensor); + active_sensor = s; + mb(); /* Trigger an ADC conversion with interrupt notification. */ - adc_trigger(1); + adc_trigger(s->adc_mux, 1); } -void sensor_init(void) +void sensor_init(struct sensor *s) { - SENSOR_ENABLE_DDR |= (1 << SENSOR_ENABLE_BIT); - SENSOR_ENABLE_PORT |= (1 << SENSOR_ENABLE_BIT); mdelay(20); /* Warm-up time */ /* Discard the first ADC result. */ - adc_trigger(0); + adc_trigger(s->adc_mux, 0); while (ADCSRA & (1 << ADSC)) mb(); } diff --git a/pressure_control/firmware/sensor.h b/pressure_control/firmware/sensor.h index a6230ad..8f3c4e5 100644 --- a/pressure_control/firmware/sensor.h +++ b/pressure_control/firmware/sensor.h @@ -4,10 +4,33 @@ #include -void sensor_trigger_read(void); -void sensor_init(void); +struct sensor { + /* ADMUX */ + uint8_t adc_mux; + /* The sensor value offset, in millivolts. + * This value is subtracted from the measured voltage before + * processing. */ + uint16_t mv_offset; + /* The Full Scale Output (maximum) output value of the sensor, + * in millivolts. */ + uint16_t full_scale_mv; + /* The pressure at Full Scale Output, in millibar. */ + uint16_t full_scale_mbar; +}; + +#define DEFINE_SENSOR(name, mux, _mv_offset, _full_scale_mv, _full_scale_mbar) \ + struct sensor name = { \ + .adc_mux = mux, \ + .mv_offset = _mv_offset, \ + .full_scale_mv = _full_scale_mv, \ + .full_scale_mbar = _full_scale_mbar, \ + } + +void sensor_trigger_read(struct sensor *s); +void sensor_init(struct sensor *s); /* Callback for sensor value reporting. */ -extern void sensor_result(uint16_t millibar_result_value); +extern void sensor_result(struct sensor *s, + uint16_t millibar_result_value); #endif /* SENSOR_H_ */ diff --git a/pressure_control/firmware/util.c b/pressure_control/firmware/util.c index 0f3b8b7..241fc19 100644 --- a/pressure_control/firmware/util.c +++ b/pressure_control/firmware/util.c @@ -25,6 +25,11 @@ #include +const prog_uint8_t bit2mask_lt[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, +}; + + void mdelay(uint16_t msecs) { uint8_t timer, i; diff --git a/pressure_control/firmware/util.h b/pressure_control/firmware/util.h index 4d357fe..28e98f8 100644 --- a/pressure_control/firmware/util.h +++ b/pressure_control/firmware/util.h @@ -90,4 +90,14 @@ uint16_t crc16_block_update(uint16_t crc, const void *data, uint16_t size); #define U64(value) ((uint64_t)(value)) +/* Convert a bit-number to a bit-mask. + * Only valid for bitnr<=7. + */ +extern const prog_uint8_t bit2mask_lt[]; +#undef BITMASK8 +#define BITMASK8(bitnr) \ + (__builtin_constant_p(bitnr) ? (1<<(bitnr)) : \ + pgm_read_byte(&bit2mask_lt[(bitnr)])) + + #endif /* UTIL_H_ */ diff --git a/pressure_control/firmware/valves.c b/pressure_control/firmware/valves.c index 700760a..8f9f2de 100644 --- a/pressure_control/firmware/valves.c +++ b/pressure_control/firmware/valves.c @@ -25,7 +25,7 @@ #include -/*** Valve interface definitions ***/ +/*** Valve interface definitions ***///XXX #define VALVE_DDR DDRD #define VALVE_PORT PORTD #define VALVE0_14 6 /* Pin for valve-0 position 14 */ @@ -33,102 +33,89 @@ #define VALVE1_14 4 /* Pin for valve-1 position 14 */ #define VALVE1_12 5 /* Pin for valve-1 position 12 */ +#define MMIO8(mem_addr) _MMIO_BYTE(mem_addr) -static uint8_t current_global_state = 0xFF; -static bool need_switch_to_idle; -static jiffies_t switch_to_idle_time; - - -void valve0_switch(uint8_t state) +void valve0_switch(struct valves *v, uint8_t state) { - VALVE_PORT &= ~((1 << VALVE0_12) | (1 << VALVE0_14)); + MMIO8(v->port) &= ~(BITMASK8(v->bit_0_12) | BITMASK8(v->bit_0_14)); if (state == VALVE_STATE_12) - VALVE_PORT |= (1 << VALVE0_12); + MMIO8(v->port) |= BITMASK8(v->bit_0_12); else if (state == VALVE_STATE_14) - VALVE_PORT |= (1 << VALVE0_14); + MMIO8(v->port) |= BITMASK8(v->bit_0_14); } -void valve1_switch(uint8_t state) +void valve1_switch(struct valves *v, uint8_t state) { - VALVE_PORT &= ~((1 << VALVE1_12) | (1 << VALVE1_14)); + MMIO8(v->port) &= ~(BITMASK8(v->bit_1_12) | BITMASK8(v->bit_1_14)); if (state == VALVE_STATE_12) - VALVE_PORT |= (1 << VALVE1_12); + MMIO8(v->port) |= BITMASK8(v->bit_1_12); else if (state == VALVE_STATE_14) - VALVE_PORT |= (1 << VALVE1_14); + MMIO8(v->port) |= BITMASK8(v->bit_1_14); } -void valves_global_switch(uint8_t state) +void valves_global_switch(struct valves *v, uint8_t state) { - if (state != current_global_state) - __valves_global_switch(state); + if (state != v->current_global_state) + __valves_global_switch(v, state); } -void __valves_global_switch(uint8_t state) +void __valves_global_switch(struct valves *v, uint8_t state) { switch (state) { case VALVES_IDLE: - valve0_switch(VALVE_STATE_12); - valve1_switch(VALVE_STATE_12); + valve0_switch(v, VALVE_STATE_12); + valve1_switch(v, VALVE_STATE_12); break; case VALVES_FLOW_IN: - valve1_switch(VALVE_STATE_12); - valve0_switch(VALVE_STATE_14); + valve1_switch(v, VALVE_STATE_12); + valve0_switch(v, VALVE_STATE_14); break; case VALVES_FLOW_OUT: - valve0_switch(VALVE_STATE_12); - valve1_switch(VALVE_STATE_14); + valve0_switch(v, VALVE_STATE_12); + valve1_switch(v, VALVE_STATE_14); break; } - switch_to_idle_time = get_jiffies() + msec_to_jiffies(VALVE_TOGGLE_MSEC); - need_switch_to_idle = 1; - current_global_state = state; -} - -void valves_disarm_auto_idle(void) -{ - need_switch_to_idle = 0; + v->switch_to_idle_time = get_jiffies() + msec_to_jiffies(VALVE_TOGGLE_MSEC); + v->need_switch_to_idle = 1; + v->current_global_state = state; } -void valves_work(void) +void valves_work(struct valves *v) { - if (need_switch_to_idle && - time_after(get_jiffies(), switch_to_idle_time)) { - need_switch_to_idle = 0; - valve0_switch(VALVE_STATE_IDLE); - valve1_switch(VALVE_STATE_IDLE); + if (v->need_switch_to_idle && + time_after(get_jiffies(), v->switch_to_idle_time)) { + v->need_switch_to_idle = 0; + valve0_switch(v, VALVE_STATE_IDLE); + valve1_switch(v, VALVE_STATE_IDLE); } } -uint8_t valves_get_global_state(void) -{ - return current_global_state; -} - -static inline void valves_ddr_setup(void) +static inline void valves_ddr_setup(struct valves *v) { - VALVE_DDR |= (1 << VALVE0_12) | (1 << VALVE0_14) | - (1 << VALVE1_12) | (1 << VALVE1_14); + MMIO8(v->ddr) |= BITMASK8(v->bit_0_12) | BITMASK8(v->bit_0_14) | + BITMASK8(v->bit_1_12) | BITMASK8(v->bit_1_14); } -void valves_shutdown(void) +void valves_shutdown(struct valves *v) { - __valves_global_switch(VALVES_FLOW_OUT); - valve_wait_toggle(); - valve0_switch(VALVE_STATE_IDLE); - valve1_switch(VALVE_STATE_IDLE); + __valves_global_switch(v, VALVES_FLOW_OUT); + valve_wait_toggle(v); + valve0_switch(v, VALVE_STATE_IDLE); + valve1_switch(v, VALVE_STATE_IDLE); } -void valves_emergency_state(void) +void valves_emergency_state(struct valves *v) { - valves_ddr_setup(); - __valves_global_switch(VALVES_IDLE); - valve_wait_toggle(); - valve0_switch(VALVE_STATE_IDLE); - valve1_switch(VALVE_STATE_IDLE); + valves_ddr_setup(v); + __valves_global_switch(v, VALVES_IDLE); + valve_wait_toggle(v); + valve0_switch(v, VALVE_STATE_IDLE); + valve1_switch(v, VALVE_STATE_IDLE); } -void valves_init(void) +void valves_init(struct valves *v) { - valves_ddr_setup(); - __valves_global_switch(VALVES_IDLE); + v->current_global_state = 0xFF; + valves_ddr_setup(v); + __valves_global_switch(v, VALVES_IDLE); } diff --git a/pressure_control/firmware/valves.h b/pressure_control/firmware/valves.h index b2df104..11ec6db 100644 --- a/pressure_control/firmware/valves.h +++ b/pressure_control/firmware/valves.h @@ -2,6 +2,7 @@ #define VALVES_H_ #include "util.h" +#include "main.h" #include @@ -20,24 +21,55 @@ enum valve_state { VALVE_STATE_14, }; +struct valves { + uint16_t ddr; /* DDRx */ + uint16_t port; /* PORTx */ + uint8_t bit_0_14; /* Valve 0: Pin for valve position 14 */ + uint8_t bit_0_12; /* Valve 0: Pin for valve position 12 */ + uint8_t bit_1_14; /* Valve 1: Pin for valve position 14 */ + uint8_t bit_1_12; /* Valve 1: Pin for valve position 12 */ + + uint8_t current_global_state; /* enum valves_global_state */ + bool need_switch_to_idle; /* Need transition to VALVE_STATE_IDLE. */ + jiffies_t switch_to_idle_time; /* Deadline for VALVE_STATE_IDLE transition. */ +}; + +#define DEFINE_VALVE(name, portid, bit0_14, bit0_12, bit1_14, bit1_12) \ + struct valves name = { \ + .ddr = _SFR_ADDR(DDR##portid), \ + .port = _SFR_ADDR(PORT##portid), \ + .bit_0_14 = bit0_14, \ + .bit_0_12 = bit0_12, \ + .bit_1_14 = bit1_14, \ + .bit_1_12 = bit1_12, \ + } + #define VALVE_TOGGLE_MSEC 10 /* Wait for the valve to toggle from one position to another. */ -static inline void valve_wait_toggle(void) +static inline void valve_wait_toggle(struct valves *v) { mdelay(VALVE_TOGGLE_MSEC); } -void valves_init(void); -void valves_work(void); -void valves_emergency_state(void); -void valves_shutdown(void); -void valves_global_switch(uint8_t global_state); -void __valves_global_switch(uint8_t global_state); -void valves_disarm_auto_idle(void); -uint8_t valves_get_global_state(void); - -void valve0_switch(uint8_t state); -void valve1_switch(uint8_t state); +void valves_init(struct valves *v); +void valves_work(struct valves *v); +void valves_emergency_state(struct valves *v); +void valves_shutdown(struct valves *v); +void valves_global_switch(struct valves *v, uint8_t global_state); +void __valves_global_switch(struct valves *v, uint8_t global_state); + +static inline void valves_disarm_auto_idle(struct valves *v) +{ + v->need_switch_to_idle = 0; +} + +static inline uint8_t valves_get_global_state(struct valves *v) +{ + return v->current_global_state; +} + +void valve0_switch(struct valves *v, uint8_t state); +void valve1_switch(struct valves *v, uint8_t state); #endif /* VALVES_H_ */ -- cgit v1.2.3