/* * Copyright (c) by BlackMark 2015-2018 * Date 26/04/2018 * Version 3.0 */ #ifndef INOUT_H #define INOUT_H ////////////////////////////////////////////////////////////////////////// #include #include /************************************************************************/ ////////////////////////////////////////////////////////////////////////// namespace InOut { #define AVR_DIP40 defined (__AVR_ATmega32A__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega1284P__) #define AVR_DIP28 defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega168A__) || defined (__AVR_ATmega328P__) #define AVR_DIP8 defined (__AVR_ATtiny13A__) || defined (__AVR_ATtiny85__) #if AVR_DIP40 static constexpr volatile uint8_t *IO_PINA = &PINA; static constexpr volatile uint8_t *IO_DDRA = &DDRA; static constexpr volatile uint8_t *IO_PORTA = &PORTA; #else static constexpr volatile uint8_t *IO_PINA = nullptr; static constexpr volatile uint8_t *IO_DDRA = nullptr; static constexpr volatile uint8_t *IO_PORTA = nullptr; #endif #if AVR_DIP40 || AVR_DIP28 || AVR_DIP8 static constexpr volatile uint8_t *IO_PINB = &PINB; static constexpr volatile uint8_t *IO_DDRB = &DDRB; static constexpr volatile uint8_t *IO_PORTB = &PORTB; #else static constexpr volatile uint8_t *IO_PINB = nullptr; static constexpr volatile uint8_t *IO_DDRB = nullptr; static constexpr volatile uint8_t *IO_PORTB = nullptr; #endif #if AVR_DIP40 || AVR_DIP28 static constexpr volatile uint8_t *IO_PINC = &PINC; static constexpr volatile uint8_t *IO_DDRC = &DDRC; static constexpr volatile uint8_t *IO_PORTC = &PORTC; #else static constexpr volatile uint8_t *IO_PINC = nullptr; static constexpr volatile uint8_t *IO_DDRC = nullptr; static constexpr volatile uint8_t *IO_PORTC = nullptr; #endif #if AVR_DIP40 || AVR_DIP28 static constexpr volatile uint8_t *IO_PIND = &PIND; static constexpr volatile uint8_t *IO_DDRD = &DDRD; static constexpr volatile uint8_t *IO_PORTD = &PORTD; #else static constexpr volatile uint8_t *IO_PIND = nullptr; static constexpr volatile uint8_t *IO_DDRD = nullptr; static constexpr volatile uint8_t *IO_PORTD = nullptr; #endif enum class Pin { #if AVR_DIP40 A0 = 0x00, A1 = 0x01, A2 = 0x02, A3 = 0x03, A4 = 0x04, A5 = 0x05, A6 = 0x06, A7 = 0x07, #endif #if AVR_DIP40 || AVR_DIP28 || AVR_DIP8 B0 = 0x10, B1 = 0x11, B2 = 0x12, B3 = 0x13, B4 = 0x14, B5 = 0x15, #endif #if AVR_DIP40 || AVR_DIP28 B6 = 0x16, B7 = 0x17, C0 = 0x20, C1 = 0x21, C2 = 0x22, C3 = 0x23, C4 = 0x24, C5 = 0x25, C6 = 0x26, #endif #if AVR_DIP40 C7 = 0x27, #endif #if AVR_DIP40 || AVR_DIP28 D0 = 0x30, D1 = 0x31, D2 = 0x32, D3 = 0x33, D4 = 0x34, D5 = 0x35, D6 = 0x36, D7 = 0x37, #endif }; enum class Port { #if AVR_DIP40 A = Pin::A0, #endif #if AVR_DIP40 || AVR_DIP28 || AVR_DIP8 B = Pin::B0, #endif #if AVR_DIP40 || AVR_DIP28 C = Pin::C0, D = Pin::D0, #endif }; enum class Dir { IN, OUT }; enum class Type { DDR, PIN, PORT }; constexpr volatile uint8_t* getPort( Pin enmPin, Type enmType ) { volatile uint8_t *vpui8Port = nullptr; uint8_t ui8Port = static_cast( enmPin ) >> 4 & 0x0F; switch( ui8Port ) { case 0: { if( enmType == Type::DDR ) vpui8Port = IO_DDRA; else if( enmType == Type::PIN ) vpui8Port = IO_PINA; else if( enmType == Type::PORT ) vpui8Port = IO_PORTA; break; } case 1: { if( enmType == Type::DDR ) vpui8Port = IO_DDRB; else if( enmType == Type::PIN ) vpui8Port = IO_PINB; else if( enmType == Type::PORT ) vpui8Port = IO_PORTB; break; } case 2: { if( enmType == Type::DDR ) vpui8Port = IO_DDRC; else if( enmType == Type::PIN ) vpui8Port = IO_PINC; else if( enmType == Type::PORT ) vpui8Port = IO_PORTC; break; } case 3: { if( enmType == Type::DDR ) vpui8Port = IO_DDRD; else if( enmType == Type::PIN ) vpui8Port = IO_PIND; else if( enmType == Type::PORT ) vpui8Port = IO_PORTD; break; } } return vpui8Port; } constexpr uint8_t getPin( Pin enmPin ) { return static_cast( enmPin ) & 0x0F; } } /************************************************************************/ ////////////////////////////////////////////////////////////////////////// template class InOutPin { public: static inline void direction( InOut::Dir enmDir ) __attribute__( (always_inline) ); static inline void pullup( bool bPullup ) __attribute__( (always_inline) ); static inline bool read() __attribute__( (always_inline) ); static inline void write( bool bValue ) __attribute__( (always_inline) ); }; ////////////////////////////////////////////////////////////////////////// template inline void InOutPin::direction( InOut::Dir enmDir ) { constexpr volatile uint8_t *vpui8DDR = InOut::getPort( enmPin, InOut::Type::DDR ); constexpr uint8_t ui8Pin = InOut::getPin( enmPin ); if( enmDir == InOut::Dir::OUT ) *vpui8DDR |= ( 1 << ui8Pin ); else *vpui8DDR &= ~( 1 << ui8Pin ); } ////////////////////////////////////////////////////////////////////////// template inline void InOutPin::pullup( bool bPullup ) { write( bPullup ); } ////////////////////////////////////////////////////////////////////////// template inline bool InOutPin::read() { constexpr volatile uint8_t *vpui8PIN = InOut::getPort( enmPin, InOut::Type::PIN ); constexpr uint8_t ui8Pin = InOut::getPin( enmPin ); if( *vpui8PIN >> ui8Pin & 1 ) return true; return false; } ////////////////////////////////////////////////////////////////////////// template inline void InOutPin::write( bool bValue ) { constexpr volatile uint8_t *vpui8PORT = InOut::getPort( enmPin, InOut::Type::PORT ); constexpr uint8_t ui8Pin = InOut::getPin( enmPin ); if( bValue ) *vpui8PORT |= ( 1 << ui8Pin ); else *vpui8PORT &= ~( 1 << ui8Pin ); } /************************************************************************/ ////////////////////////////////////////////////////////////////////////// template class InOutPort { public: static inline void direction( InOut::Dir enmDir ) __attribute__( (always_inline) ); static inline void pullup( bool bPullup ) __attribute__( (always_inline) ); static inline uint8_t read() __attribute__( (always_inline) ); static inline void write( uint8_t ui8Value ) __attribute__( (always_inline) ); }; ////////////////////////////////////////////////////////////////////////// template inline void InOutPort::direction( InOut::Dir enmDir ) { constexpr volatile uint8_t *vpui8DDR = InOut::getPort( static_cast( enmPort ), InOut::Type::DDR ); *vpui8DDR = ( enmDir == InOut::Dir::OUT ) ? 0xFF : 0x00; } ////////////////////////////////////////////////////////////////////////// template inline void InOutPort::pullup( bool bPullup ) { write( bPullup ? 0xFF : 0x00 ); } ////////////////////////////////////////////////////////////////////////// template inline uint8_t InOutPort::read() { constexpr volatile uint8_t *vpui8PIN = InOut::getPort( static_cast( enmPort ), InOut::Type::PIN ); return *vpui8PIN; } ////////////////////////////////////////////////////////////////////////// template inline void InOutPort::write( uint8_t ui8Value ) { constexpr volatile uint8_t *vpui8PORT = InOut::getPort( static_cast( enmPort ), InOut::Type::PORT ); *vpui8PORT = ui8Value; } #endif