#ifndef __JABYENGINE_IOPORT_HPP__ #define __JABYENGINE_IOPORT_HPP__ #include "../../Auxiliary/bits.hpp" struct ClearBitValue { size_t bit; constexpr ClearBitValue(size_t bit) : bit(bit) { } }; template struct Bit { typedef T ValueType; size_t value; constexpr Bit(size_t value) : value(value) { } constexpr operator size_t() const { return this->value; } constexpr ClearBitValue operator!() const { return ClearBitValue(this->value); } }; template struct BitRangeValue { T value; size_t begin; size_t length; }; template struct BitRange { typedef T ValueType; size_t begin; size_t length; static constexpr BitRange from_to(size_t start, size_t end) { return {start, (end - start + 1)}; } constexpr BitRangeValue with(T value) const { return {value, this->begin, this->length}; } }; template static constexpr __always_inline BitRangeValue operator<<(const BitRange& range, T value) { return BitRangeValue{value, range.begin, range.length}; } template class __no_align ComplexBitMap { private: T value = 0; template constexpr ComplexBitMap& set_va(const S& value) { return this->set(value); } template constexpr ComplexBitMap& set_va(const S& value, const ARGS&...args) { return this->set_va(value).set_va(args...); } public: constexpr ComplexBitMap() = default; constexpr ComplexBitMap(T value) : value(value) { } template static constexpr ComplexBitMap with(ARGS...args) { return ComplexBitMap().set_va(args...); } //Accesssing bits template constexpr ComplexBitMap& set_bit(S bit) { this->value = bit::set(this->value, static_cast(bit)); return *this; } template constexpr void set_bit(S bit) volatile { this->value = bit::set(this->value, static_cast(bit)); } template constexpr ComplexBitMap& clear_bit(S bit) { this->value = bit::clear(this->value, static_cast(bit)); return *this; } template constexpr void clear_bit(S bit) volatile { this->value = bit::clear(this->value, static_cast(bit)); } template constexpr bool is_bit_set(S bit) { return bit::is_set(this->value, static_cast(bit)); } template constexpr bool is_bit_set(S bit) volatile { return bit::is_set(this->value, static_cast(bit)); } //Accessing values template constexpr ComplexBitMap& set_value(S value, const BitRange& range) { this->value = bit::value::set_normalized(this->value, static_cast(value), range.begin, range.length); return *this; } template constexpr void set_value(S value, const BitRange& range) volatile { this->value = bit::value::set_normalized(this->value, static_cast(value), range.begin, range.length); } template constexpr ComplexBitMap& clear_value(const BitRange& range) { this->value = bit::value::clear_normalized(this->value, range.begin, range.length); return *this; } template constexpr void clear_value(const BitRange& range) volatile { this->value = bit::value::clear_normalized(this->value, range.begin, range.length); } template constexpr S get_value(const BitRange& range) { return static_cast(bit::value::get_normalized(this->value, range.begin, range.length)); } template constexpr S get_value(const BitRange& range) volatile { return static_cast(bit::value::get_normalized(this->value, range.begin, range.length)); } // For easier constructing constexpr ComplexBitMap& set(const BitRange& range, T value) { this->set_value(value, range); return *this; } constexpr ComplexBitMap& set(const BitRangeValue& value) { this->set_value(value.value, {value.begin, value.length}); return *this; } constexpr ComplexBitMap& set(const Bit& bit) { this->set_bit(bit.value); return *this; } constexpr ComplexBitMap& set(const ClearBitValue& value) { this->clear_bit(value.bit); return *this; } constexpr ComplexBitMap& operator|(const BitRangeValue& value) { this->set_value(value.value, value.range); return *this; } constexpr ComplexBitMap& operator|(const Bit& bit) { this->set_bit(bit.value); return *this; } constexpr ComplexBitMap& operator|(const ClearBitValue& value) { this->clear_bit(value.bit); return *this; } //For raw access constexpr operator T() const { return this->value; } constexpr operator T() const volatile { return this->value; } constexpr ComplexBitMap& operator=(T value) { this->value = value; return *this; } constexpr void operator=(T value) volatile { this->value = value; } }; template class __no_align IOPort { private: T value; public: //For easy access constexpr T read() const { return const_cast*>(this)->value; } constexpr void write(T value) { const_cast*>(this)->value = value; } constexpr volatile T& ref() { return const_cast*>(this)->value; } }; struct __no_align ubus32_t { ComplexBitMap low; ComplexBitMap high; constexpr ubus32_t(uint32_t value) { *this = value; } constexpr operator uint32_t() const { return ((this->high << 16) | this->low); } constexpr operator uint32_t() const volatile { return ((this->high << 16) | this->low); } constexpr ubus32_t& operator=(uint32_t value) { this->low = (value & 0xFFFF); this->high = (value >> 16); return *this; } constexpr void operator=(uint32_t value) volatile { this->low = (value & 0xFFFF); this->high = (value >> 16); } }; static constexpr uintptr_t IO_Base_Mask = 0xF0000000; static constexpr uintptr_t IO_Base_Adr = 0x10000000; #define __declare_io_port_global(type, name, adr) static __always_inline auto& name = *reinterpret_cast*>((IO_Base_Adr + (adr & ~IO_Base_Mask))) #define __declare_io_port_global_array(type, name, adr, size) static __always_inline auto& name = reinterpret_cast(*reinterpret_cast((IO_Base_Adr + (adr & ~IO_Base_Mask)))); #define __io_port_inherit_complex_bit_map(name) \ using ComplexBitMap::operator=; \ constexpr name() = default; \ constexpr name(ComplexBitMap value) : ComplexBitMap(value) { \ }\ template \ constexpr name(ARGS...args) : ComplexBitMap(args...) {\ } #endif //!__JABYENGINE_IOPORT_HPP__