1use crate::afio::MAPR;
57use crate::gpio::{self, Alternate};
58
59use super::{compute_arr_presc, Channel, FTimer, Instance, Ocm, Timer, WithPwm};
60use crate::rcc::Clocks;
61use core::marker::PhantomData;
62use core::ops::{Deref, DerefMut};
63use fugit::{HertzU32 as Hertz, TimerDurationU32};
64
65pub trait Pins<REMAP, P> {
66 const C1: bool = false;
67 const C2: bool = false;
68 const C3: bool = false;
69 const C4: bool = false;
70 type Channels;
71
72 fn check_used(c: Channel) -> Channel {
73 if (c == Channel::C1 && Self::C1)
74 || (c == Channel::C2 && Self::C2)
75 || (c == Channel::C3 && Self::C3)
76 || (c == Channel::C4 && Self::C4)
77 {
78 c
79 } else {
80 panic!("Unused channel")
81 }
82 }
83
84 fn split() -> Self::Channels;
85}
86
87pub use super::{pins::sealed::Remap, CPin, Ch, C1, C2, C3, C4};
88
89pub struct PwmChannel<TIM, const C: u8> {
90 pub(super) _tim: PhantomData<TIM>,
91}
92
93macro_rules! pins_impl {
94 ( $( ( $($PINX:ident),+ ), ( $($ENCHX:ident),+ ); )+ ) => {
95 $(
96 #[allow(unused_parens)]
97 impl<TIM, REMAP, OUTMODE, $($PINX,)+> Pins<REMAP, ($(Ch<$ENCHX>),+)> for ($($PINX),+)
98 where
99 TIM: Instance + WithPwm,
100 REMAP: Remap<Periph = TIM>,
101 $($PINX: CPin<REMAP, $ENCHX> + gpio::PinExt<Mode=Alternate<OUTMODE>>,)+
102 {
103 $(const $ENCHX: bool = true;)+
104 type Channels = ($(PwmChannel<TIM, $ENCHX>),+);
105 fn split() -> Self::Channels {
106 ($(PwmChannel::<TIM, $ENCHX>::new()),+)
107 }
108 }
109 )+
110 };
111}
112
113pins_impl!(
114 (P1, P2, P3, P4), (C1, C2, C3, C4);
115 (P2, P3, P4), (C2, C3, C4);
116 (P1, P3, P4), (C1, C3, C4);
117 (P1, P2, P4), (C1, C2, C4);
118 (P1, P2, P3), (C1, C2, C3);
119 (P3, P4), (C3, C4);
120 (P2, P4), (C2, C4);
121 (P2, P3), (C2, C3);
122 (P1, P4), (C1, C4);
123 (P1, P3), (C1, C3);
124 (P1, P2), (C1, C2);
125 (P1), (C1);
126 (P2), (C2);
127 (P3), (C3);
128 (P4), (C4);
129);
130
131pub trait PwmExt
132where
133 Self: Sized + Instance + WithPwm,
134{
135 fn pwm<REMAP, P, PINS, const FREQ: u32>(
136 self,
137 pins: PINS,
138 mapr: &mut MAPR,
139 time: TimerDurationU32<FREQ>,
140 clocks: &Clocks,
141 ) -> Pwm<Self, REMAP, P, PINS, FREQ>
142 where
143 REMAP: Remap<Periph = Self>,
144 PINS: Pins<REMAP, P>;
145
146 fn pwm_hz<REMAP, P, PINS>(
147 self,
148 pins: PINS,
149 mapr: &mut MAPR,
150 freq: Hertz,
151 clocks: &Clocks,
152 ) -> PwmHz<Self, REMAP, P, PINS>
153 where
154 REMAP: Remap<Periph = Self>,
155 PINS: Pins<REMAP, P>;
156
157 fn pwm_us<REMAP, P, PINS>(
158 self,
159 pins: PINS,
160 mapr: &mut MAPR,
161 time: TimerDurationU32<1_000_000>,
162 clocks: &Clocks,
163 ) -> Pwm<Self, REMAP, P, PINS, 1_000_000>
164 where
165 REMAP: Remap<Periph = Self>,
166 PINS: Pins<REMAP, P>,
167 {
168 self.pwm::<_, _, _, 1_000_000>(pins, mapr, time, clocks)
169 }
170}
171
172impl<TIM> PwmExt for TIM
173where
174 Self: Sized + Instance + WithPwm,
175{
176 fn pwm<REMAP, P, PINS, const FREQ: u32>(
177 self,
178 pins: PINS,
179 mapr: &mut MAPR,
180 time: TimerDurationU32<FREQ>,
181 clocks: &Clocks,
182 ) -> Pwm<TIM, REMAP, P, PINS, FREQ>
183 where
184 REMAP: Remap<Periph = Self>,
185 PINS: Pins<REMAP, P>,
186 {
187 FTimer::<Self, FREQ>::new(self, clocks).pwm(pins, mapr, time)
188 }
189
190 fn pwm_hz<REMAP, P, PINS>(
191 self,
192 pins: PINS,
193 mapr: &mut MAPR,
194 time: Hertz,
195 clocks: &Clocks,
196 ) -> PwmHz<TIM, REMAP, P, PINS>
197 where
198 REMAP: Remap<Periph = Self>,
199 PINS: Pins<REMAP, P>,
200 {
201 Timer::new(self, clocks).pwm_hz(pins, mapr, time)
202 }
203}
204
205impl<TIM: Instance + WithPwm, const C: u8> PwmChannel<TIM, C> {
206 pub(crate) fn new() -> Self {
207 Self {
208 _tim: core::marker::PhantomData,
209 }
210 }
211}
212
213impl<TIM: Instance + WithPwm, const C: u8> PwmChannel<TIM, C> {
214 #[inline]
215 pub fn disable(&mut self) {
216 TIM::enable_channel(C, false);
217 }
218
219 #[inline]
220 pub fn enable(&mut self) {
221 TIM::enable_channel(C, true);
222 }
223
224 #[inline]
225 pub fn get_duty(&self) -> u16 {
226 TIM::read_cc_value(C) as u16
227 }
228
229 #[inline]
231 pub fn get_max_duty(&self) -> u16 {
232 (TIM::read_auto_reload() as u16).wrapping_add(1)
233 }
234
235 #[inline]
236 pub fn set_duty(&mut self, duty: u16) {
237 TIM::set_cc_value(C, duty as u32)
238 }
239}
240
241pub struct PwmHz<TIM, REMAP, P, PINS>
242where
243 TIM: Instance + WithPwm,
244 REMAP: Remap<Periph = TIM>,
245 PINS: Pins<REMAP, P>,
246{
247 timer: Timer<TIM>,
248 _pins: PhantomData<(REMAP, P, PINS)>,
249}
250
251impl<TIM, REMAP, P, PINS> PwmHz<TIM, REMAP, P, PINS>
252where
253 TIM: Instance + WithPwm,
254 REMAP: Remap<Periph = TIM>,
255 PINS: Pins<REMAP, P>,
256{
257 pub fn release(mut self) -> Timer<TIM> {
258 self.tim.cr1_reset();
260 self.timer
261 }
262
263 pub fn split(self) -> PINS::Channels {
264 PINS::split()
265 }
266}
267
268impl<TIM, REMAP, P, PINS> Deref for PwmHz<TIM, REMAP, P, PINS>
269where
270 TIM: Instance + WithPwm,
271 REMAP: Remap<Periph = TIM>,
272 PINS: Pins<REMAP, P>,
273{
274 type Target = Timer<TIM>;
275 fn deref(&self) -> &Self::Target {
276 &self.timer
277 }
278}
279
280impl<TIM, REMAP, P, PINS> DerefMut for PwmHz<TIM, REMAP, P, PINS>
281where
282 TIM: Instance + WithPwm,
283 REMAP: Remap<Periph = TIM>,
284 PINS: Pins<REMAP, P>,
285{
286 fn deref_mut(&mut self) -> &mut Self::Target {
287 &mut self.timer
288 }
289}
290
291impl<TIM: Instance + WithPwm> Timer<TIM> {
292 pub fn pwm_hz<REMAP, P, PINS>(
293 mut self,
294 _pins: PINS,
295 mapr: &mut MAPR,
296 freq: Hertz,
297 ) -> PwmHz<TIM, REMAP, P, PINS>
298 where
299 REMAP: Remap<Periph = TIM>,
300 PINS: Pins<REMAP, P>,
301 {
302 REMAP::remap(mapr);
303
304 if PINS::C1 {
305 self.tim
306 .preload_output_channel_in_mode(Channel::C1, Ocm::PwmMode1);
307 }
308 if PINS::C2 && TIM::CH_NUMBER > 1 {
309 self.tim
310 .preload_output_channel_in_mode(Channel::C2, Ocm::PwmMode1);
311 }
312 if PINS::C3 && TIM::CH_NUMBER > 2 {
313 self.tim
314 .preload_output_channel_in_mode(Channel::C3, Ocm::PwmMode1);
315 }
316 if PINS::C4 && TIM::CH_NUMBER > 3 {
317 self.tim
318 .preload_output_channel_in_mode(Channel::C4, Ocm::PwmMode1);
319 }
320
321 self.tim.enable_preload(true);
325
326 let (psc, arr) = compute_arr_presc(freq.raw(), self.clk.raw());
327 self.tim.set_prescaler(psc);
328 self.tim.set_auto_reload(arr).unwrap();
329
330 self.tim.trigger_update();
332
333 self.tim.start_pwm();
334
335 PwmHz {
336 timer: self,
337 _pins: PhantomData,
338 }
339 }
340}
341
342impl<TIM, REMAP, P, PINS> PwmHz<TIM, REMAP, P, PINS>
343where
344 TIM: Instance + WithPwm,
345 REMAP: Remap<Periph = TIM>,
346 PINS: Pins<REMAP, P>,
347{
348 pub fn enable(&mut self, channel: Channel) {
349 TIM::enable_channel(PINS::check_used(channel) as u8, true)
350 }
351
352 pub fn disable(&mut self, channel: Channel) {
353 TIM::enable_channel(PINS::check_used(channel) as u8, false)
354 }
355
356 pub fn get_duty(&self, channel: Channel) -> u16 {
357 TIM::read_cc_value(PINS::check_used(channel) as u8) as u16
358 }
359
360 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
361 TIM::set_cc_value(PINS::check_used(channel) as u8, duty as u32)
362 }
363
364 pub fn get_max_duty(&self) -> u16 {
366 (TIM::read_auto_reload() as u16).wrapping_add(1)
367 }
368
369 pub fn get_period(&self) -> Hertz {
370 let clk = self.clk;
371 let psc = self.tim.read_prescaler() as u32;
372 let arr = TIM::read_auto_reload();
373
374 clk / ((psc + 1) * (arr + 1))
376 }
377
378 pub fn set_period(&mut self, period: Hertz) {
379 let clk = self.clk;
380
381 let (psc, arr) = compute_arr_presc(period.raw(), clk.raw());
382 self.tim.set_prescaler(psc);
383 self.tim.set_auto_reload(arr).unwrap();
384 }
385}
386
387pub struct Pwm<TIM, REMAP, P, PINS, const FREQ: u32>
388where
389 TIM: Instance + WithPwm,
390 REMAP: Remap<Periph = TIM>,
391 PINS: Pins<REMAP, P>,
392{
393 timer: FTimer<TIM, FREQ>,
394 _pins: PhantomData<(REMAP, P, PINS)>,
395}
396
397impl<TIM, REMAP, P, PINS, const FREQ: u32> Pwm<TIM, REMAP, P, PINS, FREQ>
398where
399 TIM: Instance + WithPwm,
400 REMAP: Remap<Periph = TIM>,
401 PINS: Pins<REMAP, P>,
402{
403 pub fn split(self) -> PINS::Channels {
404 PINS::split()
405 }
406
407 pub fn release(mut self) -> FTimer<TIM, FREQ> {
408 self.tim.cr1_reset();
410 self.timer
411 }
412}
413
414impl<TIM, REMAP, P, PINS, const FREQ: u32> Deref for Pwm<TIM, REMAP, P, PINS, FREQ>
415where
416 TIM: Instance + WithPwm,
417 REMAP: Remap<Periph = TIM>,
418 PINS: Pins<REMAP, P>,
419{
420 type Target = FTimer<TIM, FREQ>;
421 fn deref(&self) -> &Self::Target {
422 &self.timer
423 }
424}
425
426impl<TIM, REMAP, P, PINS, const FREQ: u32> DerefMut for Pwm<TIM, REMAP, P, PINS, FREQ>
427where
428 TIM: Instance + WithPwm,
429 REMAP: Remap<Periph = TIM>,
430 PINS: Pins<REMAP, P>,
431{
432 fn deref_mut(&mut self) -> &mut Self::Target {
433 &mut self.timer
434 }
435}
436
437impl<TIM: Instance + WithPwm, const FREQ: u32> FTimer<TIM, FREQ> {
438 pub fn pwm<REMAP, P, PINS>(
439 mut self,
440 _pins: PINS,
441 mapr: &mut MAPR,
442 time: TimerDurationU32<FREQ>,
443 ) -> Pwm<TIM, REMAP, P, PINS, FREQ>
444 where
445 REMAP: Remap<Periph = TIM>,
446 PINS: Pins<REMAP, P>,
447 {
448 REMAP::remap(mapr);
449
450 if PINS::C1 {
451 self.tim
452 .preload_output_channel_in_mode(Channel::C1, Ocm::PwmMode1);
453 }
454 if PINS::C2 && TIM::CH_NUMBER > 1 {
455 self.tim
456 .preload_output_channel_in_mode(Channel::C2, Ocm::PwmMode1);
457 }
458 if PINS::C3 && TIM::CH_NUMBER > 2 {
459 self.tim
460 .preload_output_channel_in_mode(Channel::C3, Ocm::PwmMode1);
461 }
462 if PINS::C4 && TIM::CH_NUMBER > 3 {
463 self.tim
464 .preload_output_channel_in_mode(Channel::C4, Ocm::PwmMode1);
465 }
466
467 self.tim.enable_preload(true);
471
472 self.tim.set_auto_reload(time.ticks() - 1).unwrap();
473
474 self.tim.trigger_update();
476
477 self.tim.start_pwm();
478
479 Pwm {
480 timer: self,
481 _pins: PhantomData,
482 }
483 }
484}
485
486impl<TIM, REMAP, P, PINS, const FREQ: u32> Pwm<TIM, REMAP, P, PINS, FREQ>
487where
488 TIM: Instance + WithPwm,
489 REMAP: Remap<Periph = TIM>,
490 PINS: Pins<REMAP, P>,
491{
492 pub fn enable(&mut self, channel: Channel) {
493 TIM::enable_channel(PINS::check_used(channel) as u8, true)
494 }
495
496 pub fn disable(&mut self, channel: Channel) {
497 TIM::enable_channel(PINS::check_used(channel) as u8, false)
498 }
499
500 pub fn get_duty(&self, channel: Channel) -> u16 {
501 TIM::read_cc_value(PINS::check_used(channel) as u8) as u16
502 }
503
504 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
505 TIM::set_cc_value(PINS::check_used(channel) as u8, duty.into())
506 }
507
508 pub fn get_max_duty(&self) -> u16 {
510 (TIM::read_auto_reload() as u16).wrapping_add(1)
511 }
512
513 pub fn get_period(&self) -> TimerDurationU32<FREQ> {
514 TimerDurationU32::from_ticks(TIM::read_auto_reload() + 1)
515 }
516
517 pub fn set_period(&mut self, period: TimerDurationU32<FREQ>) {
518 self.tim.set_auto_reload(period.ticks() - 1).unwrap();
519 }
520}