/************************************************************************/ /* */ /* File: avr/gpio.c */ /* Description: general purpose input/output 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 #include #if defined(__AVR_ATtiny84__) #define GPIO_MAX_PORT 2 #elif defined(__AVR_ATtiny841__) #define GPIO_MAX_PORT 2 #elif defined(__AVR_ATtiny85__) #define GPIO_MAX_PORT 1 #elif defined(__AVR_ATtiny1634__) #define GPIO_MAX_PORT 3 #elif defined(__AVR_ATmega328P__) #define GPIO_MAX_PORT 3 #elif defined(__AVR_ATmega2560__) #define GPIO_MAX_PORT 11 #else #error "no or unavailable cpu defined" #endif static struct { uint8_t* pin; uint8_t* ddr; uint8_t* port; } ports[GPIO_MAX_PORT] = { #if defined(__AVR_ATtiny84__)\ || defined(__AVR_ATtiny841__) { 0x0039, 0x003A, 0x003B }, { 0x0036, 0x0037, 0x0038 } #elif defined(__AVR_ATtiny85__) { 0x0016, 0x0017, 0x0018 } #elif defined(__AVR_ATtiny1634__) { 0x002F, 0x0030, 0x0031 }, { 0x002B, 0x002C, 0x002D }, { 0x0027, 0x0028, 0x0029 } #elif defined(__AVR_ATmega328P__) { 0x0023, 0x0024, 0x0025 }, { 0x0026, 0x0027, 0x0028 }, { 0x0029, 0x002A, 0x002B } #elif defined(__AVR_ATmega2560__) { 0x0020, 0x0021, 0x0022 }, { 0x0023, 0x0024, 0x0025 }, { 0x0026, 0x0027, 0x0028 }, { 0x0029, 0x002A, 0x002B }, { 0x002C, 0x002D, 0x002E }, { 0x002F, 0x0030, 0x0031 }, { 0x0032, 0x0033, 0x0034 }, { 0x0100, 0x0101, 0x0102 }, { 0x0104, 0x0104, 0x0105 }, { 0x0106, 0x0107, 0x0108 }, { 0x0109, 0x010A, 0x010B } #endif }; /* * read state of a gpio pin * * input: * gpio gpio pin * output: * low or high if success, otherwise -1 */ int8_t gpio_pin_get( uint8_t gpio ) { #ifdef CHECK_PARAM if( gpio >= (GPIO_MAX_PORT << 3) ) return( -1 ); #endif return( (*ports[gpio >> 3].pin >> (gpio & 7)) & 1 ); } /* * set state of a gpio pin * * input: * gpio gpio pin * value low or high */ void gpio_pin_set( uint8_t gpio, uint8_t value ) { #ifdef CHECK_PARAM if( gpio < (GPIO_MAX_PORT << 3) ) #endif { uint8_t port = gpio >> 3; uint8_t mask = 1 << (gpio & 7); if( value != 0 ) *ports[gpio >> 3].port |= mask; else *ports[gpio >> 3].port &= ~mask; } } /* * set a gpio pin as input * * input: * gpio gpio pin */ void gpio_pin_mode_input( uint8_t gpio ) { #ifdef CHECK_PARAM if( gpio < (GPIO_MAX_PORT << 3) ) #endif *ports[gpio >> 3].ddr &= ~(1 << (gpio & 7)); } /* * set a gpio pin as output * * input: * gpio gpio pin * value initial value, low or high */ void gpio_pin_mode_output( uint8_t gpio, uint8_t value ) { #ifdef CHECK_PARAM if( gpio < (GPIO_MAX_PORT << 3) ) #endif { uint8_t port = gpio >> 3; uint8_t mask = 1 << (gpio & 7); if( value != 0 ) *ports[port].port |= mask; else *ports[port].port &= ~mask; *ports[port].ddr |= mask; } } #ifdef USE_ADC #include "avr/adc.c" #endif #ifdef USE_PWM #include "avr/pwm.c" #endif #ifdef USE_PCINT #include "avr/pcint.c" #endif