diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/ao.h | 1 | ||||
| -rw-r--r-- | src/core/ao_debounce.c | 163 | ||||
| -rw-r--r-- | src/core/ao_debounce.h | 26 | ||||
| -rw-r--r-- | src/drivers/ao_button.c | 7 | ||||
| -rw-r--r-- | src/drivers/ao_quadrature.c | 130 | ||||
| -rw-r--r-- | src/stm/ao_debounce.c | 187 | ||||
| -rw-r--r-- | src/stm/ao_fast_timer.c | 120 | ||||
| -rw-r--r-- | src/stm/ao_fast_timer.h | 34 | ||||
| -rw-r--r-- | src/stm/stm32l.h | 5 | ||||
| -rw-r--r-- | src/telelco-v0.2/Makefile | 1 | ||||
| -rw-r--r-- | src/telelco-v0.2/ao_pins.h | 1 | 
11 files changed, 411 insertions, 264 deletions
| diff --git a/src/core/ao.h b/src/core/ao.h index 0886260f..caa0ec19 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -75,6 +75,7 @@ typedef AO_PORT_TYPE ao_port_t;  #define AO_PANIC_CRASH		14	/* Processor crashed */  #define AO_PANIC_BUFIO		15	/* Mis-using bufio API */  #define AO_PANIC_EXTI		16	/* Mis-using exti API */ +#define AO_PANIC_FAST_TIMER	17	/* Mis-using fast timer API */  #define AO_PANIC_SELF_TEST_CC1120	0x40 | 1	/* Self test failure */  #define AO_PANIC_SELF_TEST_HMC5883	0x40 | 2	/* Self test failure */  #define AO_PANIC_SELF_TEST_MPU6000	0x40 | 3	/* Self test failure */ diff --git a/src/core/ao_debounce.c b/src/core/ao_debounce.c new file mode 100644 index 00000000..b9d67729 --- /dev/null +++ b/src/core/ao_debounce.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_debounce.h> +#include <ao_fast_timer.h> + +static uint8_t			ao_debounce_initialized; +static uint8_t			ao_debounce_running; +static struct ao_debounce	*ao_debounce; + +static uint8_t	values[64]; +static uint8_t	n; + +#define d_step(n)	(((n) + 1) & 63) + +static void +_ao_debounce_set(struct ao_debounce *debounce, uint8_t value) +{ +	if (value != debounce->value) { +		values[n] = value; +		n = (n + 1) & 63; +		debounce->value = value; +		debounce->_set(debounce, value); +	} +	_ao_debounce_stop(debounce); +} + +void +ao_debounce_dump(void) +{ +	uint8_t	s; + +	for (s = 0; s < n; s++) { +		printf ("%d: %d\n", +			s, values[s]); +	} +	n = 0; +} + +/* + * Get the current value, set the result when we've + * reached the debounce count limit + */ +static void +_ao_debounce_check(struct ao_debounce *debounce) +{ +	uint8_t	next = debounce->_get(debounce); + +	if (next == debounce->current) { +		if (debounce->count < debounce->hold) { +			if (++debounce->count == debounce->hold) +				_ao_debounce_set(debounce, debounce->current); +		} +	} else { +		debounce->count = 0; +		debounce->current = next; +	} +} + +static void +_ao_debounce_isr(void) +{ +	struct ao_debounce *debounce, *next; + +	for (debounce = ao_debounce; debounce; debounce = next) { +		next = debounce->next; +		_ao_debounce_check(debounce); +	} +} + +static void +ao_debounce_on(void) +{ +	ao_fast_timer_on(_ao_debounce_isr); +} + +static void +ao_debounce_off(void) +{ +	ao_fast_timer_off(_ao_debounce_isr); +} + +/* + * Start monitoring one pin + */ +void +_ao_debounce_start(struct ao_debounce *debounce) +{ +	uint32_t	m; + +	m = ao_arch_irqsave(); +	if (!debounce->running) { +		debounce->running = 1; + +		/* Reset the counter */ +		debounce->count = 0; + +		/* Link into list */ +		debounce->next = ao_debounce; +		ao_debounce = debounce; + +		/* Make sure the timer is running */ +		if (!ao_debounce_running++) +			ao_debounce_on(); + +		/* And go check the current value */ +		_ao_debounce_check(debounce); +	} +	ao_arch_irqrestore(m); +} + +/* + * Stop monitoring one pin + */ +void +_ao_debounce_stop(struct ao_debounce *debounce) +{ +	struct ao_debounce **prev; +	uint32_t m; + +	m = ao_arch_irqsave(); +	if (debounce->running) { +		debounce->running = 0; + +		/* Unlink */ +		for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) { +			if (*prev == debounce) { +				*prev = debounce->next; +				break; +			} +		} +		debounce->next = NULL; + +		/* Turn off the timer if possible */ +		if (!--ao_debounce_running) +			ao_debounce_off(); +	} +	ao_arch_irqrestore(m); +} + +void +ao_debounce_init(void) +{ +	if (ao_debounce_initialized) +		return; +	ao_debounce_initialized = 1; +	ao_fast_timer_init(); +} diff --git a/src/core/ao_debounce.h b/src/core/ao_debounce.h index ebe290e1..19c620f5 100644 --- a/src/core/ao_debounce.h +++ b/src/core/ao_debounce.h @@ -22,13 +22,16 @@ struct ao_debounce {  	struct ao_debounce	*next;  	/* time that pin value must be stable before accepting */ -	int8_t			hold; +	uint8_t			hold;  	/* last value reported to app; don't report it twice */  	uint8_t			value; +	/* current value received from pins */ +	uint8_t			current; +  	/* current count of intervals pin value has been stable */ -	int8_t			count; +	uint8_t			count;  	/* This pin is running */  	uint8_t			running; @@ -40,6 +43,22 @@ struct ao_debounce {  	void 			(*_set)(struct ao_debounce *debounce, uint8_t value);  }; +static inline void +ao_debounce_config(struct ao_debounce *debounce, +		   uint8_t (*_get)(struct ao_debounce *debounce), +		   void (*_set)(struct ao_debounce *debounce, uint8_t value), +		   uint8_t hold) +{ +	debounce->next = 0; +	debounce->hold = hold; +	debounce->value = 0xff; +	debounce->current = 0xff; +	debounce->count = 0; +	debounce->running = 0; +	debounce->_get = _get; +	debounce->_set = _set; +} +  void  _ao_debounce_start(struct ao_debounce *debounce); @@ -49,4 +68,7 @@ _ao_debounce_stop(struct ao_debounce *debounce);  void  ao_debounce_init(void); +void +ao_debounce_dump(void); +  #endif /* _AO_DEBOUNCE_H_ */ diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index 7b1fb530..25c0cd5c 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -74,9 +74,10 @@ _ao_button_set(struct ao_debounce *debounce, uint8_t value)  static void  ao_button_debounce_init(struct ao_debounce *debounce) { -	debounce->hold = AO_BUTTON_DEBOUNCE_HOLD; -	debounce->_get = _ao_button_get; -	debounce->_set = _ao_button_set; +	ao_debounce_config(debounce, +			   _ao_button_get, +			   _ao_button_set, +			   AO_BUTTON_DEBOUNCE_HOLD);  }  static void diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index cfa58da6..d07488d0 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -18,18 +18,12 @@  #include <ao.h>  #include <ao_quadrature.h>  #include <ao_exti.h> -#include <ao_debounce.h> +#include <ao_fast_timer.h>  #include <ao_event.h> -#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]; -  static uint8_t	ao_quadrature_state[AO_QUADRATURE_COUNT]; +static int8_t	ao_quadrature_raw[AO_QUADRATURE_COUNT];  #define BIT(a,b)	((a) | ((b) << 1))  #define STATE(old_a, old_b, new_a, new_b)	(((BIT(old_a, old_b) << 2) | BIT(new_a, new_b))) @@ -39,32 +33,17 @@ static uint8_t	ao_quadrature_state[AO_QUADRATURE_COUNT];  #define bitb(q) AO_QUADRATURE_ ## q ## _B  #define pina(q) AO_QUADRATURE_ ## q ## _A ## _PIN  #define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN +#define isr(q)  ao_quadrature_isr_ ## q -#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 - -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; +static inline uint16_t +ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b) { +	uint16_t	v = stm_gpio_get_all(gpio); -	switch (q) { -#if AO_QUADRATURE_COUNT > 0 -		q_case(0); -#endif -#if AO_QUADRATURE_COUNT > 1 -		q_case(1); -#endif -	} -	if (q == 0) { -		quad_raw[quad_r] = v; -		quad_r = (quad_r + 1) & 63; -	} -	return v; +	return ~((((v >> pin_a) & 1) | (((v >> pin_b) & 1) << 1))) & 3;  } +#define _ao_quadrature_get(q)	ao_quadrature_read(port(q), bita(q), bitb(q)) +  static void  _ao_quadrature_queue(uint8_t q, int8_t step)  { @@ -75,37 +54,51 @@ _ao_quadrature_queue(uint8_t q, int8_t step)  	ao_wakeup(&ao_quadrature_count[q]);  } -uint8_t quad_history[64]; -uint8_t quad_h; +static const int8_t	step[16] = { +	[STATE(0,0,0,0)] = 0, +	[STATE(0,0,0,1)] = -1, +	[STATE(0,0,1,0)] = 1, +	[STATE(0,0,1,1)] = 0, +	[STATE(0,1,0,0)] = 1, +	[STATE(0,1,1,0)] = 0, +	[STATE(0,1,1,1)] = -1, +	[STATE(1,0,0,0)] = -1, +	[STATE(1,0,0,1)] = 0, +	[STATE(1,0,1,0)] = 0, +	[STATE(1,0,1,1)] = 1, +	[STATE(1,1,0,0)] = 0, +	[STATE(1,1,0,1)] = 1, +	[STATE(1,1,1,0)] = -1, +	[STATE(1,1,1,1)] = 0 +};  static void -_ao_quadrature_set(struct ao_debounce *debounce, uint8_t value) { -	uint8_t q = debounce_id(debounce); +_ao_quadrature_set(uint8_t q, uint8_t value) { +	uint8_t v; -	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; -	} +	v = ao_quadrature_state[q] & 3; +	value = value & 3; -	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; +	if (v == value) +		return; +	 +	ao_quadrature_state[q] = (v << 2) | value; + +	ao_quadrature_raw[q] += step[ao_quadrature_state[q]]; +	if (value == 0) { +		if (ao_quadrature_raw[q] == 4) +			_ao_quadrature_queue(q, 1); +		else if (ao_quadrature_raw[q] == -4) +			_ao_quadrature_queue(q, -1); +		ao_quadrature_raw[q] = 0;  	}  }  static void  ao_quadrature_isr(void)  { -	uint8_t	q; -	for (q = 0; q < AO_QUADRATURE_COUNT; q++) -		_ao_debounce_start(&ao_quadrature_debounce[q]); +	_ao_quadrature_set(0, _ao_quadrature_get(0)); +	_ao_quadrature_set(1, _ao_quadrature_get(1));  }  int32_t @@ -130,6 +123,15 @@ ao_quadrature_test(void)  	ao_cmd_decimal();  	q = ao_cmd_lex_i; +	if (q >= AO_QUADRATURE_COUNT) { +		ao_cmd_status = ao_cmd_syntax_error; +		return; +	} +	printf ("count %d state %x raw %d\n", +		ao_quadrature_count[q], +		ao_quadrature_state[q], +		ao_quadrature_raw[q]); +#if 0  	for (;;) {  		int32_t	c;  		flush(); @@ -138,6 +140,7 @@ ao_quadrature_test(void)  		if (c == 100)  			break;  	} +#endif  }  static const struct ao_cmds ao_quadrature_cmds[] = { @@ -145,36 +148,21 @@ 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);			\ -		ao_exti_enable(port(q), bita(q));			\ -									\ -		ao_exti_setup(port(q), bitb(q),				\ -			      AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ -			      ao_quadrature_isr);			\ -		ao_exti_enable(port(q), bitb(q));			\ +#define init(q) do {					\ +		ao_enable_input(port(q), bita(q), 0);	\ +		ao_enable_input(port(q), bitb(q), 0);	\  	} while (0)  void  ao_quadrature_init(void)  { -	ao_debounce_init();  #if AO_QUADRATURE_COUNT > 0  	init(0);  #endif  #if AO_QUADRATURE_COUNT > 1  	init(1);  #endif +	ao_fast_timer_init(); +	ao_fast_timer_on(ao_quadrature_isr);  	ao_cmd_register(&ao_quadrature_cmds[0]);  } diff --git a/src/stm/ao_debounce.c b/src/stm/ao_debounce.c deleted file mode 100644 index 22cdf230..00000000 --- a/src/stm/ao_debounce.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright © 2013 Keith Packard <keithp@keithp.com> - * - * 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 - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include <ao.h> -#include <ao_debounce.h> - -static uint8_t			ao_debounce_initialized; -static uint8_t			ao_debounce_running; -static struct ao_debounce	*ao_debounce; - -static void -ao_debounce_on(void) -{ -	stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | -			(0 << STM_TIM67_CR1_OPM) | -			(1 << STM_TIM67_CR1_URS) | -			(0 << STM_TIM67_CR1_UDIS) | -			(1 << STM_TIM67_CR1_CEN)); -} - -static void -ao_debounce_off(void) -{ -	stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | -			(0 << STM_TIM67_CR1_OPM) | -			(1 << STM_TIM67_CR1_URS) | -			(0 << STM_TIM67_CR1_UDIS) | -			(0 << STM_TIM67_CR1_CEN)); -} - -static void -_ao_debounce_set(struct ao_debounce *debounce, uint8_t value) -{ -	if (value != debounce->value) { -		debounce->value = value; -		debounce->_set(debounce, value); -	} -	_ao_debounce_stop(debounce); -} - -/* - * Get the current value, set the result when we've - * reached the debounce count limit - */ -static void -_ao_debounce_check(struct ao_debounce *debounce) -{ -	if (debounce->_get(debounce)) { -		if (debounce->count < 0) -			debounce->count = 0; -		if (debounce->count < debounce->hold) { -			if (++debounce->count == debounce->hold) -				_ao_debounce_set(debounce, 1); -		} -	} else { -		if (debounce->count > 0) -			debounce->count = 0; -		if (debounce->count > -debounce->hold) { -			if (--debounce->count == -debounce->hold) -				_ao_debounce_set(debounce, 0); -		} -	} -} - -/* - * Start monitoring one pin - */ -void -_ao_debounce_start(struct ao_debounce *debounce) -{ -	if (debounce->running) -		return; -	debounce->running = 1; - -	/* Reset the counter */ -	debounce->count = 0; - -	/* Link into list */ -	debounce->next = ao_debounce; -	ao_debounce = debounce; - -	/* Make sure the timer is running */ -	if (!ao_debounce_running++) -		ao_debounce_on(); - -	/* And go check the current value */ -	_ao_debounce_check(debounce); -} - -/* - * Stop monitoring one pin - */ -void -_ao_debounce_stop(struct ao_debounce *debounce) -{ -	struct ao_debounce **prev; -	if (!debounce->running) -		return; - -	debounce->running = 0; - -	/* Unlink */ -	for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) { -		if (*prev == debounce) { -			*prev = debounce->next; -			break; -		} -	} -	debounce->next = NULL; - -	/* Turn off the timer if possible */ -	if (!--ao_debounce_running) -		ao_debounce_off(); -} - -void stm_tim6_isr(void) -{ -	struct ao_debounce	*debounce, *next; -	if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { -		stm_tim6.sr = 0; - -		/* Walk the current list, allowing the current -		 * object to be removed from the list -		 */ -		for (debounce = ao_debounce; debounce; debounce = next) { -			next = debounce->next; -			_ao_debounce_check(debounce); -		} -	} -} - -/* - * According to the STM clock-configuration, timers run - * twice as fast as the APB1 clock *if* the APB1 prescaler - * is greater than 1. - */ - -#if AO_APB1_PRESCALER > 1 -#define TIMER_23467_SCALER 2 -#else -#define TIMER_23467_SCALER 1 -#endif - -#define TIMER_100kHz	((AO_PCLK1 * TIMER_23467_SCALER) / 100000) - -void -ao_debounce_init(void) -{ -	if (ao_debounce_initialized) -		return; -	ao_debounce_initialized = 1; - -	stm_nvic_set_enable(STM_ISR_TIM6_POS); -	stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); - -	/* Turn on timer 6 */ -	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - -	stm_tim6.psc = TIMER_100kHz; -	stm_tim6.arr = 9; -	stm_tim6.cnt = 0; - -	/* Enable update interrupt */ -	stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); - -	/* Poke timer to reload values */ -	stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); - -	stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); - -	/* And turn it off (for now) */ -	ao_debounce_off(); -} diff --git a/src/stm/ao_fast_timer.c b/src/stm/ao_fast_timer.c new file mode 100644 index 00000000..d61b40c9 --- /dev/null +++ b/src/stm/ao_fast_timer.c @@ -0,0 +1,120 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <ao.h> +#include <ao_fast_timer.h> + +static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void); +static uint8_t ao_fast_timer_count; +static uint8_t ao_fast_timer_users; + +static void +ao_fast_timer_enable(void) +{ +	stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | +			(0 << STM_TIM67_CR1_OPM) | +			(1 << STM_TIM67_CR1_URS) | +			(0 << STM_TIM67_CR1_UDIS) | +			(1 << STM_TIM67_CR1_CEN)); +} + +static void +ao_fast_timer_disable(void) +{ +	stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | +			(0 << STM_TIM67_CR1_OPM) | +			(1 << STM_TIM67_CR1_URS) | +			(0 << STM_TIM67_CR1_UDIS) | +			(0 << STM_TIM67_CR1_CEN)); +} + +void +ao_fast_timer_on(void (*callback)(void)) +{ +	ao_fast_timer_callback[ao_fast_timer_count] = callback; +	if (!ao_fast_timer_count++) +		ao_fast_timer_enable(); +} + +void +ao_fast_timer_off(void (*callback)(void)) +{ +	uint8_t	n; + +	for (n = 0; n < ao_fast_timer_count; n++) +		if (ao_fast_timer_callback[n] == callback) { +			for (; n < ao_fast_timer_count-1; n++) { +				ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1]; +			} +			if (!--ao_fast_timer_count) +				ao_fast_timer_disable(); +			break; +		} +} + +void stm_tim6_isr(void) +{ +	uint8_t	i; +	if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { +		stm_tim6.sr = 0; + +		for (i = 0; i < ao_fast_timer_count; i++) +			(*ao_fast_timer_callback[i])(); +	} +} + +/* + * According to the STM clock-configuration, timers run + * twice as fast as the APB1 clock *if* the APB1 prescaler + * is greater than 1. + */ + +#if AO_APB1_PRESCALER > 1 +#define TIMER_23467_SCALER 2 +#else +#define TIMER_23467_SCALER 1 +#endif + +#define TIMER_10kHz	((AO_PCLK1 * TIMER_23467_SCALER) / 10000) + +void +ao_fast_timer_init(void) +{ +	if (!ao_fast_timer_users) { +		stm_nvic_set_enable(STM_ISR_TIM6_POS); +		stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); + +		/* Turn on timer 6 */ +		stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + +		stm_tim6.psc = TIMER_10kHz; +		stm_tim6.arr = 9; +		stm_tim6.cnt = 0; + +		/* Enable update interrupt */ +		stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + +		/* Poke timer to reload values */ +		stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + +		stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); +		ao_fast_timer_disable(); +	} +	if (ao_fast_timer_users == AO_FAST_TIMER_MAX) +		ao_panic(AO_PANIC_FAST_TIMER); +	ao_fast_timer_users++; +} + diff --git a/src/stm/ao_fast_timer.h b/src/stm/ao_fast_timer.h new file mode 100644 index 00000000..90fb3930 --- /dev/null +++ b/src/stm/ao_fast_timer.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FAST_TIMER_H_ +#define _AO_FAST_TIMER_H_ + +void +ao_fast_timer_init(void); + +#ifndef AO_FAST_TIMER_MAX +#define AO_FAST_TIMER_MAX	2 +#endif + +void +ao_fast_timer_on(void (*callback)(void)); + +void +ao_fast_timer_off(void (*callback)(void)); + +#endif /* _AO_FAST_TIMER_H_ */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 63bde0f8..1868468f 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -171,6 +171,11 @@ stm_gpio_get(struct stm_gpio *gpio, int pin) {  	return (gpio->idr >> pin) & 1;  } +static inline uint16_t +stm_gpio_get_all(struct stm_gpio *gpio) { +	return gpio->idr; +} +  extern struct stm_gpio stm_gpioa;  extern struct stm_gpio stm_gpiob;  extern struct stm_gpio stm_gpioc; diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 42a5a7ee..f78ca9e2 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -50,6 +50,7 @@ ALTOS_SRC = \  	ao_beep_stm.c \  	ao_storage.c \  	ao_eeprom_stm.c \ +	ao_fast_timer.c \  	ao_lcd_stm.c \  	ao_usb_stm.c \  	ao_exti_stm.c \ diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index 07ea1b45..d86782f3 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -235,7 +235,6 @@   */  #define AO_QUADRATURE_COUNT	2 -#define AO_QUADRATURE_MODE	0  #define AO_QUADRATURE_0_PORT	&stm_gpioe  #define AO_QUADRATURE_0_A	3 | 
