/****************************************************************************** * * Author : Konstantin Chizhov * Date : 2010 * All rights reserved. * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************** * ../AVR/ports.h * **************************************************************************** * modified: - docu * ******** - table layout * * includes: - ../compatibility__.h> // toolchain includes * ******** - ../atomic.h // ATOMIC * - ../ioreg.h> // IO_REG_WRAPPER * - ../template_utils.h> // Util * * - ../AVR/__port_def_.h // HW specific PortX * * defines: - class NativePortBase { ... * ******** - class PortImplementation * * returns - predefined types PortA .. PortH ( in __port_def.h ) * ******* * * ****************************************************************************/ /****************************************************************************** * PUSH-PULL - OUTPUT HIGH - DRAIN CURRENT OUT ****************************************************************************** * ____ * | Q=1|---| * | | | Vcc Vcc Vcc * | | | | | | * |____| | | | | * DDR | | | | * ____ | ___ _| _|_ | | * | | |-| & |____|| /_\ | |(Load) * | Q=1|---(-|___| ||_ | _____ | * | | | |________|_______| PIN |___| HIGH * | | | ___ x| | |_____| | * |/Q=0| |-| & |____|| _|_ | * |____|-----|___| ||x /_\ | | * PORT | | |_| Load * _|_ _|_ _|_ ****************************************************************************** * PUSH-PULL OUTPUT LOW - PORTx==0 - SINK CURRENT IN ****************************************************************************** * ____ * | Q=1|---| * | | | Vcc Vcc Vcc * | | | | | | * |____| | | | | * DDR | | | | * ____ | ___ x| _|_ | | * | | |-| & |____|| /_\ |_| Load * | Q=0|---(-|___| ||x | _____ | * | | | |________|_______| PIN |___| LOW * | | | ___ _| | |_____| | * |/Q=1| |-| & |____|| _|_ | * |____|-----|___| ||_ /_\ | | * PORT | | |_|(Load) * _|_ _|_ _|_ ****************************************************************************** * IN/OUT TRISTATE ****************************************************************************** * ____ * | Q=0|---| * | | | Vcc Vcc Vcc * | | | | | | * |____| | | | | * DDR | | | | * ____ | ___ x| _|_ | | * | | |-| & |____|| /_\ |_| Load * | Q=0|---(-|___| ||x | _____ | * | | | |________|______| PIN |___| * | | | ___ x| | |_____| * |/Q=1| |-| & |____|| _|_ * |____|-----|___| ||x /_\ * PORT | | * _|_ _|_ ******************************************************************************* * INPUT with/without INTERNAL PULLUP RESISTOR ******************************************************************************* * * Vcc * ____ ___ | * | 0|----o| & | _| * |____| ---| |_________|| * PUD | o| | ||_ * ____ | | |___| | * | Q=0|-|-| | * | | | | Vcc | Vcc * | | | | | | | * |____| | | | | | * DDR | | | | | * ____ | | ___ x| | | _|_ * | | | |-| & |____|| |_| /_\ * | Q=1|-|-(-|___| ||x | | _____ * | | | |____|____|____________| PIN |________________ * | | | ___ x| | __|__ |_____| | | * |/Q=0| |-| & |____|| _|_ | STR | | | * |____|-----|___| ||x /_\ |_____| | | | * PORT | | __|__ |_| Load Uin * _|_ _|_ | D L|-<- | | * | | |CLK _|_ _|_ * | | | * |_ Q _| | * __|_____|_ * | D | * |__________| * | PIN * ******************************************************************************/ #pragma once #ifndef IOPORTS_HPP #error "Do not include this file directly. Use ioports.h instead." #endif #ifndef AVR_PORTS_H #define AVR_PORTS_H #include <__compatibility.h> // toolchain #include // ATOMIC #include // AUTO_IO_REG_WRAPPER #include // Util namespace Mcucpp { namespace IO { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class NativePortBase { //******************** public: typedef uint8_t DataT; // enum : uint8_t { MaxBitwiseOutput = 5 }; // enum : uint8_t { Width = sizeof(DataT)*8 }; // public: enum Configuration { //****************** Analog = 0, In = 0x00, Out = 0x01, AltFunc = 0x01 }; enum PullMode { //************* NoPullUp = 0, // unused in AVR PullUp = 1, PullDown = 2 // unused in AVR }; enum DriverType { // unused in AVR //*************** PushPull = 0, OpenDrain = 0 }; enum Speed { // unused in AVR //********** Slow = 0, Fast = 0, Fastest = 0 }; }; /**************************************************************** * Port definitions for AtTiny, AtMega families ***************************************************************/ // ../io.h->| addr | name| type | ioreg.h //---------------|------|-----|---------| template // increasing ID | PortA:0 ... PortH:7 | //**********************// -------------------------------------| class PortImplementation : public NativePortBase { //************************ |prototype----|-----------------------|--------------------------------------------|specialization-recursive---------------|-----| template static inline void SetBitwise () { if(mask == 0) return; if(value & mask) reg::Or (value & mask); SetBitwise (); } // !! RECURSION !! template static inline void ClearBitwise() { if(mask == 0) return; if(value & mask) reg::And(~(value & mask)); ClearBitwise(); } // !! RECURSION !! //template < DataT value, DataT mask> static inline void SetBitwiseIn() { if(mask == 0) return; if(value & mask) in::Or (value & mask); SetBitwiseIn< value, DataT(mask << 1)>(); } // !! RECURSION !! //template < DataT value, DataT mask> static inline void SetBitwise () { if(mask == 0) return; if(value & mask) out::Or (value & mask); SetBitwise < value, DataT(mask << 1)>(); } // !! RECURSION !! //template < DataT value, DataT mask> static inline void ClearBitwise() { if(mask == 0) return; if(value & mask) out::And(~(value & mask)); ClearBitwise< value, DataT(mask << 1)>(); } // !! RECURSION !! public: enum { Id = ID }; static void Write (DataT value ){ Out::Set(value);} static DataT Read ( ){return Out::Get();} static DataT PinRead ( ){return In::Get();} static void Set (DataT value ){ATOMIC Out::Or ( value);} static void Clear (DataT value ){ATOMIC Out::And(~value);} static void Toggle (DataT value ){ATOMIC Out::Xor( value);} static void ClearAndSet (DataT clearMask, DataT value ){ATOMIC Out::AndOr(DataT(~clearMask), value);} static void SetSpeed (DataT mask, Speed speed ){} // unused in AVR static void SetDriverType(DataT mask, DriverType driver){} // unused in AVR static void AltFuncNumber(DataT mask, uint8_t number){} // unused in AVR static void SetPullUp (DataT mask, PullMode pull ){if(pull == PullUp){ ATOMIC{Dir::And(DataT(~mask)); Out::Or ( mask); }}} /************************** * constant interface **************************/ template static void Set() { if(Util::PopulatedBits::value <= MaxBitwiseOutput && Id <4) SetBitWise(); else ATOMIC Out::Or(value); } template static void Clear() { if(Util::PopulatedBits::value <= MaxBitwiseOutput && Id <4) ClearBitWise(); else ATOMIC Out::And(DataT(~value));} template static void Toggle() { if(Util::PopulatedBits::value <= MaxBitwiseOutput && Id <4) SetBitWise(); //a.b. // IN?? else ATOMIC Out::Xor(value);} template // //**************************** static void ClearAndSet() { //*********** const DataT bitsToSet = value & clearMask; const DataT bitsToClear = DataT(~value & clearMask); const unsigned countBitsToChange = Util::PopulatedBits::value; if(countBitsToChange <= MaxBitwiseOutput && Id <4) { SetBitWise (); ClearBitWise(); } else ATOMIC Out::AndOr(DataT(~clearMask), value); } /********************************************* * CONFIGURATION INTERFACE *********************************************/ static void SetConfiguration(DataT mask, Configuration configuration) { //**************** if(configuration) Dir::Or ( mask); else Dir::And(DataT(~mask)); } template // //**************************************** static void SetConfiguration() { //**************** if(configuration) { if(mask == (DataT)-1) Dir::Set(mask); else Dir::Or (mask); } else { if(mask == (DataT)-1) Dir::Set(DataT(~mask)); else Dir::And(DataT(~mask)); } } template // //************************* static void SetPinConfiguration(Configuration configuration) { //******************* STATIC_ASSERT(pin for specific AVR hardware ***************************************************/ #include "__port_def_.h" // ../mcucpp/AVR } //.IO } //.Mcucpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #endif //.AVR_PORTS_H /**************************************************** * - code snippet ..\mcucpp\AVR\[_]_port_def.h **************************************************** * PortImplementation * ****************** * declares for specific AVR hardware a * Class Type for each available uc-port named * PortA, PortB, .. PortX **************************************************** #if defined(__ATMEGAaa__) || \ .. defined(__ATMEGAzz__) #define MCUCPP_HAS_PORTA // HAS_PORTA namespace Private { IO_REG_WRAPPER (PORTA, OutA, uint8_t); IO_REG_WRAPPER (DDRA, DirA, uint8_t); IO_REG_WRAPPER (PINA, InA, uint8_t); } typedef PortImplementation PortA; ... more ports /¦*************************************************************************** * code snippet ..\mcucpp\ioreg.h **************************************************************************** * AVR * ****************************************** * AUTO_IO_REG_WRAPPER * ****************************************** * defines each AVR-Register X by MACRO * ****************************************** * Class CLASS_NAME for X * AVR-Register REG_NAME * register width DATA_TYPE * ****************************************** * auto avoids numerous type casts *************************************************************************** #define AUTO_IO_REG_WRAPPER(REG_NAME, CLASS_NAME, DATA_TYPE) \ \ struct CLASS_NAME { \ typedef DATA_TYPE DataT; \ \ static volatile DataT* Addr() {return ®_NAME ;} \ \ static DataT Get () {return REG_NAME ;} \ static void Set (auto value){ REG_NAME = DataT(value);} \ static void Or (auto value){ REG_NAME |= DataT(value);} \ \ static void And (auto value){ REG_NAME &= DataT(value);} \ static void Xor (auto value){ REG_NAME ^= DataT(value);} \ \ static void AndOr (auto andMask, \ auto orMask ) { REG_NAME = \ ( REG_NAME & DataT( andMask)) \ | DataT( orMask);} \ static void ClrSet (auto andMask, \ auto orMask ) { REG_NAME = \ ( REG_NAME & DataT(~andMask)) \ | DataT( orMask );}\ \ static bool BitIsSet (auto mask) {return (REG_NAME & DataT(mask));} \ static bool BitIsClear(auto mask) {return!(REG_NAME & DataT(mask));} \ }; *************************************************************************** #define IO_REG_WRAPPER(REG_NAME, CLASS_NAME, DATA_TYPE) \ \ struct CLASS_NAME { \ typedef DATA_TYPE DataT; \ \ static volatile DataT* Addr() {return ®_NAME ;} \ \ static DataT Get () {return REG_NAME ;} \ static void Set (DataT value){ REG_NAME = value;} \ static void Or (DataT value){ REG_NAME |= value;} \ static void And (DataT value){ REG_NAME &= value;} \ static void Xor (DataT value){ REG_NAME ^= value;} \ \ static void AndOr (DataT andMask, \ DataT orMask ) { REG_NAME = \ ( REG_NAME & andMask) \ | orMask ;} \ static void ClrSet (DataT andMask, \ DataT orMask ) { REG_NAME = \ ( REG_NAME & andMask) \ | orMask ;} \ template \ static bool BitIsSet () {return (REG_NAME & (1 < \ static bool BitIsClear() {return!(REG_NAME & (1 <= 100 // # define __SFR_OFFSET 0x00 # else // # define __SFR_OFFSET 0x20 # endif #endif #define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) #define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr)) #define _MMIO_DWORD(mem_addr) (*(volatile uint32_t *)(mem_addr)) #define _SFR_MEM8(mem_addr) _MMIO_BYTE(mem_addr) #define _SFR_MEM16(mem_addr) _MMIO_WORD(mem_addr) #define _SFR_MEM32(mem_addr) _MMIO_DWORD(mem_addr) #define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET) #define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + __SFR_OFFSET) https://github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/AVR/GPIO.h */