summaryrefslogtreecommitdiffstats
path: root/pressure_control/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'pressure_control/firmware')
-rw-r--r--pressure_control/firmware/main.c36
-rw-r--r--pressure_control/firmware/main.h6
-rw-r--r--pressure_control/firmware/remote.c16
-rw-r--r--pressure_control/firmware/sensor.c53
-rw-r--r--pressure_control/firmware/sensor.h29
-rw-r--r--pressure_control/firmware/util.c5
-rw-r--r--pressure_control/firmware/util.h10
-rw-r--r--pressure_control/firmware/valves.c107
-rw-r--r--pressure_control/firmware/valves.h56
9 files changed, 187 insertions, 131 deletions
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 <mb@bu3sch.de>
+ * Copyright (C) 2008-2009 Michael Buesch <mb@bu3sch.de>
*
* 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<<MUX0), 245, 4400, 10000);
+
/* EEPROM contents */
static struct eeprom_data EEMEM eeprom = {
@@ -100,8 +105,8 @@ void get_pressure_state(struct pressure_state *ret)
/* Sensor measurement completed.
* Called in IRQ context. */
-void sensor_result(uint16_t mbar)
-{
+void sensor_result(struct sensor *s, uint16_t mbar)
+{//XXX
/* Defer processing of the value to the mainloop, so we can do it with
* interrupts enabled. */
state.mbar = mbar;
@@ -148,15 +153,15 @@ static void check_pressure(void)
offset = (int32_t)state.mbar - (int32_t)cfg.desired;
abs_offset = abs(offset);
is_too_big = (offset >= 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 <avr/interrupt.h>
-/* 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 <stdint.h>
-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 <avr/sleep.h>
+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 <avr/io.h>
-/*** 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 <stdint.h>
@@ -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_ */
bues.ch cgit interface