use stm32_hrtim::compare_register::HrCompareRegister;
use stm32_hrtim::control::{HrPwmControl, HrPwmCtrl};
use stm32_hrtim::output::{HrOutput, Output1Pin, Output2Pin};
use stm32_hrtim::timer::{HrTim, HrTimer};
use stm32_hrtim::{HrParts, HrPwmAdvExt, HrPwmBuilder, HrtimPrescaler, PreloadSource, capture};
use crate::hrtim::HrPwmBuilderExt;
use crate::peripherals::HRTIM1;
use crate::rcc::SealedRccPeripheral;
use crate::time::Hertz;
pub struct BridgeConverter<TIM, PSCL> {
timer: HrParts<TIM, PSCL>,
dead_time: u16,
primary_duty: u16,
min_secondary_duty: u16,
max_secondary_duty: u16,
}
impl<TIM: HrPwmAdvExt, PSCL: HrtimPrescaler> BridgeConverter<TIM, PSCL>
where
TIM: stm32_hrtim::timer::InstanceX + HrPwmAdvExt<PreloadSource = PreloadSource>,
HrTim<TIM, PSCL, capture::NoDma, capture::NoDma>: HrTimer,
{
pub fn new<P1, P2>(
timer: TIM,
pin1: P1,
pin2: P2,
frequency: Hertz,
prescaler: PSCL,
hr_control: &mut HrPwmControl,
) -> Self
where
P1: Output1Pin<TIM>,
P2: Output2Pin<TIM>,
HrPwmBuilder<TIM, PSCL, PreloadSource, P1, P2>: HrPwmBuilderExt<TIM, PSCL, P1, P2>,
{
let f = frequency.0;
let timer_f = HRTIM1::frequency().0;
let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
let psc = PSCL::VALUE as u32;
assert!(
psc >= psc_min,
"Prescaler set too low to be able to reach target frequency"
);
let timer_f = 32 * (timer_f / psc);
let per: u16 = (timer_f / f) as u16;
let mut timer = timer
.pwm_advanced(pin1, pin2)
.prescaler(prescaler)
.period(per)
.preload(PreloadSource::OnRepetitionUpdate)
.finalize(hr_control);
timer.out1.enable_set_event(&timer.timer);
timer.out1.enable_rst_event(&timer.cr1);
timer.out2.enable_set_event(&timer.cr2);
timer.out2.enable_rst_event(&timer.cr3);
Self {
timer,
dead_time: 0,
primary_duty: 0,
min_secondary_duty: 0,
max_secondary_duty: 0,
}
}
pub fn start(&mut self, hr_control: &mut HrPwmCtrl) {
self.timer.timer.start(hr_control);
}
pub fn stop(&mut self, hr_control: &mut HrPwmCtrl) {
self.timer.timer.stop(hr_control);
}
fn update_primary_duty_or_dead_time(&mut self) {
self.min_secondary_duty = self.primary_duty + self.dead_time;
self.timer.cr1.set_duty(self.primary_duty);
self.timer.cr2.set_duty(self.min_secondary_duty);
}
pub fn set_dead_time(&mut self, dead_time: u16) {
self.dead_time = dead_time;
self.max_secondary_duty = self.get_max_compare_value() - dead_time;
self.update_primary_duty_or_dead_time();
}
pub fn get_max_compare_value(&mut self) -> u16 {
self.timer.timer.get_period()
}
pub fn set_primary_duty(&mut self, primary_duty: u16) {
self.primary_duty = primary_duty;
self.update_primary_duty_or_dead_time();
}
pub fn set_secondary_duty(&mut self, secondary_duty: u16) {
let secondary_duty = if secondary_duty > self.max_secondary_duty {
self.max_secondary_duty
} else if secondary_duty <= self.min_secondary_duty {
self.min_secondary_duty + 1
} else {
secondary_duty
};
self.timer.cr3.set_duty(secondary_duty);
}
}