#include <cstddef>
#include <tuple>
#include <utility>
#include <cstdint>
#include <type_traits>
//#include "stm32f411xe.h"
#define __forceinline _Pragma("inline=forced")
constexpr std::uint32_t GpioaBaseAddr = 0x4002'0000 ;
constexpr std::uint32_t GpiocBaseAddr = 0x4002'0800 ;
struct PortBase
{
};
template <std::uint32_t addr>
struct Port: PortBase
{
__forceinline inline static void Toggle(const std::uint8_t bit)
{
*reinterpret_cast<std::uint32_t*>(addr) ^= (1 << bit) ;
}
};
using PortA = Port<GpioaBaseAddr> ;
using PortC = Port<GpiocBaseAddr> ;
template <typename T, std::uint8_t pinNum,
class = typename std::enable_if_t<std::is_base_of<PortBase, T>::value>>
struct Pin
{
__forceinline inline static void Toggle()
{
T::Toggle(pinNum) ;
}
} ;
using Led1 = Pin<PortA, 5> ;
using Led2 = Pin<PortC, 5> ;
using Led3 = Pin<PortC, 8> ;
class LedsContainer
{
friend int main() ;
public:
__forceinline static inline void ToggleAll()
{
visit<std::tuple_size<tRecordsTuple>::value>();
}
private:
__forceinline template<size_t N>
static inline void visit()
{
visit(std::make_index_sequence<N>());
}
__forceinline template<std::size_t... index>
static inline void visit(std::index_sequence<index...>)
{
Pass((std::get<index>(records).Toggle(), true)...);
}
__forceinline template<typename... Args>
static void inline Pass(Args... )
{
}
constexpr static auto records = std::make_tuple (
Pin<PortA, 5>{},
Pin<PortC, 5>{},
Pin<PortC, 8>{},
Pin<PortC, 9>{}
) ;
using tRecordsTuple = decltype(records) ;
} ;
int main()
{
//GPIOA->ODR ^= 1 << 5;
//GPIOC->ODR ^= 1 << 5;
//GPIOC->ODR ^= 1 << 8;
//GPIOC->ODR ^= 1 << 9;
LedsContainer::ToggleAll();
// LedsContainer::records.get<0>().Toggle();
// Pin<PortA, 5>::Toggle() ;
//std::get<0>(LedsContainer::records).Toggle();
return 0 ;
}