Module/io.cpp

187 lines
5.8 KiB
C++
Raw Normal View History

2024-01-16 16:14:54 +01:00
module;
#include "STM32L4x2.h"
export module io;
/// Asociace port Adress a RCC clock
struct GpioAssocPort {
GPIOA_Type * portAdr;
uint32_t clkMask;
};
/**
* @brief GPIO Configuration Mode enumeration
*/
typedef enum {
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 */
}GPIOMode_TypeDef;
/**
* @brief GPIO Output type enumeration
*/
typedef enum {
GPIO_OType_PP = 0x00,
GPIO_OType_OD = 0x01
}GPIOOType_TypeDef;
/**
* @brief GPIO Output Maximum frequency enumeration
*/
typedef enum {
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 */
}GPIOSpeed_TypeDef;
/**
* @brief GPIO Configuration PullUp PullDown enumeration
*/
typedef enum {
GPIO_PuPd_NOPULL = 0x00,
GPIO_PuPd_UP = 0x01,
GPIO_PuPd_DOWN = 0x02
}GPIOPuPd_TypeDef;
/** Vstupní parametry metod */
typedef enum {
GPIO_Dir_Mode_IN = 0x00, /*!< GPIO Input Mode */
GPIO_Dir_Mode_OUT = 0x01, /*!< GPIO Output Mode */
} GPIODir_TypeDef;
/// Enum pro PortNumber
typedef enum {
GpioPortA,
GpioPortB,
GpioPortC,
GpioPortD,
GpioPortE,
GpioPortH,
} GpioPortNum;
namespace io {
/** @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 {
if (b) io->BSRR.R = (uint32_t) pos;
else io->BSRR.R = (uint32_t) pos << 16;
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;
};
#define RCC_AHB2ENR_GPIOAEN ((uint32_t)0x00000001u) /*!< Ofs=0 IO port A clock enable */
#define RCC_AHB2ENR_GPIOBEN ((uint32_t)0x00000002u) /*!< Ofs=1 IO port B clock enable */
#define RCC_AHB2ENR_GPIOCEN ((uint32_t)0x00000004u) /*!< Ofs=2 IO port C clock enable */
#define RCC_AHB2ENR_GPIODEN ((uint32_t)0x00000008u) /*!< Ofs=3 IO port D clock enable */
#define RCC_AHB2ENR_GPIOEEN ((uint32_t)0x00000010u) /*!< Ofs=4 IO port E clock enable */
#define RCC_AHB2ENR_GPIOHEN ((uint32_t)0x00000080u) /*!< Ofs=7 IO port H clock enable */
#define pGPIOA ((GPIOA_Type * const) 0x48000000u) /*!< General-purpose I/Os */
#define pGPIOB ((GPIOA_Type * const) 0x48000400u) /*!< General-purpose I/Os */
#define pGPIOC ((GPIOA_Type * const) 0x48000800u) /*!< General-purpose I/Os */
#define pGPIOD ((GPIOA_Type * const) 0x48000C00u) /*!< General-purpose I/Os */
#define pGPIOE ((GPIOA_Type * const) 0x48001000u) /*!< General-purpose I/Os */
#define 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);
}
export void wait (const unsigned ms = 500000u) {
volatile unsigned n;
for (n=0u; n<ms; n+=1) asm volatile ("nop");
}
};