Compare commits

..

No commits in common. "d89322bdaae6c08bedc65209373e0a1fc5c9af05" and "80de36ee7ee3e6b0842d5eaee81d54062cb496b2" have entirely different histories.

190
io.hpp
View File

@ -45,6 +45,8 @@
#define PIN_C7_AVAILABLE #define PIN_C7_AVAILABLE
#endif #endif
#define FORCE_INLINE __attribute__((always_inline))
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Library implementation // Library implementation
@ -102,8 +104,6 @@ enum class P {
D6 = 0x36, D6 = 0x36,
D7 = 0x37, D7 = 0x37,
#endif #endif
NONE,
}; };
enum class Bus { enum class Bus {
@ -119,8 +119,6 @@ enum class Bus {
#ifdef PORT_D_AVAILABLE #ifdef PORT_D_AVAILABLE
D = 0x03, D = 0x03,
#endif #endif
NONE,
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -252,7 +250,7 @@ static inline reg_ptr_t getRegPtr()
template <template <P, uint8_t> typename Func, P pin, P... pins> template <template <P, uint8_t> typename Func, P pin, P... pins>
struct CallHelper { struct CallHelper {
template <typename... Args> template <typename... Args>
[[gnu::always_inline]] static inline void call(Args... args) FORCE_INLINE static inline void call(Args... args)
{ {
Func<pin, sizeof...(pins)>::call(args...); Func<pin, sizeof...(pins)>::call(args...);
CallHelper<Func, pins...>::call(args...); CallHelper<Func, pins...>::call(args...);
@ -262,7 +260,7 @@ struct CallHelper {
template <template <P, uint8_t> typename Func, P pin> template <template <P, uint8_t> typename Func, P pin>
struct CallHelper<Func, pin> { struct CallHelper<Func, pin> {
template <typename... Args> template <typename... Args>
[[gnu::always_inline]] static inline void call(Args... args) FORCE_INLINE static inline void call(Args... args)
{ {
Func<pin, 0>::call(args...); Func<pin, 0>::call(args...);
} }
@ -270,7 +268,7 @@ struct CallHelper<Func, pin> {
template <template <P> typename Func, P pin, P... pins> template <template <P> typename Func, P pin, P... pins>
struct ReadCallHelper { struct ReadCallHelper {
[[gnu::always_inline]] static inline uint8_t call() static inline uint8_t call() FORCE_INLINE
{ {
return Func<pin>::call() << sizeof...(pins) | ReadCallHelper<Func, pins...>::call(); return Func<pin>::call() << sizeof...(pins) | ReadCallHelper<Func, pins...>::call();
} }
@ -278,7 +276,7 @@ struct ReadCallHelper {
template <template <P> typename Func, P pin> template <template <P> typename Func, P pin>
struct ReadCallHelper<Func, pin> { struct ReadCallHelper<Func, pin> {
[[gnu::always_inline]] static inline uint8_t call() static inline uint8_t call() FORCE_INLINE
{ {
return Func<pin>::call(); return Func<pin>::call();
} }
@ -301,88 +299,79 @@ class Pin {
// The only valid way to create a Pin object is with the default constructor // The only valid way to create a Pin object is with the default constructor
Pin() = default; Pin() = default;
[[gnu::always_inline]] static inline void dir(const Dir dir) static inline void dir(const Dir dir) FORCE_INLINE
{ {
if constexpr (pin != P::NONE) { constexpr auto bus = detail::getBus(pin);
constexpr auto bus = detail::getBus(pin); constexpr auto pinBit = detail::getPinBit(pin);
constexpr auto pinBit = detail::getPinBit(pin);
detail::reg_ptr_t dirRegPtr = detail::getRegPtr<detail::getDDR(bus)>(); detail::reg_ptr_t dirRegPtr = detail::getRegPtr<detail::getDDR(bus)>();
if (dir == Dir::IN) if (dir == Dir::IN)
*dirRegPtr &= ~(1 << pinBit); *dirRegPtr &= ~(1 << pinBit);
else if (dir == Dir::OUT) else if (dir == Dir::OUT)
*dirRegPtr |= (1 << pinBit); *dirRegPtr |= (1 << pinBit);
}
} }
[[gnu::always_inline]] static inline void pullup(const bool enable) static inline void pullup(const bool enable) FORCE_INLINE
{ {
if constexpr (pin != P::NONE) { constexpr auto bus = detail::getBus(pin);
constexpr auto bus = detail::getBus(pin); constexpr auto pinBit = detail::getPinBit(pin);
constexpr auto pinBit = detail::getPinBit(pin);
detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(bus)>(); detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(bus)>();
if (enable) if (enable)
*portRegPtr |= (1 << pinBit); *portRegPtr |= (1 << pinBit);
else else
*portRegPtr &= ~(1 << pinBit); *portRegPtr &= ~(1 << pinBit);
}
} }
[[gnu::always_inline]] static inline void write(const bool value) static inline void write(const bool value) FORCE_INLINE
{ {
if constexpr (pin != P::NONE) { constexpr auto bus = detail::getBus(pin);
constexpr auto bus = detail::getBus(pin); constexpr auto pinBit = detail::getPinBit(pin);
constexpr auto pinBit = detail::getPinBit(pin);
detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(bus)>(); detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(bus)>();
if (value) if (value)
*portRegPtr |= (1 << pinBit); *portRegPtr |= (1 << pinBit);
else else
*portRegPtr &= ~(1 << pinBit); *portRegPtr &= ~(1 << pinBit);
}
} }
[[gnu::always_inline]] static inline void toggle() static inline void toggle() FORCE_INLINE
{ {
if constexpr (pin != P::NONE) { constexpr auto bus = detail::getBus(pin);
constexpr auto bus = detail::getBus(pin); constexpr auto pinBit = detail::getPinBit(pin);
constexpr auto pinBit = detail::getPinBit(pin);
#ifdef HARDWARE_TOGGLE #ifdef HARDWARE_TOGGLE
detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(bus)>(); detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(bus)>();
*pinRegPtr |= (1 << pinBit); *pinRegPtr |= (1 << pinBit);
#else #else
detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(bus)>(); detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(bus)>();
*portRegPtr ^= (1 << pinBit); *portRegPtr ^= (1 << pinBit);
#endif #endif
}
} }
[[gnu::always_inline]] static inline bool read() static inline bool read() FORCE_INLINE
{ {
if constexpr (pin != P::NONE) { constexpr auto bus = detail::getBus(pin);
constexpr auto bus = detail::getBus(pin); constexpr auto pinBit = detail::getPinBit(pin);
constexpr auto pinBit = detail::getPinBit(pin);
detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(bus)>(); detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(bus)>();
if (*pinRegPtr >> pinBit & 1)
return true;
if (*pinRegPtr >> pinBit & 1)
return true;
}
return false; return false;
} }
[[gnu::always_inline]] Pin &operator=(const bool value) Pin &operator=(const bool value) FORCE_INLINE
{ {
write(value); write(value);
return *this; return *this;
} }
[[gnu::always_inline]] operator bool() const operator bool() const FORCE_INLINE
{ {
return read(); return read();
} }
@ -403,68 +392,57 @@ class Port {
// The only valid way to create a Port object is with the default constructor // The only valid way to create a Port object is with the default constructor
Port() = default; Port() = default;
[[gnu::always_inline]] static inline void dir(const Dir dir) static inline void dir(const Dir dir) FORCE_INLINE
{ {
if constexpr (port != Bus::NONE) { detail::reg_ptr_t dirRegPtr = detail::getRegPtr<detail::getDDR(port)>();
detail::reg_ptr_t dirRegPtr = detail::getRegPtr<detail::getDDR(port)>();
if (dir == Dir::IN) if (dir == Dir::IN)
*dirRegPtr = 0x00; *dirRegPtr = 0x00;
else if (dir == Dir::OUT) else if (dir == Dir::OUT)
*dirRegPtr = 0xFF; *dirRegPtr = 0xFF;
}
} }
[[gnu::always_inline]] static inline void pullup(const bool enable) static inline void pullup(const bool enable) FORCE_INLINE
{ {
if constexpr (port != Bus::NONE) { detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(port)>();
detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(port)>();
if (enable) if (enable)
*portRegPtr = 0xFF; *portRegPtr = 0xFF;
else else
*portRegPtr = 0x00; *portRegPtr = 0x00;
}
} }
[[gnu::always_inline]] static inline void write([[maybe_unused]] const uint8_t value) static inline void write(const uint8_t value) FORCE_INLINE
{ {
if constexpr (port != Bus::NONE) { detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(port)>();
detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(port)>(); *portRegPtr = value;
*portRegPtr = value;
}
} }
[[gnu::always_inline]] static inline void invert() static inline void invert() FORCE_INLINE
{ {
if constexpr (port != Bus::NONE) {
#ifdef HARDWARE_TOGGLE #ifdef HARDWARE_TOGGLE
detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(port)>(); detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(port)>();
*pinRegPtr = 0xFF; *pinRegPtr = 0xFF;
#else #else
detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(port)>(); detail::reg_ptr_t portRegPtr = detail::getRegPtr<detail::getPORT(port)>();
*portRegPtr = ~(*portRegPtr); *portRegPtr = ~(*portRegPtr);
#endif #endif
}
} }
[[gnu::always_inline]] static inline uint8_t read() static inline uint8_t read() FORCE_INLINE
{ {
if constexpr (port != Bus::NONE) { detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(port)>();
detail::reg_ptr_t pinRegPtr = detail::getRegPtr<detail::getPIN(port)>();
return *pinRegPtr; return *pinRegPtr;
}
return 0x00;
} }
[[gnu::always_inline]] inline Port &operator=(const uint8_t value) inline Port &operator=(const uint8_t value) FORCE_INLINE
{ {
write(value); write(value);
return *this; return *this;
} }
[[gnu::always_inline]] inline operator uint8_t() const inline operator uint8_t() const FORCE_INLINE
{ {
return read(); return read();
} }
@ -477,22 +455,22 @@ namespace detail {
template <P pin, uint8_t offset> template <P pin, uint8_t offset>
struct Callers { struct Callers {
[[gnu::always_inline]] static void call(const Dir dir) static void call(const Dir dir) FORCE_INLINE
{ {
Pin<pin>::dir(dir); Pin<pin>::dir(dir);
}; };
[[gnu::always_inline]] static void call(const bool enable) static void call(const bool enable) FORCE_INLINE
{ {
Pin<pin>::pullup(enable); Pin<pin>::pullup(enable);
}; };
[[gnu::always_inline]] static void call(const uint8_t value) static void call(const uint8_t value) FORCE_INLINE
{ {
Pin<pin>::write(value >> offset & 1); Pin<pin>::write(value >> offset & 1);
}; };
[[gnu::always_inline]] static void call() static void call() FORCE_INLINE
{ {
Pin<pin>::toggle(); Pin<pin>::toggle();
}; };
@ -500,7 +478,7 @@ struct Callers {
template <P pin> template <P pin>
struct readCaller { struct readCaller {
[[gnu::always_inline]] static bool call() static bool call() FORCE_INLINE
{ {
return Pin<pin>::read(); return Pin<pin>::read();
}; };
@ -522,38 +500,38 @@ class VirtPort {
// The only valid way to create a VirtPort object is with the default constructor // The only valid way to create a VirtPort object is with the default constructor
VirtPort() = default; VirtPort() = default;
[[gnu::always_inline]] static inline void dir(const Dir dir) static inline void dir(const Dir dir) FORCE_INLINE
{ {
detail::CallHelper<detail::Callers, pins...>::call(dir); detail::CallHelper<detail::Callers, pins...>::call(dir);
} }
[[gnu::always_inline]] static inline void pullup(const bool enable) static inline void pullup(const bool enable) FORCE_INLINE
{ {
detail::CallHelper<detail::Callers, pins...>::call(enable); detail::CallHelper<detail::Callers, pins...>::call(enable);
} }
[[gnu::always_inline]] static inline void write(const uint8_t value) static inline void write(const uint8_t value) FORCE_INLINE
{ {
detail::CallHelper<detail::Callers, pins...>::call(value); detail::CallHelper<detail::Callers, pins...>::call(value);
} }
[[gnu::always_inline]] static inline void invert() static inline void invert() FORCE_INLINE
{ {
detail::CallHelper<detail::Callers, pins...>::call(); detail::CallHelper<detail::Callers, pins...>::call();
} }
[[gnu::always_inline]] static inline uint8_t read() static inline uint8_t read() FORCE_INLINE
{ {
return detail::ReadCallHelper<detail::readCaller, pins...>::call(); return detail::ReadCallHelper<detail::readCaller, pins...>::call();
} }
[[gnu::always_inline]] inline VirtPort &operator=(const uint8_t value) inline VirtPort &operator=(const uint8_t value) FORCE_INLINE
{ {
write(value); write(value);
return *this; return *this;
} }
[[gnu::always_inline]] inline operator uint8_t() const inline operator uint8_t() const FORCE_INLINE
{ {
return read(); return read();
} }
@ -575,3 +553,5 @@ class VirtPort {
#undef PIN_B6_AVAILABLE #undef PIN_B6_AVAILABLE
#undef PIN_B7_AVAILABLE #undef PIN_B7_AVAILABLE
#undef PIN_C7_AVAILABLE #undef PIN_C7_AVAILABLE
#undef FORCE_INLINE