///\file /****************************************************************************** The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com Copyright(c) 2014 John Wellbelove Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions : The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ #ifndef ETL_IO_PORT_INCLUDED #define ETL_IO_PORT_INCLUDED ///\defgroup io_port io_port /// IO port access ///\ingroup utilities #include "platform.h" #include "nullptr.h" #include "iterator.h" #include "utility.h" #include "static_assert.h" #include namespace etl { template class io_port_rw; namespace private_io_port { //*************************************************************************** /// Common io_port iterator implementation //*************************************************************************** template class iterator : public etl::iterator { public: //******************************** /// Allow TIO_Port access //******************************** friend TIO_Port; //******************************** /// Allow const_iterator access //******************************** template friend class const_iterator; //******************************** /// Types //******************************** typedef TIO_Port io_port_type; typedef typename TIO_Port::value_type value_type; //******************************** /// //******************************** iterator() : p_iop(ETL_NULLPTR) { } //******************************** /// //******************************** iterator(const iterator& other) : p_iop(other.p_iop) { } //******************************** /// //******************************** iterator& operator =(const iterator& other) { p_iop = other.p_iop; return *this; } //******************************** /// //******************************** io_port_type& operator *() { return *p_iop; } //******************************** /// //******************************** const io_port_type& operator *() const { return *p_iop; } //******************************** /// Pre-increment operator. //******************************** iterator& operator ++() { return *this; } //******************************** /// Post-increment operator. //******************************** iterator operator ++(int) { return *this; } private: //******************************** /// //******************************** iterator(io_port_type& iop) : p_iop(&iop) { } io_port_type* p_iop; }; //*************************************************************************** /// Common io_port const_iterator implementation //*************************************************************************** template class const_iterator : public etl::iterator { private: typedef etl::private_io_port::iterator iterator_type; public: //******************************** /// Allow TIO_Port access //******************************** friend TIO_Port; //******************************** /// Types //******************************** typedef TIO_Port io_port_type; typedef const typename TIO_Port::value_type value_type; //******************************** /// //******************************** const_iterator() : p_iop(ETL_NULLPTR) { } //******************************** /// //******************************** const_iterator(const iterator_type& other) : p_iop(other.p_iop) { } //******************************** /// //******************************** const_iterator(const const_iterator& other) : p_iop(other.p_iop) { } //******************************** /// //******************************** const_iterator& operator =(const iterator_type& other) { p_iop = other.p_iop; return *this; } //******************************** /// //******************************** const_iterator& operator =(const const_iterator& other) { p_iop = other.p_iop; return *this; } //******************************** /// //******************************** const io_port_type& operator *() const { return *p_iop; } //******************************** /// Pre-increment operator. //******************************** const_iterator& operator ++() { return *this; } //******************************** /// Post-increment operator. //******************************** const_iterator operator ++(int) { return *this; } private: //******************************** /// //******************************** const_iterator(const io_port_type& iop) : p_iop(&iop) { } const io_port_type* p_iop; }; } //*************************************************************************** /// Read write port. //*************************************************************************** template class io_port_rw { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::iterator > iterator; typedef etl::private_io_port::const_iterator > const_iterator; //********************************** /// Get an iterator to this port. //********************************** iterator iter() { return iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator iter() const { return const_iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator citer() const { return const_iterator(*this); } //********************************** /// Read. //********************************** operator value_type() const { return *reinterpret_cast(Address); } //********************************** /// Read. //********************************** value_type read() const { return *reinterpret_cast(Address); } //********************************** /// Write. //********************************** void write(value_type value_) { *reinterpret_cast(Address) = value_; } //********************************** /// Write. //********************************** io_port_rw& operator =(value_type value_) { *reinterpret_cast(Address) = value_; return *this; } //********************************** /// Or-Equals operator. //********************************** io_port_rw& operator |=(value_type value) { pointer address = reinterpret_cast(Address); value_type temp = *address; temp |= value; *address = temp; return *this; } //********************************** /// And-Equals operator. //********************************** io_port_rw& operator &=(value_type value) { pointer address = reinterpret_cast(Address); value_type temp = *address; temp &= value; *address = temp; return *this; } //********************************** /// Exclusive-Or-Equals operator. //********************************** io_port_rw& operator ^=(value_type value) { pointer address = reinterpret_cast(Address); value_type temp = *address; temp ^= value; *address = temp; return *this; } //********************************** /// Left-Shift-Equals operator. //********************************** io_port_rw& operator <<=(int shift) { pointer address = reinterpret_cast(Address); value_type temp = *address; temp <<= shift; *address = temp; return *this; } //********************************** /// Right-Shift-Equals operator. //********************************** io_port_rw& operator >>=(int shift) { pointer address = reinterpret_cast(Address); value_type temp = *address; temp >>= shift; *address = temp; return *this; } //********************************** /// Not operator. //********************************** value_type operator ~() const { return ~(*reinterpret_cast(Address)); } //********************************** /// Get the IO port address. //********************************** pointer get_address() { return reinterpret_cast(Address); } //********************************** /// Get the IO port address. //********************************** const_pointer get_address() const { return reinterpret_cast(Address); } private: /// Disabled. io_port_rw& operator =(const io_port_rw&); }; //*************************************************************************** /// Read only port. //*************************************************************************** template class io_port_ro { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::const_iterator > const_iterator; //********************************** /// Get a const_iterator to this port. //********************************** const_iterator iter() const { return const_iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator citer() const { return const_iterator(*this); } //********************************** /// Read. //********************************** operator value_type() const { return *reinterpret_cast(Address); } //********************************** /// Read. //********************************** value_type read() const { return *reinterpret_cast(Address); } //********************************** /// Get the IO port address. //********************************** pointer get_address() { return reinterpret_cast(Address); } //********************************** /// Get the IO port address. //********************************** const_pointer get_address() const { return reinterpret_cast(Address); } private: /// Write disabled. void operator =(value_type value) ETL_DELETE; /// Disabled. io_port_ro& operator =(const io_port_ro&) ETL_DELETE; }; //*************************************************************************** /// Write only port. //*************************************************************************** template class io_port_wo { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::iterator > iterator; //********************************** /// Get an iterator to this port. //********************************** iterator iter() { return iterator(*this); } //********************************** /// Write. //********************************** void operator =(value_type value) { *reinterpret_cast(Address) = value; } //********************************** /// Write. //********************************** void write(value_type value_) { *reinterpret_cast(Address) = value_; } //********************************** /// Get the IO port address. //********************************** pointer get_address() { return reinterpret_cast(Address); } //********************************** /// Get the IO port address. //********************************** const_pointer get_address() const { return reinterpret_cast(Address); } private: /// Read disabled. operator value_type() const ETL_DELETE; /// Disabled. io_port_wo& operator =(const io_port_wo&) ETL_DELETE; }; //*************************************************************************** /// Write only port with shadow register. //*************************************************************************** template class io_port_wos { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::iterator > iterator; typedef etl::private_io_port::const_iterator > const_iterator; //********************************** /// Default constructor. //********************************** io_port_wos() : shadow_value(value_type()) { } //********************************** /// Get an iterator to this port. //********************************** iterator iter() { return iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator iter() const { return const_iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator citer() const { return const_iterator(*this); } //********************************** /// Read. //********************************** operator value_type() const { return shadow_value; } //********************************** /// Read. //********************************** value_type read() const { return shadow_value; } //********************************** /// Write. //********************************** void write(value_type value_) { shadow_value = value_; *reinterpret_cast(Address) = shadow_value; } //********************************** /// Write. //********************************** io_port_wos& operator =(value_type value_) { shadow_value = value_; *reinterpret_cast(Address) = shadow_value; return *this; } //********************************** /// Or-Equals operator. //********************************** io_port_wos& operator |=(value_type value) { shadow_value |= value; *reinterpret_cast(Address) = shadow_value; return *this; } //********************************** /// And-Equals operator. //********************************** io_port_wos& operator &=(value_type value) { shadow_value &= value; *reinterpret_cast(Address) = shadow_value; return *this; } //********************************** /// Exclusive-Or-Equals operator. //********************************** io_port_wos& operator ^=(value_type value) { shadow_value ^= value; *reinterpret_cast(Address) = shadow_value; return *this; } //********************************** /// Left-Shift-Equals operator. //********************************** io_port_wos& operator <<=(int shift) { shadow_value <<= shift; *reinterpret_cast(Address) = shadow_value; return *this; } //********************************** /// Right-Shift-Equals operator. //********************************** io_port_wos& operator >>=(int shift) { shadow_value >>= shift; *reinterpret_cast(Address) = shadow_value; return *this; } //********************************** /// Not operator. //********************************** value_type operator ~() const { return ~shadow_value; } //********************************** /// Get the IO port address. //********************************** pointer get_address() { return reinterpret_cast(Address); } private: /// Disabled. io_port_wos& operator =(const io_port_wos&); value_type shadow_value; }; //*************************************************************************** /// Read write port. /// Specialisation for dynamic addresses. //*************************************************************************** template class io_port_rw { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::iterator > iterator; typedef etl::private_io_port::const_iterator > const_iterator; //********************************** /// Default constructor. //********************************** io_port_rw() : address(ETL_NULLPTR) { } //********************************** /// Constructor. //********************************** io_port_rw(void* address_) : address(reinterpret_cast(address_)) { } //********************************** /// Copy Constructor. //********************************** io_port_rw(const io_port_rw& other_) : address(reinterpret_cast(other_.address)) { } //********************************** /// Assignment. //********************************** io_port_rw& operator =(const io_port_rw& other_) { address = other_.address; return *this; } //********************************** /// Get an iterator to this port. //********************************** iterator iter() { return iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator iter() const { return const_iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator citer() const { return const_iterator(*this); } //********************************** /// Or-Equals operator. //********************************** io_port_rw& operator |=(value_type value) { value_type temp = *address; temp |= value; *address = temp; return *this; } //********************************** /// And-Equals operator. //********************************** io_port_rw& operator &=(value_type value) { value_type temp = *address; temp &= value; *address = temp; return *this; } //********************************** /// Exclusive-Or-Equals operator. //********************************** io_port_rw& operator ^=(value_type value) { value_type temp = *address; temp ^= value; *address = temp; return *this; } //********************************** /// Left-Shift-Equals operator. //********************************** io_port_rw& operator <<=(int shift) { value_type temp = *address; temp <<= shift; *address = temp; return *this; } //********************************** /// Right-Shift-Equals operator. //********************************** io_port_rw& operator >>=(int shift) { value_type temp = *address; temp >>= shift; *address = temp; return *this; } //********************************** /// Not operator. //********************************** value_type operator ~() const { return ~(*address); } //********************************** /// Set the IO port address. //********************************** void set_address(void* address_) { address = reinterpret_cast(address_); } //********************************** /// Get the IO port address. //********************************** pointer get_address() { return address; } //********************************** /// Get the IO port address. //********************************** const_pointer get_address() const { return address; } //********************************** /// Read. //********************************** operator value_type() const { return *address; } //********************************** /// Read. //********************************** value_type read() const { return *address; } //********************************** /// Write. //********************************** void write(value_type value_) { *address = value_; } //********************************** /// Write. //********************************** io_port_rw& operator =(value_type value_) { *address = value_; return *this; } private: pointer address; }; //*************************************************************************** /// Read only port. /// Specialisation for dynamic addresses. //*************************************************************************** template class io_port_ro { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::const_iterator > const_iterator; //********************************** /// Default constructor. //********************************** io_port_ro() : address(ETL_NULLPTR) { } //********************************** /// Constructor. //********************************** io_port_ro(void* address_) : address(reinterpret_cast(address_)) { } //********************************** /// Copy Constructor. //********************************** io_port_ro(const io_port_ro& other_) : address(reinterpret_cast(other_.address)) { } //********************************** /// Assignment. //********************************** io_port_ro& operator =(const io_port_ro& other_) { address = other_.address; return *this; } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator iter() const { return const_iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator citer() const { return const_iterator(*this); } //********************************** /// Set the IO port address. //********************************** void set_address(void* address_) { address = reinterpret_cast(address_); } //********************************** /// Get the IO port address. //********************************** const_pointer get_address() const { return address; } //********************************** /// Read. //********************************** operator value_type() const { return *address; } //********************************** /// Read. //********************************** value_type read() const { return *address; } private: /// Write disabled. void operator =(value_type value) ETL_DELETE; pointer address; }; //*************************************************************************** /// Write only port. /// Specialisation for dynamic addresses. //*************************************************************************** template class io_port_wo { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::iterator > iterator; //********************************** /// Default constructor. //********************************** io_port_wo() : address(ETL_NULLPTR) { } //********************************** /// Constructor. //********************************** io_port_wo(void* address_) : address(reinterpret_cast(address_)) { } //********************************** /// Copy Constructor. //********************************** io_port_wo(const io_port_wo& other_) : address(reinterpret_cast(other_.address)) { } //********************************** /// Assignment. //********************************** io_port_wo& operator =(const io_port_wo& other_) { address = other_.address; return *this; } //********************************** /// Get an iterator to this port. //********************************** iterator iter() { return iterator(*this); } //********************************** /// Set the IO port address. //********************************** void set_address(void* address_) { address = reinterpret_cast(address_); } //********************************** /// Get the IO port address. //********************************** pointer get_address() { return address; } //********************************** /// Get the IO port address. //********************************** const_pointer get_address() const { return address; } //********************************** /// Write. //********************************** void write(value_type value_) { *address = value_; } //********************************** /// Write. //********************************** void operator =(value_type value) { *address = value; } private: /// Read disabled. operator value_type() const ETL_DELETE; pointer address; }; //*************************************************************************** /// Write only port with shadow register. /// Specialisation for dynamic addresses. //*************************************************************************** template class io_port_wos { public: ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); typedef T value_type; typedef volatile T* pointer; typedef volatile const T* const_pointer; typedef volatile T& reference; typedef volatile const T& const_reference; typedef etl::private_io_port::iterator > iterator; typedef etl::private_io_port::const_iterator > const_iterator; //********************************** /// Default constructor. //********************************** io_port_wos() : shadow_value(T()) , address(ETL_NULLPTR) { } //********************************** /// Constructor. //********************************** io_port_wos(void* address_) : shadow_value(T()) , address(reinterpret_cast(address_)) { } //********************************** /// Copy Constructor. //********************************** io_port_wos(const io_port_wos& other_) : shadow_value(other_.shadow_value) , address(reinterpret_cast(other_.address)) { } //********************************** /// Assignment. //********************************** io_port_wos& operator =(const io_port_wos& other_) { shadow_value = other_.shadow_value; address = other_.address; return *this; } //********************************** /// Get an iterator to this port. //********************************** iterator iter() { return iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator iter() const { return const_iterator(*this); } //********************************** /// Get a const_iterator to this port. //********************************** const_iterator citer() const { return const_iterator(*this); } //********************************** /// Or-Equals operator. //********************************** io_port_wos& operator |=(value_type value) { shadow_value |= value; *address = shadow_value; return *this; } //********************************** /// And-Equals operator. //********************************** io_port_wos& operator &=(value_type value) { shadow_value &= value; *address = shadow_value; return *this; } //********************************** /// Exclusive-Or-Equals operator. //********************************** io_port_wos& operator ^=(value_type value) { shadow_value ^= value; *address = shadow_value; return *this; } //********************************** /// Left-Shift-Equals operator. //********************************** io_port_wos& operator <<=(int shift) { shadow_value <<= shift; *address = shadow_value; return *this; } //********************************** /// Right-Shift-Equals operator. //********************************** io_port_wos& operator >>=(int shift) { shadow_value >>= shift; *address = shadow_value; return *this; } //********************************** /// Not operator. //********************************** value_type operator ~() const { return ~shadow_value; } //********************************** /// Set the IO port address. //********************************** void set_address(void* address_) { address = reinterpret_cast(address_); } //********************************** /// Get the IO port address. //********************************** pointer get_address() { return address; } //********************************** /// Get the IO port address. //********************************** const_pointer get_address() const { return address; } //********************************** /// Read. //********************************** operator value_type() const { return shadow_value; } //********************************** /// Read. //********************************** value_type read() const { return shadow_value; } //********************************** /// Write. //********************************** void write(value_type value_) { shadow_value = value_; *address = shadow_value; } //********************************** /// Write. //********************************** io_port_wos& operator =(value_type value_) { shadow_value = value_; *address = shadow_value; return *this; } //********************************** /// Read / Write //********************************** io_port_wos& operator *() { return *this; } //********************************** /// Read //********************************** const_reference operator *() const { return shadow_value; } private: value_type shadow_value; pointer address; }; } #endif