Implemented virtual port convenience object
This commit is contained in:
parent
986ceef65d
commit
cde4f9beda
122
io.hpp
122
io.hpp
@ -247,6 +247,41 @@ static inline reg_ptr_t getRegPtr()
|
|||||||
return reinterpret_cast<reg_ptr_t>(Address);
|
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
|
} // 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
|
} // namespace io
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user