1mod traits;
4
5use core::marker::PhantomData;
6
7use embassy_hal_internal::Peri;
8pub use traits::Instance;
9
10use crate::gpio::{AfType, AnyPin, OutputType, Speed};
11use crate::rcc;
12use crate::time::Hertz;
13
14pub struct BurstController<T: Instance> {
16 phantom: PhantomData<T>,
17}
18
19pub struct Master<T: Instance> {
21 phantom: PhantomData<T>,
22}
23
24pub struct ChA<T: Instance> {
26 phantom: PhantomData<T>,
27}
28
29pub struct ChB<T: Instance> {
31 phantom: PhantomData<T>,
32}
33
34pub struct ChC<T: Instance> {
36 phantom: PhantomData<T>,
37}
38
39pub struct ChD<T: Instance> {
41 phantom: PhantomData<T>,
42}
43
44pub struct ChE<T: Instance> {
46 phantom: PhantomData<T>,
47}
48
49#[cfg(hrtim_v2)]
51pub struct ChF<T: Instance> {
52 phantom: PhantomData<T>,
53}
54
55trait SealedAdvancedChannel<T: Instance> {
56 fn raw() -> usize;
57}
58
59#[allow(private_bounds)]
61pub trait AdvancedChannel<T: Instance>: SealedAdvancedChannel<T> {}
62
63pub struct PwmPin<'d, T, C> {
65 _pin: Peri<'d, AnyPin>,
66 phantom: PhantomData<(T, C)>,
67}
68
69pub struct ComplementaryPwmPin<'d, T, C> {
71 _pin: Peri<'d, AnyPin>,
72 phantom: PhantomData<(T, C)>,
73}
74
75macro_rules! advanced_channel_impl {
76 ($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
77 impl<'d, T: Instance> PwmPin<'d, T, $channel<T>> {
78 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
79 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>) -> Self {
80 critical_section::with(|_| {
81 pin.set_low();
82 pin.set_as_af(
83 pin.af_num(),
84 AfType::output(OutputType::PushPull, Speed::VeryHigh),
85 );
86 });
87 PwmPin {
88 _pin: pin.into(),
89 phantom: PhantomData,
90 }
91 }
92 }
93
94 impl<'d, T: Instance> ComplementaryPwmPin<'d, T, $channel<T>> {
95 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
96 pub fn $new_chx(pin: Peri<'d, impl $complementary_pin_trait<T>>) -> Self {
97 critical_section::with(|_| {
98 pin.set_low();
99 pin.set_as_af(
100 pin.af_num(),
101 AfType::output(OutputType::PushPull, Speed::VeryHigh),
102 );
103 });
104 ComplementaryPwmPin {
105 _pin: pin.into(),
106 phantom: PhantomData,
107 }
108 }
109 }
110
111 impl<T: Instance> SealedAdvancedChannel<T> for $channel<T> {
112 fn raw() -> usize {
113 $ch_num
114 }
115 }
116 impl<T: Instance> AdvancedChannel<T> for $channel<T> {}
117 };
118}
119
120advanced_channel_impl!(new_cha, ChA, 0, ChannelAPin, ChannelAComplementaryPin);
121advanced_channel_impl!(new_chb, ChB, 1, ChannelBPin, ChannelBComplementaryPin);
122advanced_channel_impl!(new_chc, ChC, 2, ChannelCPin, ChannelCComplementaryPin);
123advanced_channel_impl!(new_chd, ChD, 3, ChannelDPin, ChannelDComplementaryPin);
124advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin);
125#[cfg(hrtim_v2)]
126advanced_channel_impl!(new_chf, ChF, 5, ChannelFPin, ChannelFComplementaryPin);
127
128pub struct AdvancedPwm<'d, T: Instance> {
130 _inner: Peri<'d, T>,
131 pub master: Master<T>,
133 pub burst_controller: BurstController<T>,
135 pub ch_a: ChA<T>,
137 pub ch_b: ChB<T>,
139 pub ch_c: ChC<T>,
141 pub ch_d: ChD<T>,
143 pub ch_e: ChE<T>,
145 #[cfg(hrtim_v2)]
147 pub ch_f: ChF<T>,
148}
149
150impl<'d, T: Instance> AdvancedPwm<'d, T> {
151 pub fn new(
155 tim: Peri<'d, T>,
156 _cha: Option<PwmPin<'d, T, ChA<T>>>,
157 _chan: Option<ComplementaryPwmPin<'d, T, ChA<T>>>,
158 _chb: Option<PwmPin<'d, T, ChB<T>>>,
159 _chbn: Option<ComplementaryPwmPin<'d, T, ChB<T>>>,
160 _chc: Option<PwmPin<'d, T, ChC<T>>>,
161 _chcn: Option<ComplementaryPwmPin<'d, T, ChC<T>>>,
162 _chd: Option<PwmPin<'d, T, ChD<T>>>,
163 _chdn: Option<ComplementaryPwmPin<'d, T, ChD<T>>>,
164 _che: Option<PwmPin<'d, T, ChE<T>>>,
165 _chen: Option<ComplementaryPwmPin<'d, T, ChE<T>>>,
166 #[cfg(hrtim_v2)] _chf: Option<PwmPin<'d, T, ChF<T>>>,
167 #[cfg(hrtim_v2)] _chfn: Option<ComplementaryPwmPin<'d, T, ChF<T>>>,
168 ) -> Self {
169 Self::new_inner(tim)
170 }
171
172 fn new_inner(tim: Peri<'d, T>) -> Self {
173 rcc::enable_and_reset::<T>();
174
175 #[cfg(stm32f334)]
176 if crate::pac::RCC.cfgr3().read().hrtim1sw() == crate::pac::rcc::vals::Timsw::PLL1_P {
177 T::regs().dllcr().modify(|w| {
179 w.set_cal(true);
180 });
181
182 trace!("hrtim: wait for dll calibration");
183 while !T::regs().isr().read().dllrdy() {}
184
185 trace!("hrtim: dll calibration complete");
186
187 T::regs().dllcr().modify(|w| {
190 w.set_cal(false);
191 });
192
193 T::regs().dllcr().modify(|w| {
194 w.set_calen(true);
195 w.set_calrte(11);
196 });
197 }
198
199 Self {
200 _inner: tim,
201 master: Master { phantom: PhantomData },
202 burst_controller: BurstController { phantom: PhantomData },
203 ch_a: ChA { phantom: PhantomData },
204 ch_b: ChB { phantom: PhantomData },
205 ch_c: ChC { phantom: PhantomData },
206 ch_d: ChD { phantom: PhantomData },
207 ch_e: ChE { phantom: PhantomData },
208 #[cfg(hrtim_v2)]
209 ch_f: ChF { phantom: PhantomData },
210 }
211 }
212}
213
214pub struct BridgeConverter<T: Instance, C: AdvancedChannel<T>> {
224 timer: PhantomData<T>,
225 channel: PhantomData<C>,
226 dead_time: u16,
227 primary_duty: u16,
228 min_secondary_duty: u16,
229 max_secondary_duty: u16,
230}
231
232impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
233 pub fn new(_channel: C, frequency: Hertz) -> Self {
235 T::set_channel_frequency(C::raw(), frequency);
236
237 T::regs().tim(C::raw()).cr().modify(|w| {
239 w.set_preen(true);
240 w.set_repu(true);
241 w.set_cont(true);
242 });
243
244 T::regs().oenr().modify(|w| {
246 w.set_t1oen(C::raw(), true);
247 w.set_t2oen(C::raw(), true);
248 });
249
250 T::regs().tim(C::raw()).setr(0).modify(|w| w.set_per(true));
256
257 T::regs().tim(C::raw()).rstr(0).modify(|w| w.set_cmp(0, true));
259
260 T::regs().tim(C::raw()).setr(1).modify(|w| w.set_cmp(1, true));
262
263 T::regs().tim(C::raw()).rstr(1).modify(|w| w.set_cmp(2, true));
265
266 Self {
267 timer: PhantomData,
268 channel: PhantomData,
269 dead_time: 0,
270 primary_duty: 0,
271 min_secondary_duty: 0,
272 max_secondary_duty: 0,
273 }
274 }
275
276 pub fn start(&mut self) {
278 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true));
279 }
280
281 pub fn stop(&mut self) {
283 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false));
284 }
285
286 pub fn enable_burst_mode(&mut self) {
288 T::regs().tim(C::raw()).outr().modify(|w| {
289 w.set_idlem(0, true);
291 w.set_idlem(1, true);
292
293 w.set_idles(0, true);
295 w.set_idles(1, true);
296 })
297 }
298
299 pub fn disable_burst_mode(&mut self) {
301 T::regs().tim(C::raw()).outr().modify(|w| {
302 w.set_idlem(0, false);
304 w.set_idlem(1, false);
305 })
306 }
307
308 fn update_primary_duty_or_dead_time(&mut self) {
309 self.min_secondary_duty = self.primary_duty + self.dead_time;
310
311 T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty));
312 T::regs()
313 .tim(C::raw())
314 .cmp(1)
315 .modify(|w| w.set_cmp(self.min_secondary_duty));
316 }
317
318 pub fn set_dead_time(&mut self, dead_time: u16) {
320 self.dead_time = dead_time;
321 self.max_secondary_duty = self.get_max_compare_value() - dead_time;
322 self.update_primary_duty_or_dead_time();
323 }
324
325 pub fn get_max_compare_value(&mut self) -> u16 {
327 T::regs().tim(C::raw()).per().read().per()
328 }
329
330 pub fn set_primary_duty(&mut self, primary_duty: u16) {
335 self.primary_duty = primary_duty;
336 self.update_primary_duty_or_dead_time();
337 }
338
339 pub fn set_secondary_duty(&mut self, secondary_duty: u16) {
344 let secondary_duty = if secondary_duty > self.max_secondary_duty {
345 self.max_secondary_duty
346 } else if secondary_duty <= self.min_secondary_duty {
347 self.min_secondary_duty + 1
348 } else {
349 secondary_duty
350 };
351
352 T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty));
353 }
354}
355
356pub struct ResonantConverter<T: Instance, C: AdvancedChannel<T>> {
362 timer: PhantomData<T>,
363 channel: PhantomData<C>,
364 min_period: u16,
365 max_period: u16,
366}
367
368impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
369 pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self {
371 T::set_channel_frequency(C::raw(), min_frequency);
372
373 T::regs().tim(C::raw()).cr().modify(|w| {
375 w.set_preen(true);
376 w.set_repu(true);
377
378 w.set_cont(true);
379 w.set_half(true);
380 });
381
382 T::regs().oenr().modify(|w| {
384 w.set_t1oen(C::raw(), true);
385 w.set_t2oen(C::raw(), true);
386 });
387
388 T::regs().tim(C::raw()).outr().modify(|w| w.set_dten(true));
391
392 let max_period = T::regs().tim(C::raw()).per().read().per();
393 let min_period = max_period * (min_frequency.0 / max_frequency.0) as u16;
394
395 Self {
396 timer: PhantomData,
397 channel: PhantomData,
398 min_period: min_period,
399 max_period: max_period,
400 }
401 }
402
403 pub fn set_dead_time(&mut self, value: u16) {
405 T::set_channel_dead_time(C::raw(), value);
406 }
407
408 pub fn set_period(&mut self, period: u16) {
410 assert!(period < self.max_period);
411 assert!(period > self.min_period);
412
413 T::regs().tim(C::raw()).per().modify(|w| w.set_per(period));
414 }
415
416 pub fn get_min_period(&mut self) -> u16 {
418 self.min_period
419 }
420
421 pub fn get_max_period(&mut self) -> u16 {
423 self.max_period
424 }
425}
426
427pin_trait!(ChannelAPin, Instance);
428pin_trait!(ChannelAComplementaryPin, Instance);
429pin_trait!(ChannelBPin, Instance);
430pin_trait!(ChannelBComplementaryPin, Instance);
431pin_trait!(ChannelCPin, Instance);
432pin_trait!(ChannelCComplementaryPin, Instance);
433pin_trait!(ChannelDPin, Instance);
434pin_trait!(ChannelDComplementaryPin, Instance);
435pin_trait!(ChannelEPin, Instance);
436pin_trait!(ChannelEComplementaryPin, Instance);
437#[cfg(hrtim_v2)]
438pin_trait!(ChannelFPin, Instance);
439#[cfg(hrtim_v2)]
440pin_trait!(ChannelFComplementaryPin, Instance);