Files
timely-reference/firmware/Bsp/Drivers/GpioDriver.cpp
Max Regan cdf0f4ffc9 Update such that tests pass for v1.2
This includes minor updates for the th different MCU variant, and bugfixes.

Resolves #7
2020-06-03 04:51:19 +00:00

216 lines
6.0 KiB
C++

#include "Bsp/Drivers/GpioDriver.h"
#include "Bsp/macros.h"
namespace BSP {
/*********************************************
*
* GpioPin
*
*********************************************/
GpioDriver::GpioDriver(GPIO_TypeDef *gpio)
: m_gpio(gpio)
{}
void GpioDriver::init() {
return;
}
void GpioDriver::enable() {
#if defined(STM32L0XX)
if (m_gpio == GPIOA) {
SET(RCC->IOPENR, RCC_IOPENR_IOPAEN);
} else if (m_gpio == GPIOB) {
SET(RCC->IOPENR, RCC_IOPENR_IOPBEN);
} else if (m_gpio == GPIOC) {
SET(RCC->IOPENR, RCC_IOPENR_IOPCEN);
} else if (m_gpio == GPIOH) {
SET(RCC->IOPENR, RCC_IOPENR_IOPHEN);
}
#elif defined(STM32L4XX)
if (m_gpio == GPIOA) {
SET(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN);
} else if (m_gpio == GPIOB) {
SET(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN);
} else if (m_gpio == GPIOC) {
SET(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN);
} else if (m_gpio == GPIOH) {
SET(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN);
}
#else
#error "Unknown device family"
#endif
}
void GpioDriver::disable() {
#if defined(STM32L0XX)
if (m_gpio == GPIOA) {
CLR(RCC->IOPENR, RCC_IOPENR_IOPAEN);
} else if (m_gpio == GPIOB) {
CLR(RCC->IOPENR, RCC_IOPENR_IOPBEN);
} else if (m_gpio == GPIOC) {
CLR(RCC->IOPENR, RCC_IOPENR_IOPCEN);
} else if (m_gpio == GPIOH) {
CLR(RCC->IOPENR, RCC_IOPENR_IOPHEN);
}
#elif defined(STM32L4XX)
if (m_gpio == GPIOA) {
CLR(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN);
} else if (m_gpio == GPIOB) {
CLR(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN);
} else if (m_gpio == GPIOC) {
CLR(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN);
} else if (m_gpio == GPIOH) {
CLR(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN);
}
#else
#error "Unknown device family"
#endif
}
void GpioDriver::set_pin_moder(uint32_t index, moder_t mode) {
uint32_t moder_value = 0;
switch (mode) {
case moder_t::INPUT:
moder_value = 0;
break;
case moder_t::OUTPUT:
moder_value = 1;
break;
case moder_t::ALTERNATE_FUNCTION:
moder_value = 2;
break;
}
SET_STRIDE_TO(m_gpio->MODER, 2, index, moder_value);
}
void GpioDriver::set_pin_pupdr(uint32_t index, input_pull_t pull_mode) {
uint32_t pupdr_value = 0;
switch (pull_mode) {
case input_pull_t::FLOATING:
pupdr_value = 0;
break;
case input_pull_t::PULL_UP:
pupdr_value = 1;
break;
case input_pull_t::PULL_DOWN:
pupdr_value = 2;
break;
}
SET_STRIDE_TO(m_gpio->PUPDR, 2, index, pupdr_value);
}
void GpioDriver::set_pin_otyper(uint32_t index, output_mode_t mode) {
uint32_t mask = 1 << index;
if (mode == output_mode_t::OPEN_DRAIN) {
SET(m_gpio->OTYPER, mask);
} else {
CLR(m_gpio->OTYPER, mask);
}
}
void GpioDriver::set_pin_ospeedr(uint32_t index, output_speed_t speed) {
uint32_t speed_val = 0;
if (speed == output_speed_t::LOW) {
speed_val = 0;
} else if (speed == output_speed_t::MEDIUM) {
speed_val = 1;
} else if (speed == output_speed_t::HIGH) {
speed_val = 2;
} else if (speed == output_speed_t::VERY_HIGH) {
speed_val = 3;
}
SET_STRIDE_TO(m_gpio->OSPEEDR, 2, index, speed_val);
}
void GpioDriver::configure_pin_input(uint32_t index, input_pull_t pull_mode) {
if (index > 15) {
return;
}
set_pin_pupdr(index, pull_mode);
set_pin_moder(index, moder_t::INPUT);
}
void GpioDriver::configure_pin_output(uint32_t index, output_mode_t mode, output_speed_t speed) {
if (index > 15) {
return;
}
set_pin_moder(index, moder_t::INPUT); // Avoid glitches during configuration
set_pin_otyper(index, mode);
set_pin_ospeedr(index, speed);
set_pin_moder(index, moder_t::OUTPUT);
}
void GpioDriver::configure_pin_alternate_function(uint32_t index, uint32_t function) {
if (index > 15) {
return;
}
if (function > 7) {
return;
}
set_pin_moder(index, moder_t::INPUT); // Avoid glitches during configuration
if (index < 8) {
SET_STRIDE_TO(m_gpio->AFR[0], 4, index, function);
} else {
SET_STRIDE_TO(m_gpio->AFR[1], 4, index - 8, function);
}
set_pin_moder(index, moder_t::ALTERNATE_FUNCTION);
}
bool GpioDriver::read_pin(uint32_t index) {
return (m_gpio->IDR >> index) & 1;
}
void GpioDriver::write_pin(uint32_t index, bool value) {
SET_STRIDE_TO(m_gpio->ODR, 1, index, value);
}
/*********************************************
*
* GpioPin
*
*********************************************/
GpioPin::GpioPin(GpioDriver &driver, uint32_t index)
: m_gpio(driver)
, m_index(index)
{}
void GpioPin::configure_input(GpioDriver::input_pull_t pull_mode) {
m_gpio.configure_pin_input(m_index, pull_mode);
}
void GpioPin::configure_output(GpioDriver::output_mode_t mode, GpioDriver::output_speed_t speed) {
m_gpio.configure_pin_output(m_index, mode, speed);
}
void GpioPin::configure_alternate_function(uint32_t function) {
m_gpio.configure_pin_alternate_function(m_index, function);
}
bool GpioPin::read() {
return m_gpio.read_pin(m_index);
}
void GpioPin::write(bool val) {
return m_gpio.write_pin(m_index, val);
}
uint32_t GpioPin::get_index() {
return m_index;
}
GpioDriver& GpioPin::get_driver() {
return m_gpio;
}
}