31 #include <string_view>
36 #include <cmsis_gcc.h>
52 template<auto Context, u8 Channel,
typename Size>
54 static_assert(Channel >= 1 && Channel <= 4,
"Channel index out of range");
63 if(!hasPwmModule())
return false;
65 case 1: Context->Instance->CCER |= TIM_CCER_CC1E;
break;
66 case 2: Context->Instance->CCER |= TIM_CCER_CC2E;
break;
67 case 3: Context->Instance->CCER |= TIM_CCER_CC3E;
break;
68 case 4: Context->Instance->CCER |= TIM_CCER_CC4E;
break;
69 default: bsp::unreachable();
71 Context->Instance->CR1 = TIM_CR1_CEN;
82 if(!hasPwmModule())
return false;
84 case 1: Context->Instance->CCER &= ~TIM_CCER_CC1E;
break;
85 case 2: Context->Instance->CCER &= ~TIM_CCER_CC2E;
break;
86 case 3: Context->Instance->CCER &= ~TIM_CCER_CC3E;
break;
87 case 4: Context->Instance->CCER &= ~TIM_CCER_CC4E;
break;
88 default: bsp::unreachable();
90 if(Context->Instance->CCER == 0) Context->Instance->CR1 &= ~TIM_CR1_CEN;
101 if(!hasPwmModule())
return false;
104 case 1: Context->Instance->CCER |= TIM_CCER_CC1P;
break;
105 case 2: Context->Instance->CCER |= TIM_CCER_CC2P;
break;
106 case 3: Context->Instance->CCER |= TIM_CCER_CC3P;
break;
107 case 4: Context->Instance->CCER |= TIM_CCER_CC4P;
break;
108 default: bsp::unreachable();
113 case 1: Context->Instance->CCER &= ~TIM_CCER_CC1P;
break;
114 case 2: Context->Instance->CCER &= ~TIM_CCER_CC2P;
break;
115 case 3: Context->Instance->CCER &= ~TIM_CCER_CC3P;
break;
116 case 4: Context->Instance->CCER &= ~TIM_CCER_CC4P;
break;
117 default: bsp::unreachable();
131 if(!hasPwmModule())
return false;
132 dutyCycle = std::abs(dutyCycle);
133 if(dutyCycle > 100) dutyCycle = 100;
134 Size arr = Context->Instance->ARR;
136 if(dutyCycle != 0) ccr = arr / 100 * dutyCycle;
138 case 1: Context->Instance->CCR1 = ccr;
break;
139 case 2: Context->Instance->CCR2 = ccr;
break;
140 case 3: Context->Instance->CCR3 = ccr;
break;
141 case 4: Context->Instance->CCR4 = ccr;
break;
142 default: bsp::unreachable();
154 bool hasPwmModule() const noexcept{
155 if ((Context->Instance == TIM6) ||
156 (Context->Instance == TIM7)) {
172 template<auto Context,
typename Size>
198 if(!hasEncoderModule())
return false;
199 Context->Instance->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
200 Context->Instance->CR1 = TIM_CR1_CEN;
211 if(!hasEncoderModule())
return false;
212 Context->Instance->CR1 &= ~TIM_CR1_CEN;
213 Context->Instance->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC2E);
224 return Context->Instance->CNT;
233 Context->Instance->CNT = cnt;
252 Context->Instance->CR1 &= ~TIM_CR1_CEN;
253 Context->Instance->SMCR &= ~(TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1);
258 Context->Instance->CR1 = TIM_CR1_CEN;
268 if(!hasEncoderModule())
return false;
269 Context->Instance->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
270 Context->Instance->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;
271 Context->Instance->CR1 = TIM_CR1_CEN;
281 bool hasEncoderModule() const noexcept{
282 if ((Context->Instance == TIM1) ||
283 (Context->Instance == TIM2) ||
284 (Context->Instance == TIM3) ||
285 (Context->Instance == TIM4) ||
286 (Context->Instance == TIM5) ||
287 (Context->Instance == TIM8) ||
288 (Context->Instance == TIM12) ||
289 (Context->Instance == TIM15)) {
303 template<auto Context,
typename Size>
311 Context->Instance->CR1 = TIM_CR1_CEN;
318 Context->Instance->CR1 &= ~TIM_CR1_CEN;
325 Context->Instance->CNT = 0;
334 return cntToNanoSeconds(std::numeric_limits<Size>::max());
343 return formatToString(cntToNanoSeconds(std::numeric_limits<Size>::max()));
352 return cntToNanoSeconds(Context->Instance->CNT);
371 std::string buffer(0xFF, 0x00);
372 u32 s = passedTime / 1E9;
373 u16 ms =
static_cast<u32>(passedTime / 1E6) % 1000;
374 u16 us =
static_cast<u32>(passedTime / 1E3) % 1000;
375 u16 ns = passedTime % 1000;
377 snprintf(buffer.data(), buffer.size(),
"%lus %dms %dus %dns", s, ms, us, ns);
391 u64 cntToNanoSeconds(Size cntValue)
const noexcept {
392 float timerFrequency;
394 if ((Context->Instance == TIM1) ||
395 (Context->Instance == TIM8) ||
396 (Context->Instance == TIM15) ||
397 (Context->Instance == TIM16) ||
398 (Context->Instance == TIM17)) {
399 float pclk2 =
static_cast<float>(HAL_RCC_GetPCLK2Freq());
400 if ((RCC->TIMG2PRER & RCC_TIMG2PRER_TIMG2PRE) == 0) timerFrequency = pclk2;
401 else timerFrequency = 2 * pclk2;
405 float pclk1 =
static_cast<float>(HAL_RCC_GetPCLK1Freq());
406 if ((RCC->TIMG1PRER & RCC_TIMG1PRER_TIMG1PRE) == 0) timerFrequency = pclk1;
407 else timerFrequency = 2 * pclk1;
410 return static_cast<u64>(((cntValue) / timerFrequency) * 1E9);
425 template<auto Context,
typename Size>
469 Context->Instance->CR1 = TIM_CR1_CEN;
476 Context->Instance->CR1 &= ~TIM_CR1_CEN;
486 return Context->Instance->CNT;
495 Context->Instance->CNT = cnt;
505 auto arr = Context->Instance->ARR;
506 auto psc = (Context->Instance->PSC + 1);
508 if ((Context->Instance == TIM1) ||
509 (Context->Instance == TIM8) ||
510 (Context->Instance == TIM15) ||
511 (Context->Instance == TIM16) ||
512 (Context->Instance == TIM17)) {
513 float pclk2 =
static_cast<float>(HAL_RCC_GetPCLK2Freq());
514 if ((RCC->TIMG2PRER & RCC_TIMG2PRER_TIMG2PRE) == 0)
return (pclk2 / psc) / arr;
515 else return 2 * (pclk2 / psc) / arr;
519 float pclk1 =
static_cast<float>(HAL_RCC_GetPCLK1Freq());
520 if ((RCC->TIMG1PRER & RCC_TIMG1PRER_TIMG1PRE) == 0)
return (pclk1 / psc) / arr;
521 else return 2 * (pclk1 / psc) / arr;
540 std::array<float, 4> dutyCycle;
541 dutyCycle[0] = intToDuty(Context->Instance->CCR1);
542 dutyCycle[1] = intToDuty(Context->Instance->CCR2);
543 dutyCycle[2] = intToDuty(Context->Instance->CCR3);
544 dutyCycle[3] = intToDuty(Context->Instance->CCR4);
550 Context->Instance->ARR = resolution;
552 arr = Context->Instance->ARR;
554 if ((Context->Instance == TIM1) ||
555 (Context->Instance == TIM8) ||
556 (Context->Instance == TIM15) ||
557 (Context->Instance == TIM16) ||
558 (Context->Instance == TIM17)) {
559 float pclk2 =
static_cast<float>(HAL_RCC_GetPCLK2Freq());
560 if ((RCC->TIMG2PRER & RCC_TIMG2PRER_TIMG2PRE) == 0) timerFrequency = pclk2;
561 else timerFrequency = 2 * pclk2;
565 float pclk1 =
static_cast<float>(HAL_RCC_GetPCLK1Freq());
566 if ((RCC->TIMG1PRER & RCC_TIMG1PRER_TIMG1PRE) == 0) timerFrequency = pclk1;
567 else timerFrequency = 2 * pclk1;
570 if((f_hz * arr) > timerFrequency)
return false;
572 psc = std::round((timerFrequency / (f_hz * arr)) - 1);
574 if(psc > 0xFFFF)
return false;
576 Context->Instance->CR1 &= ~TIM_CR1_CEN;
577 Context->Instance->PSC = psc;
581 Context->Instance->CCR1 = dutyToInt(dutyCycle[0]);
582 Context->Instance->CCR2 = dutyToInt(dutyCycle[1]);
583 Context->Instance->CCR3 = dutyToInt(dutyCycle[2]);
584 Context->Instance->CCR4 = dutyToInt(dutyCycle[3]);
586 Context->Instance->CR1 = TIM_CR1_CEN;
601 static constexpr Size dutyToInt(
float dutyCycle){
602 if(dutyCycle > 100) dutyCycle = 100;
603 else if(dutyCycle <= 0)
return 0;
604 Size arr = Context->Instance->ARR;
605 return static_cast<Size
>(arr / 100 * dutyCycle);
614 static constexpr
float intToDuty(Size intDutyCycle){
615 Size arr = Context->Instance->ARR;
616 if(arr == 0)
return 0;
617 return static_cast<float>(intDutyCycle) /
static_cast<float>(arr) * 100.0F;