module; #include "STM32L4x2.h" export module io; /// Asociace port Adress a RCC clock struct GpioAssocPort { GPIOA_Type * const portAdr; uint32_t clkMask; }; namespace io { /** * @brief GPIO Configuration Mode enumeration */ enum GPIOMode_TypeDef { GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */ GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */ GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */ GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */ }; /** * @brief GPIO Output type enumeration */ enum GPIOOType_TypeDef { GPIO_OType_PP = 0x00, GPIO_OType_OD = 0x01 }; /** * @brief GPIO Output Maximum frequency enumeration */ enum GPIOSpeed_TypeDef { GPIO_Speed_LS = 0x00, /*!< Low speed */ GPIO_Speed_MS = 0x01, /*!< Medium speed */ GPIO_Speed_FS = 0x02, /*!< Fast speed */ GPIO_Speed_HS = 0x03 /*!< Very High speed */ }; /** * @brief GPIO Configuration PullUp PullDown enumeration */ enum GPIOPuPd_TypeDef { GPIO_PuPd_NOPULL = 0x00, GPIO_PuPd_UP = 0x01, GPIO_PuPd_DOWN = 0x02 }; /** Vstupní parametry metod */ enum GPIODir_TypeDef { GPIO_Dir_Mode_IN = 0x00, /*!< GPIO Input Mode */ GPIO_Dir_Mode_OUT = 0x01, /*!< GPIO Output Mode */ }; /// Enum pro PortNumber enum GpioPortNum { GpioPortA = 0, GpioPortB, GpioPortC, GpioPortD, GpioPortE, GpioPortH, }; /** @file * @brief Obecný GPIO pin. * * @class GpioClass * @brief Obecný GPIO pin. * */ export class GpioClass { public: /** Konstruktor @param port GpioPortA | GpioPortB | GpioPortC | GpioPortD | GpioPortF @param no číslo pinu na portu @param type IN, OUT, AF, AN default OUT */ GpioClass (GpioPortNum const port, const uint32_t no, const GPIOMode_TypeDef type = GPIO_Mode_OUT); /// Nastav pin @param b na tuto hodnotu const GpioClass& operator<< (const bool b) const { const uint32_t sh = b ? pos : pos << 16; io->BSRR.R = sh; return *this; } /// Nastav pin na log. H const GpioClass& operator+ (void) const { io->BSRR.R = (uint32_t) pos; return *this; } /// Nastav pin na log. L const GpioClass& operator- (void) const { io->BSRR.R = (uint32_t) pos << 16; return *this; } /// Změň hodnotu pinu const GpioClass& operator~ (void) const { io->ODR.R ^= pos; return *this; }; /// Načti logickou hodnotu na pinu const bool get (void) const { if (io->IDR.R & pos) return true; else return false; }; /// A to samé jako operátor const GpioClass& operator>> (bool& b) const { b = get(); return *this; } /// Různá nastavení void setMode (GPIOMode_TypeDef p) { uint32_t dno = num * 2; io->MODER.R &= ~(3UL << dno); io->MODER.R |= (p << dno); } void setOType (GPIOOType_TypeDef p) { io->OTYPER.R &= ~(1UL << num); io->OTYPER.R |= (p << num); } void setSpeed (GPIOSpeed_TypeDef p) { uint32_t dno = num * 2; io->OSPEEDR.R &= ~(3UL << dno); io->OSPEEDR.R |= (p << dno); } void setPuPd (GPIOPuPd_TypeDef p) { uint32_t dno = num * 2; io->PUPDR.R &= ~(3UL << dno); io->PUPDR.R |= (p << dno); } void setAF (unsigned af) { unsigned int pd,pn = num; pd = (pn & 7) << 2; pn >>= 3; if (pn) { io->AFRH.R &= ~(0xFU << pd); io->AFRH.R |= ( af << pd); } else { io->AFRL.R &= ~(0xFU << pd); io->AFRL.R |= ( af << pd); } } void setDir (GPIODir_TypeDef p) { uint32_t dno = num * 2; if (p) io->MODER.R |= (1UL << dno); else io->MODER.R &= ~(3UL << dno); } private: /// Port. GPIOA_Type * const io; // může být klidně i odkaz, ale je to stejné, necháme to tak jak bylo /// A pozice pinu na něm, stačí 16.bit const uint16_t pos; /// pro funkce setXXX necháme i číslo pinu const uint16_t num; }; static constexpr uint32_t RCC_AHB2ENR_GPIOAEN = (0x00000001u); /*!< Ofs=0 IO port A clock enable */ static constexpr uint32_t RCC_AHB2ENR_GPIOBEN = (0x00000002u); /*!< Ofs=1 IO port B clock enable */ static constexpr uint32_t RCC_AHB2ENR_GPIOCEN = (0x00000004u); /*!< Ofs=2 IO port C clock enable */ static constexpr uint32_t RCC_AHB2ENR_GPIODEN = (0x00000008u); /*!< Ofs=3 IO port D clock enable */ static constexpr uint32_t RCC_AHB2ENR_GPIOEEN = (0x00000010u); /*!< Ofs=4 IO port E clock enable */ static constexpr uint32_t RCC_AHB2ENR_GPIOHEN = (0x00000080u); /*!< Ofs=7 IO port H clock enable */ static GPIOA_Type * const pGPIOA = ((GPIOA_Type * const) 0x48000000u); /*!< General-purpose I/Os */ static GPIOA_Type * const pGPIOB = ((GPIOA_Type * const) 0x48000400u); /*!< General-purpose I/Os */ static GPIOA_Type * const pGPIOC = ((GPIOA_Type * const) 0x48000800u); /*!< General-purpose I/Os */ static GPIOA_Type * const pGPIOD = ((GPIOA_Type * const) 0x48000C00u); /*!< General-purpose I/Os */ static GPIOA_Type * const pGPIOE = ((GPIOA_Type * const) 0x48001000u); /*!< General-purpose I/Os */ static GPIOA_Type * const pGPIOH = ((GPIOA_Type * const) 0x48001C00u); /*!< General-purpose I/Os */ static const struct GpioAssocPort cPortTab[] = { {pGPIOA, RCC_AHB2ENR_GPIOAEN}, {pGPIOB, RCC_AHB2ENR_GPIOBEN}, {pGPIOC, RCC_AHB2ENR_GPIOCEN}, {pGPIOD, RCC_AHB2ENR_GPIODEN}, {pGPIOE, RCC_AHB2ENR_GPIOEEN}, {pGPIOH, RCC_AHB2ENR_GPIOHEN}, }; GpioClass::GpioClass (GpioPortNum const port, const uint32_t no, const GPIOMode_TypeDef type) : io (cPortTab[port].portAdr), pos(1UL << no), num(no) { // Povol hodiny RCC.AHB2ENR.R |= cPortTab[port].clkMask; setMode (type); } };