From a69465fca084be51a9486a2439c3b6d596cfb14a Mon Sep 17 00:00:00 2001 From: BlackMark Date: Thu, 26 Apr 2018 15:23:42 +0200 Subject: [PATCH] Rewrote interface to make sure port and pin lookup are done at compile time --- inout.h | 457 +++++++++++++++++++------------------------------------- 1 file changed, 155 insertions(+), 302 deletions(-) diff --git a/inout.h b/inout.h index a157b8a..6469b4f 100644 --- a/inout.h +++ b/inout.h @@ -1,7 +1,7 @@ /* * Copyright (c) by BlackMark 2015-2018 -* Date 24/04/2018 -* Version 2.8 +* Date 26/04/2018 +* Version 3.0 */ #ifndef INOUT_H @@ -12,56 +12,55 @@ #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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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 @@ -130,335 +129,189 @@ struct InOut enum class Type { - PIN, DDR, + PIN, PORT }; - static constexpr volatile uint8_t* getPort( Pin enmPin, Type enmType ); - static constexpr uint8_t getPin( Pin enmPin ); + constexpr volatile uint8_t* getPort( Pin enmPin, Type enmType ) + { + volatile uint8_t *vpui8Port = nullptr; + uint8_t ui8Port = static_cast( enmPin ) >> 4 & 0x0F; - 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 ); + 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; + } - 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 ); + 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; + } - 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 ); + 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; + } - 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 ); + 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: + inline InOutPin() __attribute__( (always_inline) ); + + static inline void setDirection( InOut::Dir enmDir ) __attribute__( (always_inline) ); + static inline void setPullup( bool bPullup ) __attribute__( (always_inline) ); + + static inline bool read() __attribute__( (always_inline) ); + static inline void write( bool bValue ) __attribute__( (always_inline) ); }; ////////////////////////////////////////////////////////////////////////// -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; -} +template +inline InOutPin::InOutPin() +{} ////////////////////////////////////////////////////////////////////////// -constexpr uint8_t InOut::getPin( Pin enmPin ) +template +inline void InOutPin::setDirection( InOut::Dir enmDir ) { - return static_cast( enmPin ) & 0x0F; -} + constexpr volatile uint8_t *vpui8DDR = InOut::getPort( enmPin, InOut::Type::DDR ); + constexpr uint8_t ui8Pin = InOut::getPin( enmPin ); -////////////////////////////////////////////////////////////////////////// -inline void InOut::setPinDirection( volatile uint8_t *vpui8Port, uint8_t ui8Pin, Dir enmDir ) -{ - if( enmDir == Dir::OUT ) - *vpui8Port |= ( 1 << ui8Pin ); + if( enmDir == InOut::Dir::OUT ) + *vpui8DDR |= ( 1 << ui8Pin ); else - *vpui8Port &= ~( 1 << ui8Pin ); + *vpui8DDR &= ~( 1 << ui8Pin ); } ////////////////////////////////////////////////////////////////////////// -inline bool InOut::readPin( volatile uint8_t *vpui8Port, uint8_t ui8Pin ) +template +inline void InOutPin::setPullup( bool bPullup ) { - if( *vpui8Port >> ui8Pin & 1 ) + 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; } ////////////////////////////////////////////////////////////////////////// -inline void InOut::writePin( volatile uint8_t *vpui8Port, uint8_t ui8Pin, bool bValue ) +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 ); + *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 ); + *vpui8PORT &= ~( 1 << ui8Pin ); } /************************************************************************/ ////////////////////////////////////////////////////////////////////////// +template 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 InOutPort() __attribute__( (always_inline) ); - inline void setPort( InOut::Port enmPort ); + static inline void setDirection( InOut::Dir enmDir ) __attribute__( (always_inline) ); + static inline void setPullup( bool bPullup ) __attribute__( (always_inline) ); - inline void setDirection( InOut::Dir enmDir ); - inline void setPullup( bool bPullup ); - - inline uint8_t read(); - inline void write( uint8_t ui8Value ); + static inline uint8_t read() __attribute__( (always_inline) ); + static inline void write( uint8_t ui8Value ) __attribute__( (always_inline) ); }; ////////////////////////////////////////////////////////////////////////// -inline InOutPort::InOutPort() : - m_pvui8PIN( nullptr ), m_pvui8DDR( nullptr ), m_pvui8PORT( nullptr ) +template +inline InOutPort::InOutPort() {} ////////////////////////////////////////////////////////////////////////// -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 ) +template +inline void InOutPort::setDirection( InOut::Dir enmDir ) { - 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 ); + constexpr volatile uint8_t *vpui8DDR = InOut::getPort( static_cast( enmPort ), InOut::Type::DDR ); + *vpui8DDR = ( enmDir == InOut::Dir::OUT ) ? 0xFF : 0x00; } ////////////////////////////////////////////////////////////////////////// -inline void InOutPort::setDirection( InOut::Dir enmDir ) +template +inline void InOutPort::setPullup( bool bPullup ) { - InOut::setPortDirection( m_pvui8DDR, enmDir ); + write( bPullup ? 0xFF : 0x00 ); } ////////////////////////////////////////////////////////////////////////// -inline void InOutPort::setPullup( bool bPullup ) +template +inline uint8_t InOutPort::read() { - InOut::writePort( m_pvui8PORT, bPullup ? 0xFF : 0x00 ); + constexpr volatile uint8_t *vpui8PIN = InOut::getPort( static_cast( enmPort ), InOut::Type::PIN ); + return *vpui8PIN; } ////////////////////////////////////////////////////////////////////////// -inline uint8_t InOutPort::read() +template +inline void InOutPort::write( uint8_t ui8Value ) { - return InOut::readPort( m_pvui8PIN ); -} - -////////////////////////////////////////////////////////////////////////// -inline void InOutPort::write( uint8_t ui8Value ) -{ - InOut::writePort( m_pvui8PORT, ui8Value ); + constexpr volatile uint8_t *vpui8PORT = InOut::getPort( static_cast( enmPort ), InOut::Type::PORT ); + *vpui8PORT = ui8Value; } #endif \ No newline at end of file