diff options
| author | Otto Mattik <otto@mattik.org> | 2021-07-08 18:10:55 +0200 |
|---|---|---|
| committer | Otto Mattik <otto@mattik.org> | 2021-07-08 18:10:55 +0200 |
| commit | da34d97efb21719b2b332f8c60b2750d11bcde1f (patch) | |
| tree | 2de9fe89f6d79b8ebfcde64c5e86204e904aedf2 /avr/pcint.c | |
| download | armen-a861fb554ced7709555d2d1b639c534e3f45a83f.tar.gz armen-a861fb554ced7709555d2d1b639c534e3f45a83f.zip | |
Diffstat (limited to 'avr/pcint.c')
| -rw-r--r-- | avr/pcint.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/avr/pcint.c b/avr/pcint.c new file mode 100644 index 0000000..4dea0c7 --- /dev/null +++ b/avr/pcint.c @@ -0,0 +1,247 @@ +/************************************************************************/ +/* */ +/* File: avr/pcint.c */ +/* Description: pin change interruption driver. */ +/* Version: 1.0 */ +/* Author: Otto Mattik */ +/* */ +/* (C)Copyright Otto Mattik 2014-2021. */ +/* */ +/* This file is a part of 'armen' (a tiny operating system). */ +/* 'armen' is distributed under the CeCILL-V2.1 licence. For more */ +/* details about this licence, please visit the website cecill.info */ +/* */ +/************************************************************************/ + +#ifndef AVR_GPIO_C + #error "do not use this code directly, it must be included via gpio.c" +#endif + +#include "avr/core.h" +#include <avr/interrupt.h> + +#if defined(__AVR_ATtiny84__) + #define GPIO_MAX_PCINT 2 + #define GPIO_MAX_INT 1 +#elif defined(__AVR_ATtiny841__) + #define GPIO_MAX_PCINT 2 + #define GPIO_MAX_INT 1 +#elif defined(__AVR_ATtiny85__) + #define GPIO_MAX_PCINT 1 + #define GPIO_MAX_INT 1 +#elif defined(__AVR_ATtiny1634__) + #define GPIO_MAX_PCINT 3 + #define GPIO_MAX_INT 1 +#elif defined(__AVR_ATmega328P__) + #define GPIO_MAX_PCINT 3 + #define GPIO_MAX_INT 2 +#elif defined(__AVR_ATmega2560__) + #define GPIO_MAX_PCINT 3 + #define GPIO_MAX_INT 3 /* really 8, limited to 3 by events mask */ +#endif + +static struct { + uint8_t* pcmsk; + uint8_t pcie; +} pcints[GPIO_MAX_PCINT] = { +#if defined(__AVR_ATtiny85__) + { 0x0015, 1<<PCIE0 } +#elif defined(__AVR_ATtiny84__)\ + || defined(__AVR_ATtiny841__) + { 0x0032, 1<<PCIE0 }, + { 0x0040, 1<<PCIE1 } +#elif defined(__AVR_ATtiny1634__) + { 0x0047, 1<<PCIE0 }, + { 0x0048, 1<<PCIE1 }, + { 0x0049, 1<<PCIE2 } +#elif defined(__AVR_ATmega328P__)\ + || defined(__AVR_ATmega2560__) + { 0x006B, 1<<PCIE0 }, + { 0x006C, 1<<PCIE1 }, + { 0x006D, 1<<PCIE2 } + #endif +}; + +/* + * interrupt vectors +*/ +ISR( INT0_vect ) +{ + register uint8_t iflag; + + iflag = _disable_intr( ); +#ifdef GIMSK + if( (MCUCR & 0x03) == INT_LOW ) + GIMSK &= ~(1 << INT0); +#else + if( (EICRA & 0x03) == INT_LOW ) + EIMSK &= ~1; +#endif + _wakeup( EVENT_INT0, 0 ); + _enable_intr( iflag ); +} + +#if (GPIO_MAX_INT >= 2) + ISR( INT1_vect ) + { + register uint8_t iflag; + + iflag = _disable_intr( ); + if( (EICRA & 0x0C) == INT_LOW ) + EIMSK &= ~2; + _wakeup( EVENT_INT1, 0 ); + _enable_intr( iflag ); + } +#endif +#if (GPIO_MAX_INT == 3) + ISR( INT2_vect ) + { + register uint8_t iflag; + + iflag = _disable_intr( ); + if( (EICRA & 0x30) == INT_LOW ) + EIMSK &= ~4; + _wakeup( EVENT_INT2, 0 ); + _enable_intr( iflag ); + } +#endif + +ISR( PCINT0_vect ) +{ + register uint8_t iflag; + + iflag = _disable_intr( ); + _wakeup( EVENT_PCINT0, 0 ); + _enable_intr( iflag ); +} + +#ifndef PCINT_PER_PORT + #if (GPIO_MAX_PCINT >= 2) + ISR( PCINT1_vect, ISR_ALIASOF( PCINT0_vect ) ); + #endif + #if (GPIO_MAX_PCINT == 3) + ISR( PCINT2_vect, ISR_ALIASOF( PCINT0_vect ) ); + #endif +#else + #if (GPIO_MAX_PCINT >= 2) + ISR( PCINT1_vect ) + { + register uint8_t iflag; + + iflag = _disable_intr( ); + _wakeup( EVENT_PCINT1, 0 ); + _enable_intr( iflag ); + } + #endif + #if (GPIO_MAX_PCINT == 3) + ISR( PCINT2_vect ) + { + register uint8_t iflag; + + iflag = _disable_intr( ); + _wakeup( EVENT_PCINT2, 0 ); + _enable_intr( iflag ); + } + #endif +#endif + +/* + * enable/disable interrupt on gpio pin change + * + * input: + * interrupt interrupt number (0, 1, 2) + * mode interrupt mode (LOW, CHANGE, RISING, FALLING, DISABLE) +*/ +void gpio_int_enable( uint8_t interrupt, uint8_t mode ) +{ +#ifdef CHECK_PARAM + if( interrupt < GPIO_MAX_INT && mode <= INT_DISABLE ) +#endif + { + if( mode == INT_DISABLE ) +/* +#if defined(__AVR_ATtiny84__)\ + || defined(__AVR_ATtiny85__)\ + || defined(__AVR_ATtiny841__)\ + || defined(__AVR_ATtiny1634__) +*/ +#ifdef GIMSK + GIMSK &= ~(1 << INT0); + else + { + MCUCR |= mode; + GIMSK |= (1 << INT0); + } +#else + EIMSK &= ~(1 << interrupt); + else + { + #if 0 + #if defined(__AVR_ATmega2560__) + if( interrupt >= 4 ) + EICRB |= (mode << (interrupt-4)); + else + #endif + #endif + EICRA |= (mode << interrupt); + EIMSK |= (1 << interrupt); + } +#endif + } +} + +/* + * enable/disable interrupt on gpio pin change + * + * input: + * gpio gpio pin + * enable true or false +*/ +void gpio_pcint_enable( uint8_t gpio, uint8_t enable ) +{ +#ifdef CHECK_PARAM + if( gpio < (GPIO_MAX_PORT << 3) ) +#endif + { +#if defined(__AVR_ATtiny1634__) + if( gpio > 11 ) + gpio += 4; + if( gpio < 22 ) +#elif defined(__AVR_ATmega328P__) + if( gpio != 15 ) +#elif defined(__AVR_ATmega2560__) + if( gpio >= 8 && gpio <= 15 ) + gpio -= 8; + else if( gpio == 32 ) + gpio = 8; + else if( gpio >= 64 && gpio <= 70 ) + gpio -= 55; + else if( gpio >= 72 && gpio <= 79 ) + gpio -= 56; + else + return; +#endif + { + uint8_t port = gpio >> 3; + uint8_t mask = 1 << (gpio & 7); + + if( enable != 0 ) + { + *pcints[port].pcmsk |= mask; +/* +#if defined(__AVR_ATtiny84__)\ + || defined(__AVR_ATtiny85__)\ + || defined(__AVR_ATtiny841__)\ + || defined(__AVR_ATtiny1634__) +*/ +#ifdef GIMSK + GIMSK |= pcints[port].pcie; +#else + PCICR |= pcints[port].pcie; +#endif + } + else + *pcints[port].pcmsk &= ~mask; + } + } +} |
