1use cast::{u16, u32};
2use core::{marker::PhantomData, mem::MaybeUninit};
3
4use crate::rcc::Rcc;
5
6use crate::time::Hertz;
7use embedded_hal as hal;
8
9pub trait Pins<TIM, P> {
10 const C1: bool = false;
11 const C2: bool = false;
12 const C3: bool = false;
13 const C4: bool = false;
14 type Channels;
15}
16use crate::timers::PinC1;
17use crate::timers::PinC2;
18use crate::timers::PinC3;
19use crate::timers::PinC4;
20
21pub struct C1;
22pub struct C2;
23pub struct C3;
24pub struct C4;
25
26pub struct PwmChannels<TIM, CHANNELS> {
27 _channel: PhantomData<CHANNELS>,
28 _tim: PhantomData<TIM>,
29}
30
31macro_rules! pins_impl {
32 ( $( ( $($PINX:ident),+ ), ( $($TRAIT:ident),+ ), ( $($ENCHX:ident),* ); )+ ) => {
33 $(
34 #[allow(unused_parens)]
35 impl<TIM, $($PINX,)+> Pins<TIM, ($($ENCHX),+)> for ($($PINX),+)
36 where
37 $($PINX: $TRAIT<TIM>,)+
38 {
39 $(const $ENCHX: bool = true;)+
40 type Channels = ($(PwmChannels<TIM, $ENCHX>),+);
41 }
42 )+
43 };
44}
45
46pins_impl!(
47 (P1, P2, P3, P4), (PinC1, PinC2, PinC3, PinC4), (C1, C2, C3, C4);
48 (P2, P3, P4), (PinC2, PinC3, PinC4), (C2, C3, C4);
49 (P1, P3, P4), (PinC1, PinC3, PinC4), (C1, C3, C4);
50 (P1, P2, P4), (PinC1, PinC2, PinC4), (C1, C2, C4);
51 (P1, P2, P3), (PinC1, PinC2, PinC3), (C1, C2, C3);
52 (P3, P4), (PinC3, PinC4), (C3, C4);
53 (P2, P4), (PinC2, PinC4), (C2, C4);
54 (P2, P3), (PinC2, PinC3), (C2, C3);
55 (P1, P4), (PinC1, PinC4), (C1, C4);
56 (P1, P3), (PinC1, PinC3), (C1, C3);
57 (P1, P2), (PinC1, PinC2), (C1, C2);
58 (P1), (PinC1), (C1);
59 (P2), (PinC2), (C2);
60 (P3), (PinC3), (C3);
61 (P4), (PinC4), (C4);
62);
63
64impl<TIM, P1: PinC1<TIM>, P2: PinC1<TIM>> PinC1<TIM> for (P1, P2) {}
65impl<TIM, P1: PinC2<TIM>, P2: PinC2<TIM>> PinC2<TIM> for (P1, P2) {}
66impl<TIM, P1: PinC3<TIM>, P2: PinC3<TIM>> PinC3<TIM> for (P1, P2) {}
67impl<TIM, P1: PinC4<TIM>, P2: PinC4<TIM>> PinC4<TIM> for (P1, P2) {}
68
69impl<TIM, P1: PinC1<TIM>, P2: PinC1<TIM>, P3: PinC1<TIM>> PinC1<TIM> for (P1, P2, P3) {}
70impl<TIM, P1: PinC2<TIM>, P2: PinC2<TIM>, P3: PinC2<TIM>> PinC2<TIM> for (P1, P2, P3) {}
71impl<TIM, P1: PinC3<TIM>, P2: PinC3<TIM>, P3: PinC3<TIM>> PinC3<TIM> for (P1, P2, P3) {}
72impl<TIM, P1: PinC4<TIM>, P2: PinC4<TIM>, P3: PinC4<TIM>> PinC4<TIM> for (P1, P2, P3) {}
73
74impl<TIM, P1: PinC1<TIM>, P2: PinC1<TIM>, P3: PinC1<TIM>, P4: PinC1<TIM>> PinC1<TIM>
75 for (P1, P2, P3, P4)
76{
77}
78impl<TIM, P1: PinC2<TIM>, P2: PinC2<TIM>, P3: PinC2<TIM>, P4: PinC2<TIM>> PinC2<TIM>
79 for (P1, P2, P3, P4)
80{
81}
82impl<TIM, P1: PinC3<TIM>, P2: PinC3<TIM>, P3: PinC3<TIM>, P4: PinC3<TIM>> PinC3<TIM>
83 for (P1, P2, P3, P4)
84{
85}
86impl<TIM, P1: PinC4<TIM>, P2: PinC4<TIM>, P3: PinC4<TIM>, P4: PinC4<TIM>> PinC4<TIM>
87 for (P1, P2, P3, P4)
88{
89}
90
91macro_rules! brk {
93 (TIM1, $tim:ident) => {
94 $tim.bdtr.modify(|_, w| w.aoe().set_bit());
95 };
96 (TIM15, $tim:ident) => {
97 $tim.bdtr.modify(|_, w| w.aoe().set_bit());
98 };
99 (TIM16, $tim:ident) => {
100 $tim.bdtr.modify(|_, w| w.aoe().set_bit());
101 };
102 (TIM17, $tim:ident) => {
103 $tim.bdtr.modify(|_, w| w.aoe().set_bit());
104 };
105 ($_other:ident, $_tim:ident) => {};
106}
107
108macro_rules! pwm_4_channels {
110 ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
111 $(
112 pub fn $timX<P, PINS, T>(tim: $TIMX, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
113 where
114 PINS: Pins<$TIMX, P>,
115 T: Into<Hertz>,
116 {
117 rcc.regs.$apbenr.modify(|_, w| w.$timXen().set_bit());
119 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
120 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
121
122 if PINS::C1 {
123 tim.ccmr1_output()
124 .modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1() );
125 }
126 if PINS::C2 {
127 tim.ccmr1_output()
128 .modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1() );
129 }
130 if PINS::C3 {
131 tim.ccmr2_output()
132 .modify(|_, w| w.oc3pe().set_bit().oc3m().pwm_mode1() );
133 }
134 if PINS::C4 {
135 tim.ccmr2_output()
136 .modify(|_, w| w.oc4pe().set_bit().oc4m().pwm_mode1() );
137 }
138
139 let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
141 rcc.clocks.pclk().0
142 } else {
143 rcc.clocks.pclk().0 * 2
144 };
145 let ticks = tclk / freq.into().0;
146
147 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
148 tim.psc.write(|w| w.psc().bits(psc) );
149 let arr = u16(ticks / u32(psc + 1)).unwrap();
150 tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
151
152 tim.cr1.modify(|_, w| w.arpe().set_bit());
154
155 tim.cr1.modify(|_, w| w.urs().set_bit());
157 tim.egr.write(|w| w.ug().set_bit());
158 tim.cr1.modify(|_, w| w.urs().clear_bit());
159
160 brk!($TIMX, tim);
161 tim.cr1.write(|w|
162 w.cms()
163 .bits(0b00)
164 .dir()
165 .clear_bit()
166 .opm()
167 .clear_bit()
168 .cen()
169 .set_bit()
170 );
171 unsafe { MaybeUninit::uninit().assume_init() }
173 }
174
175 impl hal::PwmPin for PwmChannels<$TIMX, C1> {
176 type Duty = u16;
177
178 fn disable(&mut self) {
180 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
181 }
182
183 fn enable(&mut self) {
185 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
186 }
187
188 fn get_duty(&self) -> u16 {
190 unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }
191 }
192
193 fn get_max_duty(&self) -> u16 {
195 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
196 }
197
198 fn set_duty(&mut self, duty: u16) {
200 unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
201 }
202 }
203
204 impl hal::PwmPin for PwmChannels<$TIMX, C2> {
205 type Duty = u16;
206
207 fn disable(&mut self) {
209 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc2e().clear_bit()) };
210 }
211
212 fn enable(&mut self) {
214 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc2e().set_bit()) };
215 }
216
217 fn get_duty(&self) -> u16 {
219 unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() as u16 }
220 }
221
222 fn get_max_duty(&self) -> u16 {
224 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
225 }
226
227 fn set_duty(&mut self, duty: u16) {
229 unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) }
230 }
231 }
232
233 impl hal::PwmPin for PwmChannels<$TIMX, C3> {
234 type Duty = u16;
235
236 fn disable(&mut self) {
238 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc3e().clear_bit()) };
239 }
240
241 fn enable(&mut self) {
243 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc3e().set_bit()) };
244 }
245
246 fn get_duty(&self) -> u16 {
248 unsafe { (*$TIMX::ptr()).ccr3.read().ccr().bits() as u16 }
249 }
250
251 fn get_max_duty(&self) -> u16 {
253 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
254 }
255
256 fn set_duty(&mut self, duty: u16) {
258 unsafe { (*$TIMX::ptr()).ccr3.write(|w| w.ccr().bits(duty.into())) }
259 }
260 }
261
262 impl hal::PwmPin for PwmChannels<$TIMX, C4> {
263 type Duty = u16;
264
265 fn disable(&mut self) {
267 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc4e().clear_bit()) };
268 }
269
270 fn enable(&mut self) {
272 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc4e().set_bit()) };
273 }
274
275 fn get_duty(&self) -> u16 {
277 unsafe { (*$TIMX::ptr()).ccr4.read().ccr().bits() as u16 }
278 }
279
280 fn get_max_duty(&self) -> u16 {
282 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
283 }
284
285 fn set_duty(&mut self, duty: u16) {
287 unsafe { (*$TIMX::ptr()).ccr4.write(|w| w.ccr().bits(duty.into())) }
288 }
289 }
290 )+
291 };
292}
293
294#[cfg(any(
296 feature = "stm32f030x8",
297 feature = "stm32f030xc",
298 feature = "stm32f051",
299 feature = "stm32f058",
300 feature = "stm32f070xb",
301 feature = "stm32f071",
302 feature = "stm32f072",
303 feature = "stm32f078",
304 feature = "stm32f091",
305 feature = "stm32f098",
306))]
307macro_rules! pwm_2_channels {
308 ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
309 $(
310 pub fn $timX<P, PINS, T>(tim: $TIMX, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
311 where
312 PINS: Pins<$TIMX, P>,
313 T: Into<Hertz>,
314 {
315 rcc.regs.$apbenr.modify(|_, w| w.$timXen().set_bit());
317 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
318 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
319
320 if PINS::C1 {
321 tim.ccmr1_output().modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
322 }
323 if PINS::C2 {
324 tim.ccmr1_output().modify(|_, w| w.oc2pe().set_bit().oc1m().bits(6));
325 }
326
327 let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
329 rcc.clocks.pclk().0
330 } else {
331 rcc.clocks.pclk().0 * 2
332 };
333 let ticks = tclk / freq.into().0;
334
335 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
336 tim.psc.write(|w| w.psc().bits(psc) );
337 let arr = u16(ticks / u32(psc + 1)).unwrap();
338 tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
339
340 tim.cr1.modify(|_, w| w.arpe().set_bit());
342
343 tim.cr1.modify(|_, w| w.urs().set_bit());
345 tim.egr.write(|w| w.ug().set_bit());
346 tim.cr1.modify(|_, w| w.urs().clear_bit());
347
348 brk!($TIMX, tim);
349 tim.cr1.write(|w|
350 w.opm()
351 .clear_bit()
352 .cen()
353 .set_bit()
354 );
355 unsafe { MaybeUninit::uninit().assume_init() }
357 }
358
359 impl hal::PwmPin for PwmChannels<$TIMX, C1> {
360 type Duty = u16;
361
362 fn disable(&mut self) {
364 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
365 }
366
367 fn enable(&mut self) {
369 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
370 }
371
372 fn get_duty(&self) -> u16 {
374 unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }
375 }
376
377 fn get_max_duty(&self) -> u16 {
379 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
380 }
381
382 fn set_duty(&mut self, duty: u16) {
384 unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
385 }
386 }
387
388 impl hal::PwmPin for PwmChannels<$TIMX, C2> {
389 type Duty = u16;
390
391 fn disable(&mut self) {
393 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc2e().clear_bit()) };
394 }
395
396 fn enable(&mut self) {
398 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc2e().set_bit()) };
399 }
400
401 fn get_duty(&self) -> u16 {
403 unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() as u16 }
404 }
405
406 fn get_max_duty(&self) -> u16 {
408 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
409 }
410
411 fn set_duty(&mut self, duty: u16) {
413 unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) }
414 }
415 }
416 )+
417 };
418}
419
420macro_rules! pwm_1_channel {
422 ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
423 $(
424 pub fn $timX<P, PINS, T>(tim: $TIMX, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
425 where
426 PINS: Pins<$TIMX, P>,
427 T: Into<Hertz>,
428 {
429 rcc.regs.$apbenr.modify(|_, w| w.$timXen().set_bit());
431 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
432 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
433
434 if PINS::C1 {
435 tim.ccmr1_output().modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
436 }
437
438 let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
440 rcc.clocks.pclk().0
441 } else {
442 rcc.clocks.pclk().0 * 2
443 };
444 let ticks = tclk / freq.into().0;
445
446 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
447 tim.psc.write(|w| w.psc().bits(psc) );
448 let arr = u16(ticks / u32(psc + 1)).unwrap();
449 tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
450
451 tim.cr1.modify(|_, w| w.arpe().set_bit());
453
454 tim.cr1.modify(|_, w| w.urs().set_bit());
456 tim.egr.write(|w| w.ug().set_bit());
457 tim.cr1.modify(|_, w| w.urs().clear_bit());
458
459 brk!($TIMX, tim);
460 tim.cr1.write(|w|
461 w.cen()
462 .set_bit()
463 );
464 unsafe { MaybeUninit::uninit().assume_init() }
466 }
467
468 impl hal::PwmPin for PwmChannels<$TIMX, C1> {
469 type Duty = u16;
470
471 fn disable(&mut self) {
473 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
474 }
475
476 fn enable(&mut self) {
478 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
479 }
480
481 fn get_duty(&self) -> u16 {
483 unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }
484 }
485
486 fn get_max_duty(&self) -> u16 {
488 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
489 }
490
491 fn set_duty(&mut self, duty: u16) {
493 unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
494 }
495 }
496 )+
497 };
498}
499
500macro_rules! pwm_1_channel_with_complementary_outputs {
502 ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
503 $(
504 pub fn $timX<P, PINS, T>(tim: $TIMX, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels
505 where
506 PINS: Pins<$TIMX, P>,
507 T: Into<Hertz>,
508 {
509 rcc.regs.$apbenr.modify(|_, w| w.$timXen().set_bit());
511 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
512 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
513
514 if PINS::C1 {
515 tim.ccmr1_output().modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
516 }
517
518 let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
520 rcc.clocks.pclk().0
521 } else {
522 rcc.clocks.pclk().0 * 2
523 };
524 let ticks = tclk / freq.into().0;
525
526 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
527 tim.psc.write(|w| w.psc().bits(psc) );
528 let arr = u16(ticks / u32(psc + 1)).unwrap();
529 tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
530
531 tim.cr1.modify(|_, w| w.arpe().set_bit());
533
534 tim.cr1.modify(|_, w| w.urs().set_bit());
536 tim.egr.write(|w| w.ug().set_bit());
537 tim.cr1.modify(|_, w| w.urs().clear_bit());
538
539 brk!($TIMX, tim);
540 tim.cr1.write(|w|
541 w.opm()
542 .clear_bit()
543 .cen()
544 .set_bit()
545 );
546
547 unsafe { MaybeUninit::uninit().assume_init() }
549 }
550
551 impl hal::PwmPin for PwmChannels<$TIMX, C1> {
552 type Duty = u16;
553
554 fn disable(&mut self) {
556 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) };
557 }
558
559 fn enable(&mut self) {
561 unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) };
562 }
563
564 fn get_duty(&self) -> u16 {
566 unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }
567 }
568
569 fn get_max_duty(&self) -> u16 {
571 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
572 }
573
574 fn set_duty(&mut self, duty: u16) {
576 unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
577 }
578 }
579 )+
580 };
581}
582
583use crate::pac::*;
584
585pwm_4_channels!(
586 TIM1: (tim1, tim1en, tim1rst, apb2enr, apb2rstr),
587 TIM3: (tim3, tim3en, tim3rst, apb1enr, apb1rstr),
588);
589
590pwm_1_channel!(TIM14: (tim14, tim14en, tim14rst, apb1enr, apb1rstr),);
591
592pwm_1_channel_with_complementary_outputs!(
593 TIM16: (tim16, tim16en, tim16rst, apb2enr, apb2rstr),
594 TIM17: (tim17, tim17en, tim17rst, apb2enr, apb2rstr),
595);
596
597#[cfg(any(
598 feature = "stm32f030x8",
599 feature = "stm32f030xc",
600 feature = "stm32f051",
601 feature = "stm32f058",
602 feature = "stm32f070xb",
603 feature = "stm32f071",
604 feature = "stm32f072",
605 feature = "stm32f078",
606 feature = "stm32f091",
607 feature = "stm32f098",
608))]
609pwm_2_channels! {
610 TIM15: (tim15, tim15en, tim15rst, apb2enr, apb2rstr),
611}