mirror of
https://github.com/OpenSolo/OpenSolo.git
synced 2025-05-30 13:30:14 +02:00
102 lines
2.8 KiB
C++
102 lines
2.8 KiB
C++
|
|
#include "hwtimer.h"
|
|
|
|
bool ALWAYS_INLINE IS_ADVANCED(volatile TIM_t *t) {
|
|
return t == &TIM1 || t == &TIM8;
|
|
}
|
|
|
|
void HwTimer::init(uint16_t period_, uint16_t prescaler) const
|
|
{
|
|
if (tim == &TIM1) {
|
|
RCC.APB2ENR |= (1 << 11); // TIM1 enable
|
|
RCC.APB2RSTR = (1 << 11); // TIM1 reset
|
|
RCC.APB2RSTR = 0;
|
|
|
|
} else if (tim >= &TIM2 && tim <= &TIM7) {
|
|
unsigned bit = 1 << ((((uintptr_t)tim) >> 10) & 7);
|
|
RCC.APB1ENR |= bit; // TIM2-TIM7 enable
|
|
RCC.APB1RSTR = bit; // TIM2-TIM7 reset
|
|
RCC.APB1RSTR = 0;
|
|
}
|
|
|
|
// Timer configuration
|
|
tim->PSC = prescaler;
|
|
tim->ARR = period_;
|
|
|
|
if (IS_ADVANCED(tim)) {
|
|
tim->BDTR = (1 << 15); // MOE - main output enable
|
|
}
|
|
|
|
tim->DIER = 0;
|
|
tim->CR2 = 0;
|
|
tim->CCER = 0;
|
|
tim->EGR = 1;
|
|
tim->SR = 0; // clear status register
|
|
tim->CR1 = (1 << 7) | // ARPE - auto reload preload enable
|
|
(1 << 2) | // URS - update request source
|
|
(1 << 0); // EN - enable
|
|
}
|
|
|
|
void HwTimer::deinit() const
|
|
{
|
|
tim->CR1 = 0; // control disabled
|
|
tim->DIER = 0; // IRQs disabled
|
|
tim->SR = 0; // clear status
|
|
|
|
if (tim == &TIM2) {
|
|
RCC.APB1ENR &= ~(1 << 0); // TIM2 disable
|
|
}
|
|
else if (tim == &TIM3) {
|
|
RCC.APB1ENR &= ~(1 << 1); // TIM3 disable
|
|
}
|
|
else if (tim == &TIM4) {
|
|
RCC.APB1ENR &= ~(1 << 2); // TIM4 disable
|
|
}
|
|
else if (tim == &TIM5) {
|
|
RCC.APB1ENR &= ~(1 << 3); // TIM5 disable
|
|
}
|
|
else if (tim == &TIM1) {
|
|
RCC.APB2ENR &= ~(1 << 11); // TIM1 disable
|
|
}
|
|
}
|
|
|
|
// channels are numbered 1-4
|
|
void HwTimer::configureChannelAsOutput(int ch, Polarity polarity, TimerMode timmode, OutputMode outmode, DmaMode dmamode) const
|
|
{
|
|
uint8_t mode, pol;
|
|
(void)dmamode;
|
|
|
|
mode = (1 << 3) | // OCxPE - output compare preload enable
|
|
(timmode << 4); // OCxM - output compare mode
|
|
if (ch <= 2) {
|
|
tim->CCMR1 |= mode << ((ch - 1) * 8);
|
|
}
|
|
else {
|
|
tim->CCMR2 |= mode << ((ch - 3) * 8);
|
|
}
|
|
|
|
pol = ((unsigned)polarity << 1); // enable OCxE (and OCxP based on polarity)
|
|
if (IS_ADVANCED(tim) && outmode == ComplementaryOutput) {
|
|
pol |= 1 << 2; // enable OCxNE
|
|
}
|
|
|
|
tim->compareCapRegs[ch - 1].CCR = 0;
|
|
tim->CCER |= (pol << ((ch - 1) * 4));
|
|
}
|
|
|
|
void HwTimer::configureChannelAsInput(int ch, InputCaptureEdge edge, uint8_t filterFreq, uint8_t prescaler) const
|
|
{
|
|
uint8_t mode = (1 << 0) | // configured as input, mapped on TI1
|
|
((filterFreq & 0xF) << 4) |
|
|
((prescaler & 0x3) << 2);
|
|
|
|
if (ch <= 2) {
|
|
tim->CCMR1 |= mode << ((ch - 1) * 8);
|
|
}
|
|
else {
|
|
tim->CCMR2 |= mode << ((ch - 3) * 8);
|
|
}
|
|
|
|
tim->CCER |= edge << ((ch - 1) * 4);
|
|
}
|