diff options
| -rw-r--r-- | src/lpc/ao_exti.h | 47 | ||||
| -rw-r--r-- | src/lpc/ao_exti_lpc.c | 151 | 
2 files changed, 198 insertions, 0 deletions
| diff --git a/src/lpc/ao_exti.h b/src/lpc/ao_exti.h new file mode 100644 index 00000000..cbe63eaa --- /dev/null +++ b/src/lpc/ao_exti.h @@ -0,0 +1,47 @@ +/* + * Copyright © 2012 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_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING	1 +#define AO_EXTI_MODE_FALLING	2 +#define AO_EXTI_MODE_PULL_UP	4 +#define AO_EXTI_MODE_PULL_DOWN	8 +#define AO_EXTI_PRIORITY_LOW	16 +#define AO_EXTI_PRIORITY_MED	0 +#define AO_EXTI_PRIORITY_HIGH	32 + +void +ao_exti_setup(uint8_t gpio, uint8_t pin, uint8_t mode, void (*callback)()); + +void +ao_exti_set_mode(uint8_t gpio, uint8_t pin, uint8_t mode); + +void +ao_exti_set_callback(uint8_t gpio, uint8_t pin, void (*callback)()); + +void +ao_exti_enable(uint8_t gpio, uint8_t pin); + +void +ao_exti_disable(uint8_t gpio, uint8_t pin); + +void +ao_exti_init(void); + +#endif /* _AO_EXTI_H_ */ diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c new file mode 100644 index 00000000..2e42dabb --- /dev/null +++ b/src/lpc/ao_exti_lpc.c @@ -0,0 +1,151 @@ +/* + * Copyright © 2012 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_exti.h> + +#define LPC_NUM_PINS	56 +#define LPC_NUM_PINT	8 + +static void	(*ao_exti_callback[LPC_NUM_PINT])(void); + +static uint8_t	ao_pint_map[LPC_NUM_PINS]; +static uint8_t	ao_pint_mode[LPC_NUM_PINS]; +static uint8_t	ao_pint_inuse; +static uint8_t	ao_pint_enabled; + +static void +ao_exti_isr(uint8_t pint) +{ +	uint8_t	mask = 1 << pint; + +	if (lpc_gpio_pin.ist & mask) { +		lpc_gpio_pin.ist = mask; + +		(*ao_exti_callback) (); +	} +} + +#define pin_isr(n)	void lpc_pin_int ## n ## _isr(void) { ao_exti_isr(n); } +pin_isr(0) +pin_isr(1) +pin_isr(2) +pin_isr(3) +pin_isr(4) +pin_isr(5) +pin_isr(6) +pin_isr(7) + +#define pin_id(port,pin)	((port) * 24 + (pin)); + +void +ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) { +	uint8_t		id = pin_id(port,pin); +	uint8_t	       	pint; +	uint32_t	mask; +	uint8_t		prio; + +	for (pint = 0; pint < LPC_NUM_PINT; pint++) +		if ((ao_pint_inuse & (1 << pint)) == 0) +			break; +	if (pint == LPC_NUM_PINT) +		ao_panic(AO_PANIC_EXTI); + +	mask = (1 << pint); +	ao_pint_inuse |= mask; +	ao_pint_enabled &= ~mask; +	 +	ao_pint_map[id] = pint; +	ao_exti_callback[pin] = callback; + +	/* configure gpio to interrupt routing */ +	lpc_scb.pintsel[pint] = id; + +	ao_enable_input(port, pin, mode); + +	/* Set edge triggered */ +	lpc_gpio_pin.isel &= ~mask; + +	ao_exti_set_mode(port, pin, mode); + +	/* Set interrupt mask and rising/falling mode */ + +	prio = AO_LPC_NVIC_MED_PRIORITY; +	if (mode & AO_EXTI_PRIORITY_LOW) +		prio = AO_LPC_NVIC_LOW_PRIORITY; +	else if (mode & AO_EXTI_PRIORITY_HIGH) +		prio = AO_LPC_NVIC_HIGH_PRIORITY; + +	/* Set priority and enable */ +	lpc_nvic_set_priority(LPC_ISR_PIN_INT0_POS + pint, prio); +	lpc_nvic_set_enable(LPC_ISR_PIN_INT0_POS + pint); +} + +void +ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode) { +	uint8_t		id = pin_id(port,pin); +	uint8_t		pint = ao_pint_map[id]; +	uint8_t		mask = 1 << pint; + +	ao_pint_mode[pint] = mode; + +	if (mode & AO_EXTI_MODE_RISING) +		lpc_gpio_pin.sienr = mask; +	else +		lpc_gpio_pin.cienr = mask; +		 +	if (mode & AO_EXTI_MODE_FALLING) +		lpc_gpio_pin.sienf = mask; +	else +		lpc_gpio_pin.cienf = mask; +} + +void +ao_exti_set_callback(uint8_t port, uint8_t pin, void (*callback)()) { +	uint8_t		id = pin_id(port,pin); +	uint8_t		pint = ao_pint_map[id]; + +	ao_exti_callback[pint] = callback; +} + +void +ao_exti_enable(uint8_t port, uint8_t pin) +{ +	uint8_t		id = pin_id(port,pin); +	uint8_t		pint = ao_pint_map[id]; +	uint8_t		mask = 1 << pint; + +	ao_pint_enabled |= mask; +	ao_exti_set_mode(port, pin, ao_pint_mode[pint]); +} + +void +ao_exti_disable(uint8_t port, uint8_t pin) { +	uint8_t		id = pin_id(port,pin); +	uint8_t		pint = ao_pint_map[id]; +	uint8_t		mask = 1 << pint; + +	ao_pint_enabled &= ~mask; +	lpc_gpio_pin.cienr = mask; +	lpc_gpio_pin.cienf = mask; +} + +void +ao_exti_init(void) +{ +	lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_PINT); +} | 
