RISC-V/V003/stm32f051/gpio.h

146 lines
3.8 KiB
C
Raw Permalink Normal View History

2024-03-07 13:46:47 +01:00
#ifndef GPIO_H
#define GPIO_H
#include "STM32F0x1.h"
/**
* @brief General Purpose IO
*/
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 In/Out Mode */
} GPIOMode_TypeDef;
typedef enum {
GPIO_OType_PP = 0x00,
GPIO_OType_OD = 0x01
} GPIOOType_TypeDef;
typedef enum {
GPIO_Speed_Level_1 = 0x01, /*!< Medium Speed */
GPIO_Speed_Level_2 = 0x02, /*!< Fast Speed */
GPIO_Speed_Level_3 = 0x03 /*!< High Speed */
} GPIOSpeed_TypeDef;
typedef enum {
GPIO_PuPd_NOPULL = 0x00,
GPIO_PuPd_UP = 0x01,
GPIO_PuPd_DOWN = 0x02
} GPIOPuPd_TypeDef;
/// Enum pro PortNumber
typedef enum {
GpioPortA,
GpioPortB,
GpioPortC,
GpioPortD,
GpioPortF
} GpioPortNum;
/// Asociace port Adress a RCC clock
struct GpioAssocPort {
GPIOF_Type * const portAdr;
const uint32_t clkMask;
};
/** @file
* @brief Obecný GPIO pin.
*
* @class GpioClass
* @brief Obecný GPIO pin.
*
* Ukázka přetížení operátorů. Návratové hodnoty jsou v tomto případě celkem zbytečné,
* ale umožňují řetězení, takže je možné napsat např.
@code
+-+-+-led;
@endcode
* a máme na led 3 pulsy. Je to sice blbost, ale funguje.
* Všechny metody jsou konstantní, protože nemění data uvnitř třídy.
* Vlastně ani nemohou, protože data jsou konstantní.
*/
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
*/
explicit GpioClass (GpioPortNum const port, const uint32_t no, const GPIOMode_TypeDef type = GPIO_Mode_OUT) noexcept;
/// Nastav pin @param b na tuto hodnotu
const GpioClass& operator<< (const bool b) const {
if (b) io->BSRR.R = pos;
else io->BRR.R = pos;
return *this;
}
//![Gpio example]
/// 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->BRR.R = pos;
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;
2024-03-12 13:24:01 +01:00
else return false;
2024-03-07 13:46:47 +01:00
};
/// A to samé jako operátor
const GpioClass& operator>> (bool& b) const {
b = get();
return *this;
}
2024-03-12 13:24:01 +01:00
operator bool () const {
return get();
}
2024-03-07 13:46:47 +01:00
//![Gpio example]
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 &= (uint16_t)~(1UL << num);
io->OTYPER.R |= (uint16_t) (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);
}
}
private:
/// Port.
GPIOF_Type * const io;
/// 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;
};
#endif // GPIO_H