diff --git a/cpu/atmega1281/include/periph_cpu.h b/cpu/atmega1281/include/periph_cpu.h index 1f503fdb0732..9f69d979e7e1 100644 --- a/cpu/atmega1281/include/periph_cpu.h +++ b/cpu/atmega1281/include/periph_cpu.h @@ -42,6 +42,20 @@ enum { PORT_G = 6, /**< port G */ }; +/** + * @brief Available external interrupt pins on the ATmega1281 family + * + * In order of their interrupt number. + */ +#define CPU_ATMEGA_EXT_INTS { GPIO_PIN(PORT_D, 0), \ + GPIO_PIN(PORT_D, 1), \ + GPIO_PIN(PORT_D, 2), \ + GPIO_PIN(PORT_D, 3), \ + GPIO_PIN(PORT_E, 4), \ + GPIO_PIN(PORT_E, 5), \ + GPIO_PIN(PORT_E, 6), \ + GPIO_PIN(PORT_E, 7) } + /** * @name Defines for the I2C interface * @{ diff --git a/cpu/atmega1284p/include/periph_cpu.h b/cpu/atmega1284p/include/periph_cpu.h index c7f43419125f..047dae07c172 100644 --- a/cpu/atmega1284p/include/periph_cpu.h +++ b/cpu/atmega1284p/include/periph_cpu.h @@ -35,7 +35,7 @@ extern "C" { #define GPIO_PIN(x, y) ((x << 4) | y) /** - * @brief Available ports on the ATmega328p family + * @brief Available ports on the ATmega1284p family */ enum { PORT_A = 0, /**< port A */ @@ -44,6 +44,15 @@ enum { PORT_D = 3 /**< port D */ }; +/** + * @brief Available external interrupt pins on the ATmega1284p family + * + * In order of their interrupt number + */ +#define CPU_ATMEGA_EXT_INTS { GPIO_PIN(PORT_D, 2), \ + GPIO_PIN(PORT_D, 3), \ + GPIO_PIN(PORT_B, 2) } + /** * @name Defines for the I2C interface * @{ diff --git a/cpu/atmega2560/include/periph_cpu.h b/cpu/atmega2560/include/periph_cpu.h index 92fd80968602..10cd8acc1e1e 100644 --- a/cpu/atmega2560/include/periph_cpu.h +++ b/cpu/atmega2560/include/periph_cpu.h @@ -44,6 +44,20 @@ enum { PORT_L = 10 /**< port L */ }; +/** + * @brief Available external interrupt pins on the ATmega2560 family + * + * In order of their interrupt number. + */ +#define CPU_ATMEGA_EXT_INTS { GPIO_PIN(PORT_D, 0), \ + GPIO_PIN(PORT_D, 1), \ + GPIO_PIN(PORT_D, 2), \ + GPIO_PIN(PORT_D, 3), \ + GPIO_PIN(PORT_E, 4), \ + GPIO_PIN(PORT_E, 5), \ + GPIO_PIN(PORT_E, 6), \ + GPIO_PIN(PORT_E, 7) } + /** * @name Defines for the I2C interface * @{ diff --git a/cpu/atmega256rfr2/include/periph_cpu.h b/cpu/atmega256rfr2/include/periph_cpu.h index 731149bb5a0a..03562a2402d5 100644 --- a/cpu/atmega256rfr2/include/periph_cpu.h +++ b/cpu/atmega256rfr2/include/periph_cpu.h @@ -46,6 +46,20 @@ enum { PORT_G = 6, /**< port G */ }; +/** + * @brief Available external interrupt pins on the ATmega256rfr family + * + * In order of their interrupt number. + */ +#define CPU_ATMEGA_EXT_INTS { GPIO_PIN(PORT_D, 0), \ + GPIO_PIN(PORT_D, 1), \ + GPIO_PIN(PORT_D, 2), \ + GPIO_PIN(PORT_D, 3), \ + GPIO_PIN(PORT_E, 4), \ + GPIO_PIN(PORT_E, 5), \ + GPIO_PIN(PORT_E, 6), \ + GPIO_PIN(PORT_E, 7) } + /** * @name Defines for the I2C interface * @{ diff --git a/cpu/atmega328p/include/periph_cpu.h b/cpu/atmega328p/include/periph_cpu.h index 5e29096ad46b..03ab92365fd9 100644 --- a/cpu/atmega328p/include/periph_cpu.h +++ b/cpu/atmega328p/include/periph_cpu.h @@ -41,6 +41,14 @@ enum { PORT_D = 3 /**< port D */ }; +/** + * @brief Available external interrupt pins on the ATmega328p family + * + * In order of their interrupt number. + */ +#define CPU_ATMEGA_EXT_INTS { GPIO_PIN(PORT_D, 2), \ + GPIO_PIN(PORT_D, 3) } + /** * @name Defines for the I2C interface * @{ diff --git a/cpu/atmega_common/periph/gpio.c b/cpu/atmega_common/periph/gpio.c index 5e0bced64e70..233ae2950973 100644 --- a/cpu/atmega_common/periph/gpio.c +++ b/cpu/atmega_common/periph/gpio.c @@ -30,6 +30,7 @@ #include "cpu.h" #include "periph/gpio.h" #include "periph_conf.h" +#include "periph_cpu.h" #define GPIO_BASE_PORT_A (0x20) #define GPIO_OFFSET_PORT_H (0xCB) @@ -40,18 +41,18 @@ * @brief Define GPIO interruptions for an specific atmega CPU, by default * 2 (for small atmega CPUs) */ -#if defined(INT2_vect) -#define GPIO_EXT_INT_NUMOF (3U) -#elif defined(INT3_vect) -#define GPIO_EXT_INT_NUMOF (4U) -#elif defined(INT4_vect) -#define GPIO_EXT_INT_NUMOF (4U) -#elif defined(INT5_vect) -#define GPIO_EXT_INT_NUMOF (4U) +#if defined(INT7_vect) +#define GPIO_EXT_INT_NUMOF (8U) #elif defined(INT6_vect) +#define GPIO_EXT_INT_NUMOF (7U) +#elif defined(INT5_vect) +#define GPIO_EXT_INT_NUMOF (6U) +#elif defined(INT4_vect) +#define GPIO_EXT_INT_NUMOF (5U) +#elif defined(INT3_vect) #define GPIO_EXT_INT_NUMOF (4U) -#elif defined(INT7_vect) -#define GPIO_EXT_INT_NUMOF (4U) +#elif defined(INT2_vect) +#define GPIO_EXT_INT_NUMOF (3U) #else #define GPIO_EXT_INT_NUMOF (2U) #endif @@ -109,6 +110,21 @@ static inline uint16_t _pin_addr(gpio_t pin) return (_port_addr(pin) - 0x02); } +static inline int8_t _int_num(gpio_t pin) +{ + uint8_t num; + const gpio_t ext_ints[GPIO_EXT_INT_NUMOF] = CPU_ATMEGA_EXT_INTS; + + /* find pin in ext_ints array to get the interrupt number */ + for (num = 0; num < GPIO_EXT_INT_NUMOF; num++) { + if (pin == ext_ints[num]) { + return num; + } + } + + return -1; +} + int gpio_init(gpio_t pin, gpio_mode_t mode) { switch (mode) { @@ -132,20 +148,14 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg) { - uint8_t pin_num = _pin_num(pin); - - if ((_port_num(pin) == PORT_D && pin_num > 3) -#if defined (PORTE) - || (_port_num(pin) == PORT_E && pin_num < 4) - || (_port_num(pin) != PORT_D && _port_num(pin) != PORT_E) -#elif defined(CPU_ATMEGA328P) - || (pin_num < 2) || (_port_num(pin) != PORT_D) -#elif defined(CPU_ATMEGA1284P) - || (_port_num(pin) == PORT_B && pin_num != 2) - || (_port_num(pin) == PORT_D && pin_num < 2) - || (_port_num(pin) != PORT_D && _port_num(pin) != PORT_D) -#endif - || ((mode != GPIO_IN) && (mode != GPIO_IN_PU))) { + int8_t int_num = _int_num(pin); + + if ((mode != GPIO_IN) && (mode != GPIO_IN_PU)) { + return -1; + } + + /* not a valid interrupt pin */ + if (int_num < 0) { return -1; } @@ -154,35 +164,27 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, /* clear global interrupt flag */ cli(); -#if defined(CPU_ATMEGA328P) - /* INT pins start at PD2 instead of at PD0 */ - pin_num -= 2; -#elif defined(CPU_ATMEGA1284P) - /* INT pins start at PD2 instead of at PD0 on PORT_D */ - if (_port_num(pin) == PORT_D) { - pin_num -= 2; - } -#endif - - EIMSK |= (1 << pin_num); + /* enable interrupt number int_num */ + EIMSK |= (1 << int_num); /* configure the flank */ if (flank > GPIO_RISING) { return -1; } - if (pin_num < 4) { - EICRA |= (flank << (pin_num * 2)); + /* apply flank to interrupt number int_num */ + if (int_num < 4) { + EICRA |= (flank << (int_num * 2)); } #if defined(EICRB) else { - EICRB |= (flank << (pin_num * 2) % 4); + EICRB |= (flank << ((int_num % 4) * 2)); } #endif /* set callback */ - config[pin_num].cb = cb; - config[pin_num].arg = arg; + config[int_num].cb = cb; + config[int_num].arg = arg; /* set global interrupt flag */ sei(); @@ -192,38 +194,12 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, void gpio_irq_enable(gpio_t pin) { -#if defined(CPU_ATMEGA328P) - /* INT pins start at PD2 instead of at PD0 */ - EIMSK |= (1 << (_pin_num(pin) - 2)); -#elif defined(CPU_ATMEGA1284P) - /* INT pins start at PD2 instead of at PD0 on PORT_D */ - if (_port_num(pin) == PORT_D) { - EIMSK |= (1 << (_pin_num(pin) - 2)); - } - else { - EIMSK |= (1 << _pin_num(pin)); - } -#else - EIMSK |= (1 << _pin_num(pin)); -#endif + EIMSK |= (1 << _int_num(pin)); } void gpio_irq_disable(gpio_t pin) { -#if defined(CPU_ATMEGA328P) - /* INT pins start at PD2 instead of at PD0 */ - EIMSK &= ~(1 << (_pin_num(pin) - 2)); -#elif defined (CPU_ATMEGA1284P) - /* INT pins start at PD2 instead of at PD0 on PORT_D */ - if (_port_num(pin) == PORT_D) { - EIMSK &= ~(1 << (_pin_num(pin) - 2)); - } - else { - EIMSK &= ~(1 << _pin_num(pin)); - } -#else - EIMSK &= ~(1 << _pin_num(pin)); -#endif + EIMSK &= ~(1 << _int_num(pin)); } int gpio_read(gpio_t pin) @@ -261,10 +237,10 @@ void gpio_write(gpio_t pin, int value) } } -static inline void irq_handler(uint8_t pin_num) +static inline void irq_handler(uint8_t int_num) { __enter_isr(); - config[pin_num].cb(config[pin_num].arg); + config[int_num].cb(config[int_num].arg); __exit_isr(); }