Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@shima-529
Last active December 7, 2019 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shima-529/712c790bd73656c2ecc1a57f8edf1929 to your computer and use it in GitHub Desktop.
Save shima-529/712c790bd73656c2ecc1a57f8edf1929 to your computer and use it in GitHub Desktop.
#include "gpio.hpp"
#include "stm32f3xx.h"
#include <type_traits>
template <typename T>
constexpr auto cast_base(T &&enumstruct) {
using T_noref = std::remove_reference_t<T>;
return static_cast<std::underlying_type_t<T_noref>>(enumstruct);
}
uint8_t Gpio::instancesNum = 0;
Gpio::Gpio() {
}
Gpio::Gpio(GPIO_TypeDef *gpio, PinName pin, GpioConfig pc)
: Instance(gpio), pin(pin), config(pc)
{
if( ++Gpio::instancesNum == 1 ) {
Gpio::allGpioInit();
}
this->configure(gpio, pin, pc);
}
Gpio::Gpio(GPIO_TypeDef *gpio, PinName pin, GpioConfig::PinMode mode)
: Instance(gpio), pin(pin)
{
if( ++Gpio::instancesNum == 1 ) {
Gpio::allGpioInit();
}
this->configure(gpio, pin, mode);
}
void Gpio::configure(GPIO_TypeDef *gpio, PinName pin, GpioConfig pc) {
this->Instance = gpio;
this->pin = pin;
this->config = pc;
this->Instance->MODER &= ~(GPIO_MODER_MODER0 << (2*pin));
this->Instance->MODER |= (cast_base(pc.mode) << (2*pin));
this->Instance->OTYPER &= ~(GPIO_OTYPER_OT_0 << pin);
this->Instance->OTYPER |= (cast_base(pc.outputtype) << pin);
this->Instance->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (2*pin));
this->Instance->OSPEEDR |= (cast_base(pc.speed) << (2*pin));
this->Instance->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (2*pin));
this->Instance->PUPDR |= (cast_base(pc.pull) << (2*pin));
if( this->config.mode == GpioConfig::PinMode::ALTERNATE ) {
if( this->pin <= 7 ) {
this->Instance->AFR[0] &= ~(GPIO_AFRL_AFRL0_Msk << (pin * 4));
this->Instance->AFR[0] |= (this->config.alternateFunc << (pin * 4));
}else{
this->Instance->AFR[1] &= ~(GPIO_AFRH_AFRH0_Msk << ((pin - 8) * 4));
this->Instance->AFR[1] |= (this->config.alternateFunc << ((pin - 8) * 4));
}
}
}
void Gpio::configure(GPIO_TypeDef *gpio, PinName pin, GpioConfig::PinMode mode) {
this->Instance = gpio;
this->pin = pin;
this->config.mode = mode;
this->Instance->MODER &= ~(GPIO_MODER_MODER0 << (2*pin));
this->Instance->MODER |= (cast_base(mode) << (2*pin));
}
void Gpio::setMode(GpioConfig::PinMode mode) {
this->Instance->MODER &= ~(GPIO_MODER_MODER0 << (2*pin));
this->Instance->MODER |= (cast_base(mode) << (2*pin));
this->mode = mode;
}
void Gpio::allGpioInit() {
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
RCC->AHBENR |= RCC_AHBENR_GPIODEN;
RCC->AHBENR |= RCC_AHBENR_GPIOEEN;
RCC->AHBENR |= RCC_AHBENR_GPIOFEN;
// ** DO NOT SET THE REGISTERS BELOW **
// If GPIOA->MODER is set to 0, it causes errors on SWD debugging.
// GPIOA->MODER = 0;
// GPIOB->MODER = 0;
// GPIOC->MODER = 0;
// GPIOD->MODER = 0;
// GPIOF->MODER = 0;
}
bool Gpio::getValue() {
if( this->config.mode == GpioConfig::PinMode::INPUT ) {
return (this->Instance->IDR >> this->pin) & 0x01;
}
//else
return (this->Instance->ODR >> this->pin) & 0x01;
}
uint8_t Gpio::operator =(bool val) {
if( val == true ) {
return (this->Instance->ODR |= (1 << this->pin));
}else{
return (this->Instance->ODR &= ~(1 << this->pin));
}
}
uint8_t Gpio::operator ^(bool val) {
return this->getValue() ^ val;
}
uint8_t Gpio::operator^=(bool val) {
if( this->config.mode != GpioConfig::PinMode::GPIO_OUTPUT ) {
return *this = *this ^ val;
}
//else
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment