Implemented virtual port convenience object

This commit is contained in:
BlackMark 2020-02-01 22:07:52 +01:00
parent 986ceef65d
commit cde4f9beda

122
io.hpp
View File

@ -247,6 +247,41 @@ static inline reg_ptr_t getRegPtr()
return reinterpret_cast<reg_ptr_t>(Address);
}
template <template <P, uint8_t> typename Func, P pin, P... pins>
struct CallHelper {
template <typename... Args>
FORCE_INLINE static inline void call(Args... args)
{
Func<pin, sizeof...(pins)>::call(args...);
CallHelper<Func, pins...>::call(args...);
}
};
template <template <P, uint8_t> typename Func, P pin>
struct CallHelper<Func, pin> {
template <typename... Args>
FORCE_INLINE static inline void call(Args... args)
{
Func<pin, 0>::call(args...);
}
};
template <template <P> typename Func, P pin, P... pins>
struct ReadCallHelper {
static inline uint8_t call() FORCE_INLINE
{
return Func<pin>::call() << sizeof...(pins) | ReadCallHelper<Func, pins...>::call();
}
};
template <template <P> typename Func, P pin>
struct ReadCallHelper<Func, pin> {
static inline uint8_t call() FORCE_INLINE
{
return Func<pin>::call();
}
};
} // namespace detail
//////////////////////////////////////////////////////////////////////////
@ -413,6 +448,93 @@ class Port {
}
};
//////////////////////////////////////////////////////////////////////////
// Zero overhead Virtual Port object for pretty code without losing performance
namespace detail {
template <P pin, uint8_t offset>
struct Callers {
static void call(const Dir dir) FORCE_INLINE
{
Pin<pin>::dir(dir);
};
static void call(const bool enable) FORCE_INLINE
{
Pin<pin>::pullup(enable);
};
static void call(const uint8_t value) FORCE_INLINE
{
Pin<pin>::write(value >> offset & 1);
};
static void call() FORCE_INLINE
{
Pin<pin>::toggle();
};
};
template <P pin>
struct readCaller {
static bool call() FORCE_INLINE
{
return Pin<pin>::read();
};
};
} // namespace detail
template <P... pins>
class VirtPort {
public:
// VirtPort objects cannot be moved or copied
VirtPort(const VirtPort &) = delete;
VirtPort(VirtPort &&) = delete;
VirtPort &operator=(const VirtPort &) = delete;
VirtPort &operator=(VirtPort &&) = delete;
// The only valid way to create a VirtPort object is with the default constructor
VirtPort() = default;
static inline void dir(const Dir dir) FORCE_INLINE
{
detail::CallHelper<detail::Callers, pins...>::call(dir);
}
static inline void pullup(const bool enable) FORCE_INLINE
{
detail::CallHelper<detail::Callers, pins...>::call(enable);
}
static inline void write(const uint8_t value) FORCE_INLINE
{
detail::CallHelper<detail::Callers, pins...>::call(value);
}
static inline void invert() FORCE_INLINE
{
detail::CallHelper<detail::Callers, pins...>::call();
}
static inline uint8_t read() FORCE_INLINE
{
return detail::ReadCallHelper<detail::readCaller, pins...>::call();
}
inline VirtPort &operator=(const uint8_t value) FORCE_INLINE
{
write(value);
return *this;
}
inline operator uint8_t() const FORCE_INLINE
{
return read();
}
};
} // namespace io
//////////////////////////////////////////////////////////////////////////