diff --git a/Inc/peripherals_config.hpp b/Inc/peripherals_config.hpp new file mode 100644 index 0000000..87a1b97 --- /dev/null +++ b/Inc/peripherals_config.hpp @@ -0,0 +1,17 @@ +/* + * peripherals_config.h + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#ifndef PERIPHERALS_CONFIG_HPP_ +#define PERIPHERALS_CONFIG_HPP_ + +#define PERIPHERALS_USE_DELAY_US + +#ifndef PERIPHERALS_USE_DELAY_US +# pragma info "Compiled without usecond delay." +#endif + +#endif /* PERIPHERALS_CONFIG_HPP_ */ diff --git a/Inc/peripherals_io.hpp b/Inc/peripherals_io.hpp new file mode 100644 index 0000000..c6df7ad --- /dev/null +++ b/Inc/peripherals_io.hpp @@ -0,0 +1,38 @@ +/* + * IO.h + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#ifndef PERIPHERALS_IO_HPP_ +#define PERIPHERALS_IO_HPP_ + +#include +#include + +#include + +namespace Peripherals +{ + +struct IO +{ + GPIO_TypeDef* port; + std::uint16_t pin; + + IO() = default; + IO(GPIO_TypeDef* port, const unsigned short pin); + + void Set(const bool state); + void Toggle(); + bool Read(); + +#ifdef PERIPHERALS_USE_DELAY_US + void SetDelayUs(const bool state, const std::uint32_t micros); +#endif +}; + +} /* namespace Peripherals */ + +#endif /* PERIPHERALS_IO_HPP_ */ diff --git a/Inc/peripherals_motors.hpp b/Inc/peripherals_motors.hpp new file mode 100644 index 0000000..7646a59 --- /dev/null +++ b/Inc/peripherals_motors.hpp @@ -0,0 +1,54 @@ +/* + * peripherals_motors.hpp + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#ifndef PERIPHERALS_MOTORS_HPP_ +#define PERIPHERALS_MOTORS_HPP_ + +#include "peripherals_io.hpp" + +#include + +#include "peripherals_pwm_channel.hpp" + +namespace Peripherals +{ + +class IMotors +{ +public: + struct TwoChannelMotorData + { + PwmChannel forward; + PwmChannel backward; + }; + + virtual void Set(const std::int16_t left, const std::int16_t right) = 0; + virtual void Coast() = 0; + virtual void Break() = 0; + virtual void Unbreak() = 0; +}; + +class DualDrvMotors : public IMotors +{ +public: + DualDrvMotors(const IMotors::TwoChannelMotorData& left, const IMotors::TwoChannelMotorData& right, const IO& sleep_pin); + + virtual void Set(const std::int16_t left, const std::int16_t right) override; + virtual void Coast() override; + virtual void Break() override; + virtual void Unbreak() override; + +private: + IMotors::TwoChannelMotorData _left; + IMotors::TwoChannelMotorData _right; + IO _sleep_pin; +}; + +} + + +#endif /* PERIPHERALS_MOTORS_HPP_ */ diff --git a/Inc/peripherals_pwm_channel.hpp b/Inc/peripherals_pwm_channel.hpp new file mode 100644 index 0000000..d2baf8e --- /dev/null +++ b/Inc/peripherals_pwm_channel.hpp @@ -0,0 +1,44 @@ +/* + * peripherals_pwm.hpp + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#ifndef PERIPHERALS_PWM_CHANNEL_HPP_ +#define PERIPHERALS_PWM_CHANNEL_HPP_ + +#include + +#include + +#include "peripherals_io.hpp" + +namespace Peripherals +{ + +struct PwmChannel +{ + TIM_HandleTypeDef* timer; + std::uint32_t channel; + std::uint32_t timer_code; + IO pin; + + PwmChannel() = default; + + PwmChannel(TIM_HandleTypeDef* timer, + const std::uint32_t channel, + const std::uint32_t timer_code, + const IO& pin); + + void PinToPwm(); + void PinToGpio(); + + void Enable(); + void Disable(); +}; + +} + + +#endif /* PERIPHERALS_PWM_CHANNEL_HPP_ */ diff --git a/Inc/peripherals_utility.hpp b/Inc/peripherals_utility.hpp new file mode 100644 index 0000000..e100dc1 --- /dev/null +++ b/Inc/peripherals_utility.hpp @@ -0,0 +1,38 @@ +/* + * peripherals_utility.hpp + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#ifndef PERIPHERALS_UTILITY_HPP_ +#define PERIPHERALS_UTILITY_HPP_ + +#include + +#include "peripherals_config.hpp" + +namespace Peripherals +{ + +void Initialize(); + +#ifdef PERIPHERALS_USE_DELAY_US +void DelayUs(const std::uint32_t micros); +#endif + +template +constexpr const T& Clamp(const T& v, const T& lo, const T& hi) +{ + if (v > hi) + return hi; + else if (v < lo) + return lo; + else + return v; +} + +} + + +#endif /* PERIPHERALS_UTILITY_HPP_ */ diff --git a/Src/peripherals_io.cpp b/Src/peripherals_io.cpp new file mode 100644 index 0000000..aa84e0d --- /dev/null +++ b/Src/peripherals_io.cpp @@ -0,0 +1,44 @@ +/* + * IO.cpp + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#include + +#include "peripherals_utility.hpp" + +namespace Peripherals +{ + +IO::IO(GPIO_TypeDef* port, const unsigned short pin) + : port(port) + , pin(std::uint16_t(pin)) +{ } + +void IO::Set(const bool state) +{ + HAL_GPIO_WritePin(port, pin, GPIO_PinState(state)); +} + +void IO::Toggle() +{ + HAL_GPIO_TogglePin(port, pin); +} + +bool IO::Read() +{ + return bool(HAL_GPIO_ReadPin(port, pin)); +} + +#ifdef PERIPHERALS_USE_DELAY_US +void IO::SetDelayUs(const bool state, const std::uint32_t micros) +{ + HAL_GPIO_WritePin(port, pin, GPIO_PinState(state)); + + DelayUs(micros); +} +#endif + +} /* namespace Peripherals */ diff --git a/Src/peripherals_motors.cpp b/Src/peripherals_motors.cpp new file mode 100644 index 0000000..f4475e6 --- /dev/null +++ b/Src/peripherals_motors.cpp @@ -0,0 +1,94 @@ +/* + * peripherals_motors.cpp + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#include "peripherals_motors.hpp" + +namespace Peripherals +{ + +DualDrvMotors::DualDrvMotors(const IMotors::TwoChannelMotorData& left, + const IMotors::TwoChannelMotorData& right, const IO& sleep_pin) + : _left(left) + , _right(right) + , _sleep_pin(sleep_pin) +{ + _left.forward.Enable(); + _left.backward.Enable(); + _right.forward.Enable(); + _right.backward.Enable(); + + Set(0, 0); +} + +void DualDrvMotors::Set(const std::int16_t left, const std::int16_t right) +{ + if (left > 0) + { + __HAL_TIM_SET_COMPARE(_left.forward.timer, _left.forward.channel, left); + __HAL_TIM_SET_COMPARE(_left.backward.timer, _left.backward.channel, 0); + } + else + { + __HAL_TIM_SET_COMPARE(_left.forward.timer, _left.forward.channel, 0); + __HAL_TIM_SET_COMPARE(_left.backward.timer, _left.backward.channel, (-1 * left)); + } + + if (right > 0) + { + __HAL_TIM_SET_COMPARE(_right.forward.timer, _right.forward.channel, right); + __HAL_TIM_SET_COMPARE(_right.backward.timer, _right.backward.channel, 0); + } + else + { + __HAL_TIM_SET_COMPARE(_right.forward.timer, _right.forward.channel, 0); + __HAL_TIM_SET_COMPARE(_right.backward.timer, _right.backward.channel, (-1 * right)); + } +} + +void DualDrvMotors::Coast() +{ + __HAL_TIM_SET_COMPARE(_left.forward.timer, _left.forward.channel, 0); + __HAL_TIM_SET_COMPARE(_left.backward.timer, _left.backward.channel, 0); + + __HAL_TIM_SET_COMPARE(_right.forward.timer, _right.forward.channel, 0); + __HAL_TIM_SET_COMPARE(_right.backward.timer, _right.backward.channel, 0); +} + +void DualDrvMotors::Break() +{ + Set(0, 0); + + _left.forward.Disable(); + _left.backward.Disable(); + _right.forward.Disable(); + _right.backward.Disable(); + + _left.forward.PinToGpio(); + _left.backward.PinToGpio(); + _right.forward.PinToGpio(); + _right.backward.PinToGpio(); + + _left.forward.pin.Set(true); + _left.backward.pin.Set(true); + _right.forward.pin.Set(true); + _right.backward.pin.Set(true); +} + +void DualDrvMotors::Unbreak() +{ + _left.forward.PinToPwm(); + _left.backward.PinToPwm(); + _right.forward.PinToPwm(); + _right.backward.PinToPwm(); + + _left.forward.Enable(); + _left.backward.Enable(); + _right.forward.Enable(); + _right.backward.Enable(); +} + +} diff --git a/Src/peripherals_pwm_channel.cpp b/Src/peripherals_pwm_channel.cpp new file mode 100644 index 0000000..988f653 --- /dev/null +++ b/Src/peripherals_pwm_channel.cpp @@ -0,0 +1,58 @@ +/* + * peripherals_pwm_channel.cpp + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#include "peripherals_pwm_channel.hpp" + +namespace Peripherals +{ + +PwmChannel::PwmChannel(TIM_HandleTypeDef* timer, + const std::uint32_t channel, + const std::uint32_t timer_code, + const IO& pin) + : timer(timer) + , channel(channel) + , timer_code(timer_code) + , pin(pin) +{ } + +void PwmChannel::PinToPwm() +{ + GPIO_InitTypeDef gpio_init = { 0 }; + + gpio_init.Pin = pin.pin; + gpio_init.Mode = GPIO_MODE_AF_PP; + gpio_init.Pull = GPIO_NOPULL; + gpio_init.Speed = GPIO_SPEED_FREQ_LOW; + gpio_init.Alternate = timer_code; + + HAL_GPIO_Init(pin.port, &gpio_init); +} + +void PwmChannel::PinToGpio() +{ + GPIO_InitTypeDef gpio_config = { 0 }; + + gpio_config.Pin = pin.pin; + gpio_config.Mode = GPIO_MODE_OUTPUT_PP; + gpio_config.Pull = GPIO_NOPULL; + gpio_config.Speed = GPIO_SPEED_FREQ_LOW; + + HAL_GPIO_Init(pin.port, &gpio_config); +} + +void PwmChannel::Enable() +{ + HAL_TIM_PWM_Start(timer, channel); +} + +void PwmChannel::Disable() +{ + HAL_TIM_PWM_Stop(timer, channel); +} + +} diff --git a/Src/peripherals_utility.cpp b/Src/peripherals_utility.cpp new file mode 100644 index 0000000..be2156b --- /dev/null +++ b/Src/peripherals_utility.cpp @@ -0,0 +1,34 @@ +/* + * peripherals_utility.cpp + * + * Created on: Feb 24, 2021 + * Author: erki + */ + +#include "peripherals_utility.hpp" + +#include "main.h" + +namespace Peripherals +{ + +void Initialize() +{ +#ifdef PERIPHERALS_USE_DELAY_US + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CYCCNT = 0; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; +#endif +} + +#ifdef PERIPHERALS_USE_DELAY_US +void DelayUs(const std::uint32_t micros) +{ + const std::uint32_t tick_start = DWT->CYCCNT; + const std::uint32_t ticks_delay = micros * (SystemCoreClock / 1'000'000); + + while (DWT->CYCCNT - tick_start < ticks_delay); +} +#endif + +}