/* * Copyright (c) by BlackMark 2015-2018 * Date 24/04/2018 * Version 2.8 */ #ifndef INOUT_H #define INOUT_H ////////////////////////////////////////////////////////////////////////// #include #include ////////////////////////////////////////////////////////////////////////// #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 /************************************************************************/ ////////////////////////////////////////////////////////////////////////// struct InOut { 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 { PIN, DDR, PORT }; static constexpr volatile uint8_t* getPort( Pin enmPin, Type enmType ); static constexpr uint8_t getPin( Pin enmPin ); static inline void setPinDirection( volatile uint8_t *vpui8Port, uint8_t ui8Pin, Dir enmDir ); static inline bool readPin( volatile uint8_t *vpui8Port, uint8_t ui8Pin ); static inline void writePin( volatile uint8_t *vpui8Port, uint8_t ui8Pin, bool bValue ); static inline void setPortDirection( volatile uint8_t *vpui8Port, Dir enmDir ); static inline uint8_t readPort( volatile uint8_t *vpui8Port ); static inline void writePort( volatile uint8_t *vpui8Port, uint8_t ui8Value ); static inline void setPinDirection( Pin enmPin, Dir enmDir ); static inline void setPinPullup( Pin enmPin, bool bPullup ); static inline bool readPin( Pin enmPin ); static inline void writePin( Pin enmPin, bool bValue ); static inline void setPortDirection( Port enmPort, Dir enmDir ); static inline void setPortPullup( Port enmPort, bool bPullup ); static inline uint8_t readPort( Port enmPort ); static inline void writePort( Port enmPort, uint8_t ui8Value ); }; ////////////////////////////////////////////////////////////////////////// constexpr volatile uint8_t* InOut::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::PIN ) vpui8Port = IO_PINA; else if( enmType == Type::DDR ) vpui8Port = IO_DDRA; else if( enmType == Type::PORT ) vpui8Port = IO_PORTA; break; } case 1: { if( enmType == Type::PIN ) vpui8Port = IO_PINB; else if( enmType == Type::DDR ) vpui8Port = IO_DDRB; else if( enmType == Type::PORT ) vpui8Port = IO_PORTB; break; } case 2: { if( enmType == Type::PIN ) vpui8Port = IO_PINC; else if( enmType == Type::DDR ) vpui8Port = IO_DDRC; else if( enmType == Type::PORT ) vpui8Port = IO_PORTC; break; } case 3: { if( enmType == Type::PIN ) vpui8Port = IO_PIND; else if( enmType == Type::DDR ) vpui8Port = IO_DDRD; else if( enmType == Type::PORT ) vpui8Port = IO_PORTD; break; } } return vpui8Port; } ////////////////////////////////////////////////////////////////////////// constexpr uint8_t InOut::getPin( Pin enmPin ) { return static_cast( enmPin ) & 0x0F; } ////////////////////////////////////////////////////////////////////////// inline void InOut::setPinDirection( volatile uint8_t *vpui8Port, uint8_t ui8Pin, Dir enmDir ) { if( enmDir == Dir::OUT ) *vpui8Port |= ( 1 << ui8Pin ); else *vpui8Port &= ~( 1 << ui8Pin ); } ////////////////////////////////////////////////////////////////////////// inline bool InOut::readPin( volatile uint8_t *vpui8Port, uint8_t ui8Pin ) { if( *vpui8Port >> ui8Pin & 1 ) return true; return false; } ////////////////////////////////////////////////////////////////////////// inline void InOut::writePin( volatile uint8_t *vpui8Port, uint8_t ui8Pin, bool bValue ) { if( bValue ) *vpui8Port |= ( 1 << ui8Pin ); else *vpui8Port &= ~( 1 << ui8Pin ); } ////////////////////////////////////////////////////////////////////////// inline void InOut::setPortDirection( volatile uint8_t *vpui8Port, Dir enmDir ) { *vpui8Port = ( enmDir == Dir::OUT ) ? 0xFF : 0x00; } ////////////////////////////////////////////////////////////////////////// inline uint8_t InOut::readPort( volatile uint8_t *vpui8Port ) { return *vpui8Port; } ////////////////////////////////////////////////////////////////////////// inline void InOut::writePort( volatile uint8_t *vpui8Port, uint8_t ui8Value ) { *vpui8Port = ui8Value; } ////////////////////////////////////////////////////////////////////////// inline void InOut::setPinDirection( Pin enmPin, Dir enmDir ) { volatile uint8_t *vpui8PortDir = getPort( enmPin, Type::DDR ); uint8_t ui8Pin = getPin( enmPin ); setPinDirection( vpui8PortDir, ui8Pin, enmDir ); } ////////////////////////////////////////////////////////////////////////// inline void InOut::setPinPullup( Pin enmPin, bool bPullup ) { volatile uint8_t *vpui8PortOut = getPort( enmPin, Type::PORT ); uint8_t ui8Pin = getPin( enmPin ); writePin( vpui8PortOut, ui8Pin, bPullup ); } ////////////////////////////////////////////////////////////////////////// inline bool InOut::readPin( Pin enmPin ) { volatile uint8_t *vpui8Port = getPort( enmPin, Type::PIN ); uint8_t ui8Pin = getPin( enmPin ); return readPin( vpui8Port, ui8Pin ); } ////////////////////////////////////////////////////////////////////////// inline void InOut::writePin( Pin enmPin, bool bValue ) { volatile uint8_t *vpui8Port = getPort( enmPin, Type::PORT ); uint8_t ui8Pin = getPin( enmPin ); writePin( vpui8Port, ui8Pin, bValue ); } ////////////////////////////////////////////////////////////////////////// inline void InOut::setPortDirection( Port enmPort, Dir enmDir ) { volatile uint8_t *vpui8PortDir = getPort( static_cast( enmPort ), Type::DDR ); setPortDirection( vpui8PortDir, enmDir ); } ////////////////////////////////////////////////////////////////////////// inline void InOut::setPortPullup( Port enmPort, bool bPullup ) { volatile uint8_t *vpui8PortOut = getPort( static_cast( enmPort ), Type::PORT ); writePort( vpui8PortOut, bPullup ? 0xFF : 0x00 ); } ////////////////////////////////////////////////////////////////////////// inline uint8_t InOut::readPort( Port enmPort ) { volatile uint8_t *vpui8Port = getPort( static_cast( enmPort ), Type::PIN ); return readPort( vpui8Port ); } ////////////////////////////////////////////////////////////////////////// inline void InOut::writePort( Port enmPort, uint8_t ui8Value ) { volatile uint8_t *vpui8Port = getPort( static_cast( enmPort ), Type::PORT ); writePort( vpui8Port, ui8Value ); } /************************************************************************/ ////////////////////////////////////////////////////////////////////////// class InOutPin { private: volatile uint8_t *m_pvui8PIN; volatile uint8_t *m_pvui8DDR; volatile uint8_t *m_pvui8PORT; uint8_t m_ui8Pin; public: inline InOutPin(); inline InOutPin( InOut::Pin enmPin ); inline void setPin( InOut::Pin enmPin ); inline void setDirection( InOut::Dir enmDir ); inline void setPullup( bool bPullup ); inline bool read(); inline void write( bool bValue ); }; ////////////////////////////////////////////////////////////////////////// inline InOutPin::InOutPin() : m_pvui8PIN( nullptr ), m_pvui8DDR( nullptr ), m_pvui8PORT( nullptr ), m_ui8Pin( 0xFF ) {} ////////////////////////////////////////////////////////////////////////// inline InOutPin::InOutPin( InOut::Pin enmPin ) : m_pvui8PIN( InOut::getPort( enmPin, InOut::Type::PIN ) ), m_pvui8DDR( InOut::getPort( enmPin, InOut::Type::DDR ) ), m_pvui8PORT( InOut::getPort( enmPin, InOut::Type::PORT ) ), m_ui8Pin( InOut::getPin( enmPin ) ) {} ////////////////////////////////////////////////////////////////////////// inline void InOutPin::setPin( InOut::Pin enmPin ) { m_pvui8PIN = InOut::getPort( enmPin, InOut::Type::PIN ); m_pvui8DDR = InOut::getPort( enmPin, InOut::Type::DDR ); m_pvui8PORT = InOut::getPort( enmPin, InOut::Type::PORT ); m_ui8Pin = InOut::getPin( enmPin ); } ////////////////////////////////////////////////////////////////////////// inline void InOutPin::setDirection( InOut::Dir enmDir ) { InOut::setPinDirection( m_pvui8DDR, m_ui8Pin, enmDir ); } ////////////////////////////////////////////////////////////////////////// inline void InOutPin::setPullup( bool bPullup ) { InOut::writePin( m_pvui8PORT, m_ui8Pin, bPullup ); } ////////////////////////////////////////////////////////////////////////// inline bool InOutPin::read() { return InOut::readPin( m_pvui8PIN, m_ui8Pin ); } ////////////////////////////////////////////////////////////////////////// inline void InOutPin::write( bool bValue ) { InOut::writePin( m_pvui8PORT, m_ui8Pin, bValue ); } /************************************************************************/ ////////////////////////////////////////////////////////////////////////// class InOutPort { private: volatile uint8_t *m_pvui8PIN; volatile uint8_t *m_pvui8DDR; volatile uint8_t *m_pvui8PORT; public: inline InOutPort(); inline InOutPort( InOut::Port enmPort ); inline void setPort( InOut::Port enmPort ); inline void setDirection( InOut::Dir enmDir ); inline void setPullup( bool bPullup ); inline uint8_t read(); inline void write( uint8_t ui8Value ); }; ////////////////////////////////////////////////////////////////////////// inline InOutPort::InOutPort() : m_pvui8PIN( nullptr ), m_pvui8DDR( nullptr ), m_pvui8PORT( nullptr ) {} ////////////////////////////////////////////////////////////////////////// inline InOutPort::InOutPort( InOut::Port enmPort ) : m_pvui8PIN( InOut::getPort( static_cast( enmPort ), InOut::Type::PIN ) ), m_pvui8DDR( InOut::getPort( static_cast( enmPort ), InOut::Type::DDR ) ), m_pvui8PORT( InOut::getPort( static_cast( enmPort ), InOut::Type::PORT ) ) {} ////////////////////////////////////////////////////////////////////////// inline void InOutPort::setPort( InOut::Port enmPort ) { m_pvui8PIN = InOut::getPort( static_cast( enmPort ), InOut::Type::PIN ); m_pvui8DDR = InOut::getPort( static_cast( enmPort ), InOut::Type::DDR ); m_pvui8PORT = InOut::getPort( static_cast( enmPort ), InOut::Type::PORT ); } ////////////////////////////////////////////////////////////////////////// inline void InOutPort::setDirection( InOut::Dir enmDir ) { InOut::setPortDirection( m_pvui8DDR, enmDir ); } ////////////////////////////////////////////////////////////////////////// inline void InOutPort::setPullup( bool bPullup ) { InOut::writePort( m_pvui8PORT, bPullup ? 0xFF : 0x00 ); } ////////////////////////////////////////////////////////////////////////// inline uint8_t InOutPort::read() { return InOut::readPort( m_pvui8PIN ); } ////////////////////////////////////////////////////////////////////////// inline void InOutPort::write( uint8_t ui8Value ) { InOut::writePort( m_pvui8PORT, ui8Value ); } #endif