So habe ich das jetzt auch gelößt.. also mit Enum. Allerdings anstatt dem Switch-Case nutzte ich eine static constexpr, damit ich quasi alles direkt Adressieren kann.
Mein Punkt war, dass ich drum rum kommen wollte, trotz einer gewissen Typsicherheit alle Enums nochmal selbst schreiben zu müssen.
das sieht dann jetzt halt so aus:
Code: Alles auswählen
#define IO_READ(x) ( static_cast<decltype(x)>( *const_cast< typename std::remove_volatile<decltype(x)>::type* >(&(x)) ))
enum ePinSpeed { psUltraLow = 0, psLow = 1, psMedium = 2, psHigh = 3 };
enum eInputPullDirection { ipdHighZ = 0, ipdPullUp = 1, ipdPullDown = 2 };
enum eGPIO {GPIO_A = GPIOA_BASE, GPIO_B = GPIOB_BASE, GPIO_C = GPIOC_BASE, GPIO_D = GPIOD_BASE,
GPIO_E = GPIOE_BASE, GPIO_F = GPIOF_BASE, GPIO_G = GPIOG_BASE, GPIO_H = GPIOH_BASE }; //because C++ sucks
template<const eGPIO gpio, const unsigned int Pin> struct CSpecificGPIO
{
static constexpr GPIO_TypeDef* GPIO = (GPIO_TypeDef*)gpio;
struct COutput
{
void High() const { GPIO->BSRRH = 1u<<Pin; }
void Low() const { GPIO->BSRRL = 1u<<Pin; }
void SetLevel(const bool Level) const { if (Level) High(); else Low(); }
void Toggle() const { GPIO->ODR = IO_READ(GPIO->ODR) ^ (1u<<Pin); }
void SetDriveStrength(const ePinSpeed PinSPeed) const { GPIO->OSPEEDR = (IO_READ(GPIO->OSPEEDR) & (~(3u<<(Pin*2)))) | (((unsigned int)PinSPeed)<<(Pin*2)); }
void operator()() const
{
GPIO->PUPDR = (IO_READ(GPIO->PUPDR) & (~(3u<<(Pin*2)))) | (0u<<(Pin*2)); //No Pull up/down
GPIO->OTYPER = IO_READ(GPIO->OTYPER) & ~(1u<<Pin); // PushPull
GPIO->MODER = (IO_READ(GPIO->MODER) & (~(3u<<(Pin*2)))) | (1u<<(Pin*2)); // Output
GPIO->OSPEEDR = IO_READ(GPIO->OSPEEDR) | (((unsigned int)psHigh)<<(Pin*2)); //HighSpeed as default
}
void operator()(const bool InitialLevel, const ePinSpeed PinSpeed = psHigh) const
{
GPIO->PUPDR = (IO_READ(GPIO->PUPDR) & (~(3u<<(Pin*2)))) | (0u<<(Pin*2)); // No Pull up/down
GPIO->OTYPER = IO_READ(GPIO->OTYPER) | (1u<<Pin); // PushPull
SetDriveStrength(PinSpeed); // Pin Speed
GPIO->MODER = (IO_READ(GPIO->MODER) & (~(3u<<(Pin*2)))) | (1u<<(Pin*2)); // Output
if (InitialLevel) High(); else Low(); // Level
}
} Output;
....
};
Nicht sonderlich schlimm.. aber auch nicht so, wie ich es mag. Auf einem anderen Prozessor mit mehr Ports muss ich dann wieder die Enums nachbearbeiten und für einen kleineren Prozessor müsste ich mt dem #Präprozessor die ungültigen enums wegmachen und argh. Wird halt hässlich.
Und wieso geht die Texteinrückung im Code-Tag nicht. Ich habs mit Tabs probiert und auch die Tabs durch Leerzeichen ersetzt. Aha. code=cpp