From aa5604d118bc89e85c8230562080c034bfc9df17 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 3 May 2009 12:35:53 +0200 Subject: pressure-control: Implement idle-release of valves through timer. Signed-off-by: Michael Buesch --- pressure_control/firmware/Makefile | 2 +- pressure_control/firmware/main.c | 56 +++++++++++++++++++++++++------------- pressure_control/firmware/main.h | 21 ++++++++++++++ pressure_control/firmware/remote.c | 13 +++++---- pressure_control/firmware/remote.h | 1 - pressure_control/firmware/valves.c | 25 +++++++++++++---- pressure_control/firmware/valves.h | 5 +++- 7 files changed, 90 insertions(+), 33 deletions(-) (limited to 'pressure_control') diff --git a/pressure_control/firmware/Makefile b/pressure_control/firmware/Makefile index a4d380e..1e965be 100644 --- a/pressure_control/firmware/Makefile +++ b/pressure_control/firmware/Makefile @@ -27,7 +27,7 @@ main.o: util.h calibration.h valves.h sensor.h remote.h main.h util.o: util.h calibration.h -valves.o: util.h valves.h +valves.o: util.h valves.h main.h sensor.o: util.h sensor.h diff --git a/pressure_control/firmware/main.c b/pressure_control/firmware/main.c index a82a503..af779a7 100644 --- a/pressure_control/firmware/main.c +++ b/pressure_control/firmware/main.c @@ -40,6 +40,9 @@ struct eeprom_data { struct pressure_config cfg; /* The pressure state data. */ struct pressure_state state; +/* The 1000Hz jiffies counter */ +static jiffies_t jiffies_counter; + /* EEPROM contents */ static struct eeprom_data EEMEM eeprom = { @@ -106,12 +109,22 @@ void sensor_result(uint16_t mbar) state.needs_checking = 1; } +jiffies_t get_jiffies(void) +{ + uint16_t sreg; + jiffies_t j; + + sreg = irq_disable_save(); + j = jiffies_counter; + irq_restore(sreg); + + return j; +} + /* 1kHz system timer. */ ISR(TIMER1_COMPA_vect) { - if (state.sensor_trigger_cnt > 0) - state.sensor_trigger_cnt--; - remote_1khz_work(); + jiffies_counter++; } void system_timer_init(void) @@ -225,28 +238,33 @@ int main(void) print("Monitoring...\n"); remote_work(); remote_notify_restart(); + sensor_trigger_read(); while (1) { + static jiffies_t next_sensor_trigger; + static bool need_sensor_trigger; + jiffies_t now; + mb(); - if (state.device_enabled) { - if (state.sensor_trigger_cnt == 0) { - /* It's time for triggering another - * sensor measurement. */ - state.sensor_trigger_cnt = -1; - mb(); - sensor_trigger_read(); - } - if (state.needs_checking) { + now = get_jiffies(); + if (state.needs_checking) { + if (state.device_enabled) check_pressure(); - /* Trigger another measurement in - * a few milliseconds. */ - state.sensor_trigger_cnt = 35; - state.needs_checking = 0; - mb(); - } - } else { + /* Trigger another measurement in + * a few milliseconds. */ state.needs_checking = 0; + next_sensor_trigger = now + msec_to_jiffies(35); + mb(); + need_sensor_trigger = 1; + } + if (need_sensor_trigger && + time_after(now, next_sensor_trigger)) { + /* It's time for triggering another + * sensor measurement. */ + need_sensor_trigger = 0; + sensor_trigger_read(); } remote_work(); + valves_work(); wdt_reset(); } } diff --git a/pressure_control/firmware/main.h b/pressure_control/firmware/main.h index edb8694..d8cb6aa 100644 --- a/pressure_control/firmware/main.h +++ b/pressure_control/firmware/main.h @@ -6,6 +6,27 @@ #include +typedef uint16_t jiffies_t; +typedef int16_t s_jiffies_t; + +/* Jiffies timing helpers derived from the Linux Kernel sources. + * These inlines deal with timer wrapping correctly. + * + * time_after(a, b) returns true if the time a is after time b. + * + * Do this with "<0" and ">=0" to only test the sign of the result. A + * good compiler would generate better code (and a really good compiler + * wouldn't care). Gcc is currently neither. + */ +#define time_after(a, b) ((s_jiffies_t)(b) - (s_jiffies_t)(a) < 0) +#define time_before(a, b) time_after(b, a) + +#define JIFFIES_PER_SECOND 1000 +#define msec_to_jiffies(msec) ((jiffies_t)((uint32_t)JIFFIES_PER_SECOND * (uint32_t)(msec) / (uint32_t)1000)) + +jiffies_t get_jiffies(void); + + struct pressure_config { /* Desired pressure in mBar */ uint16_t desired; diff --git a/pressure_control/firmware/remote.c b/pressure_control/firmware/remote.c index f41c9ed..6383339 100644 --- a/pressure_control/firmware/remote.c +++ b/pressure_control/firmware/remote.c @@ -362,6 +362,9 @@ void print_hex(uint8_t number) /* Maintanance work. Called with IRQs enabled. */ void remote_work(void) { + static jiffies_t last_timeout_check; + jiffies_t now = get_jiffies(); + if (rx_msg_valid) { handle_received_message(); mb(); @@ -372,15 +375,13 @@ void remote_work(void) rx_softirq = 0; usart_handle_rx_irq(); } + if (last_timeout_check != now) { + last_timeout_check = now; + usart_rx_timeout_check(); + } sei(); } -/* Maintanance work. Called at a frequency of 1KHz with IRQs disabled. */ -void remote_1khz_work(void) -{ - usart_rx_timeout_check(); -} - void remote_pressure_change_notification(uint16_t mbar) { struct remote_message msg; diff --git a/pressure_control/firmware/remote.h b/pressure_control/firmware/remote.h index 85afd92..709a1f0 100644 --- a/pressure_control/firmware/remote.h +++ b/pressure_control/firmware/remote.h @@ -85,7 +85,6 @@ void remote_pressure_change_notification(uint16_t mbar); void remote_notify_restart(void); void remote_work(void); -void remote_1khz_work(void); void remote_init(void); #endif /* REMOTE_H_ */ diff --git a/pressure_control/firmware/valves.c b/pressure_control/firmware/valves.c index 75d4606..86ea85b 100644 --- a/pressure_control/firmware/valves.c +++ b/pressure_control/firmware/valves.c @@ -20,6 +20,7 @@ #include "valves.h" #include "util.h" +#include "main.h" #include @@ -34,6 +35,8 @@ 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) @@ -56,7 +59,6 @@ void valve1_switch(uint8_t state) void valves_global_switch(uint8_t state) { - if (state == current_global_state) return; current_global_state = state; @@ -65,9 +67,6 @@ void valves_global_switch(uint8_t state) case VALVES_IDLE: valve0_switch(VALVE_STATE_12); valve1_switch(VALVE_STATE_12); - valve_wait_toggle(); - valve0_switch(VALVE_STATE_IDLE); - valve1_switch(VALVE_STATE_IDLE); break; case VALVES_FLOW_IN: valve1_switch(VALVE_STATE_12); @@ -78,6 +77,18 @@ void valves_global_switch(uint8_t state) valve1_switch(VALVE_STATE_14); break; } + switch_to_idle_time = get_jiffies() + msec_to_jiffies(VALVE_TOGGLE_MSEC); + need_switch_to_idle = 1; +} + +void valves_work(void) +{ + 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); + } } uint8_t valves_get_global_state(void) @@ -101,7 +112,11 @@ void valves_shutdown(void) void valves_emergency_state(void) { - valves_init(); + valves_ddr_setup(); + valves_global_switch(VALVES_IDLE); + valve_wait_toggle(); + valve0_switch(VALVE_STATE_IDLE); + valve1_switch(VALVE_STATE_IDLE); } void valves_init(void) diff --git a/pressure_control/firmware/valves.h b/pressure_control/firmware/valves.h index 0929682..1b50b3a 100644 --- a/pressure_control/firmware/valves.h +++ b/pressure_control/firmware/valves.h @@ -20,13 +20,16 @@ enum valve_state { VALVE_STATE_14, }; +#define VALVE_TOGGLE_MSEC 10 + /* Wait for the valve to toggle from one position to another. */ static inline void valve_wait_toggle(void) { - mdelay(10); + 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); -- cgit v1.2.3