1use super::sealed::Split;
39use super::{
40 compute_arr_presc, Advanced, CPin, CenterAlignedMode, FTimer, IdleState, Instance, NCPin, Ocm,
41 Polarity, Timer, WithPwm,
42};
43pub use super::{Ch, C1, C2, C3, C4};
44use crate::gpio::{OpenDrain, PushPull};
45use crate::rcc::Clocks;
46use core::ops::{Deref, DerefMut};
47use fugit::{HertzU32 as Hertz, TimerDurationU32};
48
49pub trait PwmExt
50where
51 Self: Sized + Instance + WithPwm + Split,
52{
53 fn pwm<const FREQ: u32>(
54 self,
55 time: TimerDurationU32<FREQ>,
56 clocks: &Clocks,
57 ) -> (PwmManager<Self, FREQ>, Self::Channels);
58
59 fn pwm_hz(self, freq: Hertz, clocks: &Clocks) -> (PwmHzManager<Self>, Self::Channels);
60
61 fn pwm_us(
62 self,
63 time: TimerDurationU32<1_000_000>,
64 clocks: &Clocks,
65 ) -> (PwmManager<Self, 1_000_000>, Self::Channels) {
66 self.pwm::<1_000_000>(time, clocks)
67 }
68}
69
70impl<TIM> PwmExt for TIM
71where
72 Self: Sized + Instance + WithPwm + Split,
73{
74 fn pwm<const FREQ: u32>(
75 self,
76 time: TimerDurationU32<FREQ>,
77 clocks: &Clocks,
78 ) -> (PwmManager<Self, FREQ>, Self::Channels) {
79 FTimer::<Self, FREQ>::new(self, clocks).pwm(time)
80 }
81
82 fn pwm_hz(self, time: Hertz, clocks: &Clocks) -> (PwmHzManager<Self>, Self::Channels) {
83 Timer::new(self, clocks).pwm_hz(time)
84 }
85}
86
87impl<TIM: Instance + WithPwm + Split> Timer<TIM> {
88 pub fn pwm_hz(mut self, freq: Hertz) -> (PwmHzManager<TIM>, TIM::Channels) {
89 self.tim.enable_preload(true);
93
94 let (psc, arr) = compute_arr_presc(freq.raw(), self.clk.raw());
95 self.tim.set_prescaler(psc);
96 self.tim.set_auto_reload(arr).unwrap();
97
98 self.tim.trigger_update();
100
101 self.tim.start_pwm();
102
103 (PwmHzManager { timer: self }, TIM::split())
104 }
105}
106
107impl<TIM: Instance + WithPwm + Split, const FREQ: u32> FTimer<TIM, FREQ> {
108 pub fn pwm(mut self, time: TimerDurationU32<FREQ>) -> (PwmManager<TIM, FREQ>, TIM::Channels) {
109 self.tim.enable_preload(true);
113
114 self.tim.set_auto_reload(time.ticks() - 1).unwrap();
115
116 self.tim.trigger_update();
118
119 self.tim.start_pwm();
120
121 (PwmManager { timer: self }, TIM::split())
122 }
123}
124
125pub struct PwmChannelDisabled<TIM, const C: u8> {
126 pub(super) tim: TIM,
127}
128
129impl<TIM: crate::Steal, const C: u8> PwmChannelDisabled<TIM, C> {
130 pub(crate) fn new() -> Self {
131 Self {
132 tim: unsafe { TIM::steal() },
133 }
134 }
135}
136impl<TIM: Instance + WithPwm + crate::Steal, const C: u8> PwmChannelDisabled<TIM, C>
137where
138 TIM: CPin<C>,
139{
140 pub fn with(
141 mut self,
142 pin: impl Into<TIM::Ch<PushPull>>,
143 ) -> PwmChannel<TIM, C, false, PushPull> {
144 self.tim.preload_output_channel_in_mode(C, Ocm::PwmMode1);
145 PwmChannel {
146 tim: self.tim,
147 lines: Lines::One(pin.into()),
148 }
149 }
150 pub fn with_open_drain(
151 mut self,
152 pin: impl Into<TIM::Ch<OpenDrain>>,
153 ) -> PwmChannel<TIM, C, false, OpenDrain> {
154 self.tim.preload_output_channel_in_mode(C, Ocm::PwmMode1);
155 PwmChannel {
156 tim: self.tim,
157 lines: Lines::One(pin.into()),
158 }
159 }
160}
161
162#[derive(Debug)]
163pub enum Lines<P> {
164 One(P),
165 Two(P, P),
166 Three(P, P, P),
167 Four(P, P, P, P),
168}
169impl<P> Lines<P> {
170 pub fn and(self, pin: P) -> Self {
171 match self {
172 Self::One(p) => Self::Two(p, pin),
173 Self::Two(p1, p2) => Self::Three(p1, p2, pin),
174 Self::Three(p1, p2, p3) => Self::Four(p1, p2, p3, pin),
175 Self::Four(_, _, _, _) => unreachable!(),
176 }
177 }
178}
179
180pub struct PwmChannel<TIM: CPin<C>, const C: u8, const COMP: bool = false, Otype = PushPull> {
181 pub(super) tim: TIM,
182 lines: Lines<TIM::Ch<Otype>>,
183 }
185
186impl<TIM: Instance + WithPwm + CPin<C>, const C: u8, const COMP: bool, Otype>
187 PwmChannel<TIM, C, COMP, Otype>
188{
189 pub const fn channel(&self) -> u8 {
190 C
191 }
192 pub fn release(mut self) -> (PwmChannelDisabled<TIM, C>, Lines<TIM::Ch<Otype>>) {
193 self.tim.freeze_output_channel(C);
194 (PwmChannelDisabled { tim: self.tim }, self.lines)
195 }
196 pub fn erase(self) -> ErasedChannel<TIM> {
197 ErasedChannel {
198 _tim: self.tim,
199 channel: C,
200 }
201 }
202}
203impl<TIM: Instance + CPin<C>, const C: u8, const COMP: bool, Otype>
204 PwmChannel<TIM, C, COMP, Otype>
205{
206 pub fn with(self, pin: impl Into<TIM::Ch<Otype>>) -> Self {
207 Self {
208 tim: self.tim,
209 lines: self.lines.and(pin.into()),
210 }
211 }
212}
213impl<TIM: Instance + CPin<C> + NCPin<C>, const C: u8, const COMP: bool, Otype>
214 PwmChannel<TIM, C, COMP, Otype>
215{
216 pub fn with_complementary(
217 self,
218 pin: impl Into<TIM::ChN<Otype>>,
219 ) -> PwmChannel<TIM, C, true, Otype> {
220 let _pin = pin.into();
221 PwmChannel {
222 tim: self.tim,
223 lines: self.lines,
224 }
225 }
226}
227
228pub struct ErasedChannel<TIM> {
229 _tim: TIM,
230 channel: u8,
231}
232
233impl<TIM> ErasedChannel<TIM> {
234 pub const fn channel(&self) -> u8 {
235 self.channel
236 }
237}
238
239macro_rules! ch_impl {
240 () => {
241 #[inline]
243 pub fn disable(&mut self) {
244 TIM::enable_channel(self.channel(), false);
245 }
246
247 #[inline]
249 pub fn enable(&mut self) {
250 TIM::enable_channel(self.channel(), true);
251 }
252
253 #[inline]
255 pub fn get_duty(&self) -> u16 {
256 TIM::read_cc_value(self.channel()) as u16
257 }
258
259 #[inline]
263 pub fn get_max_duty(&self) -> u16 {
264 (TIM::read_auto_reload() as u16).wrapping_add(1)
265 }
266
267 #[inline]
269 pub fn set_duty(&mut self, duty: u16) {
270 TIM::set_cc_value(self.channel(), duty as u32)
271 }
272
273 #[inline]
275 pub fn set_polarity(&mut self, p: Polarity) {
276 TIM::set_channel_polarity(self.channel(), p);
277 }
278
279 #[inline]
281 pub fn set_complementary_polarity(&mut self, p: Polarity) {
282 TIM::set_nchannel_polarity(self.channel(), p);
283 }
284 };
285}
286
287macro_rules! chN_impl {
288 () => {
289 #[inline]
291 pub fn disable_complementary(&mut self) {
292 TIM::enable_nchannel(self.channel(), false);
293 }
294
295 #[inline]
297 pub fn enable_complementary(&mut self) {
298 TIM::enable_nchannel(self.channel(), true);
299 }
300
301 #[inline]
303 pub fn set_idle_state(&mut self, s: IdleState) {
304 TIM::idle_state(self.channel(), false, s);
305 }
306
307 #[inline]
309 pub fn set_complementary_idle_state(&mut self, s: IdleState) {
310 TIM::idle_state(self.channel(), true, s);
311 }
312 };
313}
314
315impl<TIM: Instance + WithPwm + CPin<C>, const C: u8, const COMP: bool, Otype>
316 PwmChannel<TIM, C, COMP, Otype>
317{
318 ch_impl!();
319}
320
321impl<TIM: Instance + WithPwm + Advanced + CPin<C>, const C: u8, Otype>
322 PwmChannel<TIM, C, true, Otype>
323{
324 chN_impl!();
325}
326
327impl<TIM: Instance + WithPwm> ErasedChannel<TIM> {
328 ch_impl!();
329}
330
331impl<TIM: Instance + WithPwm + Advanced> ErasedChannel<TIM> {
332 chN_impl!();
333}
334
335pub struct PwmManager<TIM, const FREQ: u32>
336where
337 TIM: Instance + WithPwm,
338{
339 pub(super) timer: FTimer<TIM, FREQ>,
340}
341
342impl<TIM, const FREQ: u32> PwmManager<TIM, FREQ>
343where
344 TIM: Instance + WithPwm + Split,
345{
346 pub fn release(mut self, _channels: TIM::Channels) -> FTimer<TIM, FREQ> {
347 self.tim.cr1_reset();
349 self.timer
350 }
351}
352
353impl<TIM, const FREQ: u32> Deref for PwmManager<TIM, FREQ>
354where
355 TIM: Instance + WithPwm,
356{
357 type Target = FTimer<TIM, FREQ>;
358 fn deref(&self) -> &Self::Target {
359 &self.timer
360 }
361}
362
363impl<TIM, const FREQ: u32> DerefMut for PwmManager<TIM, FREQ>
364where
365 TIM: Instance + WithPwm,
366{
367 fn deref_mut(&mut self) -> &mut Self::Target {
368 &mut self.timer
369 }
370}
371
372pub struct PwmHzManager<TIM>
373where
374 TIM: Instance + WithPwm,
375{
376 pub(super) timer: Timer<TIM>,
377}
378
379impl<TIM> PwmHzManager<TIM>
380where
381 TIM: Instance + WithPwm + Split,
382{
383 pub fn release(mut self, _channels: TIM::Channels) -> Timer<TIM> {
384 self.tim.cr1_reset();
386 self.timer
387 }
388}
389
390impl<TIM> Deref for PwmHzManager<TIM>
391where
392 TIM: Instance + WithPwm,
393{
394 type Target = Timer<TIM>;
395 fn deref(&self) -> &Self::Target {
396 &self.timer
397 }
398}
399
400impl<TIM> DerefMut for PwmHzManager<TIM>
401where
402 TIM: Instance + WithPwm,
403{
404 fn deref_mut(&mut self) -> &mut Self::Target {
405 &mut self.timer
406 }
407}
408
409impl<TIM, const FREQ: u32> PwmManager<TIM, FREQ>
410where
411 TIM: Instance + WithPwm,
412{
413 pub fn get_max_duty(&self) -> u16 {
417 (TIM::read_auto_reload() as u16).wrapping_add(1)
418 }
419
420 pub fn get_period(&self) -> TimerDurationU32<FREQ> {
422 TimerDurationU32::from_ticks(TIM::read_auto_reload() + 1)
423 }
424
425 pub fn set_period(&mut self, period: TimerDurationU32<FREQ>) {
427 self.tim.set_auto_reload(period.ticks() - 1).unwrap();
428 self.tim.cnt_reset();
429 }
430}
431
432impl<TIM> PwmHzManager<TIM>
433where
434 TIM: Instance + WithPwm,
435{
436 pub fn get_max_duty(&self) -> u16 {
440 (TIM::read_auto_reload() as u16).wrapping_add(1)
441 }
442
443 pub fn get_period(&self) -> Hertz {
445 let clk = self.clk;
446 let psc = self.tim.read_prescaler() as u32;
447 let arr = TIM::read_auto_reload();
448
449 clk / ((psc + 1) * (arr + 1))
451 }
452
453 pub fn set_period(&mut self, period: Hertz) {
455 let clk = self.clk;
456
457 let (psc, arr) = compute_arr_presc(period.raw(), clk.raw());
458 self.tim.set_prescaler(psc);
459 self.tim.set_auto_reload(arr).unwrap();
460 self.tim.cnt_reset();
461 }
462}
463
464macro_rules! impl_advanced {
465 () => {
466 #[inline]
472 pub fn set_dead_time(&mut self, dts_ticks: u16) {
473 let bits = pack_ceil_dead_time(dts_ticks);
474 TIM::set_dtg_value(bits);
475 }
476
477 #[inline]
482 pub fn set_dead_time_bits(&mut self, bits: u8) {
483 TIM::set_dtg_value(bits);
484 }
485
486 #[inline]
488 pub fn get_dead_time(&self) -> u16 {
489 unpack_dead_time(TIM::read_dtg_value())
490 }
491
492 #[inline]
494 pub fn get_dead_time_bits(&self) -> u8 {
495 TIM::read_dtg_value()
496 }
497
498 #[inline]
500 pub fn set_cms(&mut self, mode: CenterAlignedMode) {
501 self.tim.enable_counter(false);
502 TIM::set_cms(mode);
503 self.tim.enable_counter(true);
504 }
505 };
506}
507
508impl<TIM, const FREQ: u32> PwmManager<TIM, FREQ>
509where
510 TIM: Instance + WithPwm + Advanced,
511{
512 impl_advanced!();
513}
514
515impl<TIM> PwmHzManager<TIM>
516where
517 TIM: Instance + WithPwm + Advanced,
518{
519 impl_advanced!();
520}
521
522const fn pack_ceil_dead_time(dts_ticks: u16) -> u8 {
525 match dts_ticks {
526 0..=127 => dts_ticks as u8,
527 128..=254 => ((((dts_ticks + 1) >> 1) - 64) as u8) | 0b_1000_0000,
528 255..=504 => ((((dts_ticks + 7) >> 3) - 32) as u8) | 0b_1100_0000,
529 505..=1008 => ((((dts_ticks + 15) >> 4) - 32) as u8) | 0b_1110_0000,
530 1009.. => 0xff,
531 }
532}
533
534const fn unpack_dead_time(bits: u8) -> u16 {
536 if bits & 0b_1000_0000 == 0 {
537 bits as u16
538 } else if bits & 0b_0100_0000 == 0 {
539 (((bits & !0b_1000_0000) as u16) + 64) * 2
540 } else if bits & 0b_0010_0000 == 0 {
541 (((bits & !0b_1100_0000) as u16) + 32) * 8
542 } else {
543 (((bits & !0b_1110_0000) as u16) + 32) * 16
544 }
545}