diff options
| author | Keith Packard <keithp@keithp.com> | 2013-05-13 22:34:19 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2013-06-09 12:14:11 -0700 | 
| commit | 72b6c699d355fcd41addb9919d846e63105b9db7 (patch) | |
| tree | e80c32df0eaa776db2b01eccc91bbba15b8d2499 /src/drivers/ao_quadrature.c | |
| parent | 47b7e1d819e48aaebf6ffda49effbee041ce8750 (diff) | |
altos: Add debounce helper. Use in button and quadrature drivers for TeleLCO
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/drivers/ao_quadrature.c')
| -rw-r--r-- | src/drivers/ao_quadrature.c | 108 | 
1 files changed, 77 insertions, 31 deletions
diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 6cc2467a..cfa58da6 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -18,12 +18,14 @@  #include <ao.h>  #include <ao_quadrature.h>  #include <ao_exti.h> -#if AO_EVENT +#include <ao_debounce.h>  #include <ao_event.h> -#define ao_quadrature_queue(q)	ao_event_put_isr(AO_EVENT_QUADRATURE, q, ao_quadrature_count[q]) -#else -#define ao_quadrature_queue(q) -#endif + +#define AO_QUADRATURE_DEBOUNCE_HOLD	3 + +static __xdata struct ao_debounce ao_quadrature_debounce[AO_QUADRATURE_COUNT]; + +#define debounce_id(d)	((d) - ao_quadrature_debounce)  __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; @@ -35,41 +37,77 @@ static uint8_t	ao_quadrature_state[AO_QUADRATURE_COUNT];  #define port(q)	AO_QUADRATURE_ ## q ## _PORT  #define bita(q) AO_QUADRATURE_ ## q ## _A  #define bitb(q) AO_QUADRATURE_ ## q ## _B +#define pina(q) AO_QUADRATURE_ ## q ## _A ## _PIN +#define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN -#define ao_quadrature_update(q) do {					\ -		ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); \ -		ao_quadrature_state[q] |= ao_gpio_get(port(q), bita(q), 0); \ -		ao_quadrature_state[q] |= ao_gpio_get(port(q), bitb(q), 0) << 1; \ -	} while (0) -	 +#define q_case(q) case q: v = (!ao_gpio_get(port(q), bita(q), pina(q))) | ((!ao_gpio_get(port(q), bitb(q), pinb(q))) << 1); break -static void -ao_quadrature_isr(void) -{ -	uint8_t	q; +uint8_t quad_raw[64]; +uint8_t quad_r; + +static uint8_t +_ao_quadrature_get(struct ao_debounce *debounce) { +	uint8_t	q = debounce_id(debounce); +	uint8_t v = 0; + +	switch (q) {  #if AO_QUADRATURE_COUNT > 0 -	ao_quadrature_update(0); +		q_case(0);  #endif  #if AO_QUADRATURE_COUNT > 1 -	ao_quadrature_update(1); +		q_case(1);  #endif +	} +	if (q == 0) { +		quad_raw[quad_r] = v; +		quad_r = (quad_r + 1) & 63; +	} +	return v; +} -	for (q = 0; q < AO_QUADRATURE_COUNT; q++) { -		switch (ao_quadrature_state[q]) { -		case STATE(0, 1, 0, 0): -			ao_quadrature_count[q]++; -			break; -		case STATE(1, 0, 0, 0): -			ao_quadrature_count[q]--; -			break; -		default: -			continue; -		} -		ao_quadrature_queue(q); -		ao_wakeup(&ao_quadrature_count[q]); +static void +_ao_quadrature_queue(uint8_t q, int8_t step) +{ +	ao_quadrature_count[q] += step; +#if AO_EVENT +	ao_event_put_isr(AO_EVENT_QUADRATURE, q, step); +#endif +	ao_wakeup(&ao_quadrature_count[q]); +} + +uint8_t quad_history[64]; +uint8_t quad_h; + +static void +_ao_quadrature_set(struct ao_debounce *debounce, uint8_t value) { +	uint8_t q = debounce_id(debounce); +	 +	ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); +	ao_quadrature_state[q] |= value; + +	if (q == 0) { +		quad_history[quad_h] = ao_quadrature_state[0]; +		quad_h = (quad_h + 1) & 63; +	} + +	switch (ao_quadrature_state[q]) { +	case STATE(0, 1, 0, 0): +		_ao_quadrature_queue(q, 1); +		break; +	case STATE(1, 0, 0, 0): +		_ao_quadrature_queue(q, -1); +		break;  	}  } +static void +ao_quadrature_isr(void) +{ +	uint8_t	q; +	for (q = 0; q < AO_QUADRATURE_COUNT; q++) +		_ao_debounce_start(&ao_quadrature_debounce[q]); +} +  int32_t  ao_quadrature_poll(uint8_t q)  { @@ -107,9 +145,16 @@ static const struct ao_cmds ao_quadrature_cmds[] = {  	{ 0, NULL }  }; +static void +ao_quadrature_debounce_init(struct ao_debounce *debounce) { +	debounce->hold = AO_QUADRATURE_DEBOUNCE_HOLD; +	debounce->_get = _ao_quadrature_get; +	debounce->_set = _ao_quadrature_set; +} +  #define init(q) do {							\  		ao_enable_port(port(q));				\ -									\ +		ao_quadrature_debounce_init(&ao_quadrature_debounce[q]); \  		ao_exti_setup(port(q), bita(q),				\  			      AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \  			      ao_quadrature_isr);			\ @@ -124,6 +169,7 @@ static const struct ao_cmds ao_quadrature_cmds[] = {  void  ao_quadrature_init(void)  { +	ao_debounce_init();  #if AO_QUADRATURE_COUNT > 0  	init(0);  #endif  | 
