diff --git a/cpu/atmega_common/include/periph_cpu_common.h b/cpu/atmega_common/include/periph_cpu_common.h index c355a843cc..b6f9f74a39 100644 --- a/cpu/atmega_common/include/periph_cpu_common.h +++ b/cpu/atmega_common/include/periph_cpu_common.h @@ -32,6 +32,24 @@ extern "C" { */ #define GPIO_PIN(x, y) ((x << 4) | y) +/** + * @brief Override the GPIO flanks + * + * This device has an additional mode in which the interrupt is triggered + * when the pin is low. + * + * Enumeration order is important, do not modify. + * @{ + */ +#define HAVE_GPIO_FLANK_T +typedef enum { + GPIO_LOW, /**< emit interrupt when pin low */ + GPIO_BOTH, /**< emit interrupt on both flanks */ + GPIO_FALLING, /**< emit interrupt on falling flank */ + GPIO_RISING, /**< emit interrupt on rising flank */ +} gpio_flank_t; +/** @} */ + /** * @brief Use some common SPI functions * @{ diff --git a/cpu/atmega_common/periph/gpio.c b/cpu/atmega_common/periph/gpio.c index 4316d000aa..e74db5d68c 100644 --- a/cpu/atmega_common/periph/gpio.c +++ b/cpu/atmega_common/periph/gpio.c @@ -138,6 +138,9 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, 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) #endif || ((mode != GPIO_IN) && (mode != GPIO_IN_PU))) { return -1; @@ -148,43 +151,26 @@ 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; +#endif + EIMSK |= (1 << pin_num); /* configure the flank */ - switch (flank) { - case GPIO_RISING: - if (pin_num < 4) { - EICRA |= (3 << pin_num * 2); - } + if (flank > GPIO_RISING) { + return -1; + } + + if (pin_num < 4) { + EICRA |= (flank << (pin_num * 2)); + } #if defined(EICRB) - else { - EICRB |= (3 << (pin_num * 2) % 4); - } + else { + EICRB |= (flank << (pin_num * 2) % 4); + } #endif - break; - case GPIO_FALLING: - if (pin_num < 4) { - EICRA |= (2 << pin_num * 2); - } -#if defined(EICRB) - else { - EICRB |= (2 << (pin_num * 2) % 4); - } -#endif - break; - case GPIO_BOTH: - if (pin_num < 4) { - EICRA |= (1 << pin_num * 2); - } -#if defined(EICRB) - else { - EICRB |= (1 << (pin_num * 2) % 4); - } -#endif - break; - default: - return -1; - }; /* set callback */ config[pin_num].cb = cb; @@ -198,12 +184,22 @@ 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)); +#else EIMSK |= (1 << _pin_num(pin)); +#endif } 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)); +#else EIMSK &= ~(1 << _pin_num(pin)); +#endif } int gpio_read(gpio_t pin)