1use core::marker::PhantomData;
4use core::mem::ManuallyDrop;
5
6use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
7use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin};
8#[cfg(gpio_v2)]
9use crate::gpio::Pull;
10use crate::gpio::{AfType, AnyPin, OutputType, Speed};
11use crate::time::Hertz;
12use crate::Peri;
13
14pub struct PwmPin<'d, T, C> {
18 _pin: Peri<'d, AnyPin>,
19 phantom: PhantomData<(T, C)>,
20}
21
22#[derive(Debug, Copy, Clone)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27pub struct PwmPinConfig {
28 pub output_type: OutputType,
30 pub speed: Speed,
32 #[cfg(gpio_v2)]
34 pub pull: Pull,
35}
36
37impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
38 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self {
40 critical_section::with(|_| {
41 pin.set_low();
42 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
43 });
44 PwmPin {
45 _pin: pin.into(),
46 phantom: PhantomData,
47 }
48 }
49
50 pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, pin_config: PwmPinConfig) -> Self {
52 critical_section::with(|_| {
53 pin.set_low();
54 pin.set_as_af(
55 pin.af_num(),
56 #[cfg(gpio_v1)]
57 AfType::output(pin_config.output_type, pin_config.speed),
58 #[cfg(gpio_v2)]
59 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
60 );
61 });
62 PwmPin {
63 _pin: pin.into(),
64 phantom: PhantomData,
65 }
66 }
67}
68
69pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> {
75 timer: ManuallyDrop<Timer<'d, T>>,
76 channel: Channel,
77}
78
79impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> {
81 pub fn enable(&mut self) {
83 self.timer.enable_channel(self.channel, true);
84 }
85
86 pub fn disable(&mut self) {
88 self.timer.enable_channel(self.channel, false);
89 }
90
91 pub fn is_enabled(&self) -> bool {
93 self.timer.get_channel_enable_state(self.channel)
94 }
95
96 pub fn max_duty_cycle(&self) -> u16 {
100 let max = self.timer.get_max_compare_value();
101 assert!(max < u16::MAX as u32);
102 max as u16 + 1
103 }
104
105 pub fn set_duty_cycle(&mut self, duty: u16) {
109 assert!(duty <= (*self).max_duty_cycle());
110 self.timer.set_compare_value(self.channel, duty.into())
111 }
112
113 pub fn set_duty_cycle_fully_off(&mut self) {
115 self.set_duty_cycle(0);
116 }
117
118 pub fn set_duty_cycle_fully_on(&mut self) {
120 self.set_duty_cycle((*self).max_duty_cycle());
121 }
122
123 pub fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) {
128 assert!(denom != 0);
129 assert!(num <= denom);
130 let duty = u32::from(num) * u32::from(self.max_duty_cycle()) / u32::from(denom);
131
132 #[allow(clippy::cast_possible_truncation)]
134 self.set_duty_cycle(duty as u16);
135 }
136
137 pub fn set_duty_cycle_percent(&mut self, percent: u8) {
141 self.set_duty_cycle_fraction(u16::from(percent), 100)
142 }
143
144 pub fn current_duty_cycle(&self) -> u16 {
148 unwrap!(self.timer.get_compare_value(self.channel).try_into())
149 }
150
151 pub fn set_polarity(&mut self, polarity: OutputPolarity) {
153 self.timer.set_output_polarity(self.channel, polarity);
154 }
155
156 pub fn set_output_compare_mode(&mut self, mode: OutputCompareMode) {
158 self.timer.set_output_compare_mode(self.channel, mode);
159 }
160}
161
162pub struct SimplePwmChannels<'d, T: GeneralInstance4Channel> {
164 pub ch1: SimplePwmChannel<'d, T>,
166 pub ch2: SimplePwmChannel<'d, T>,
168 pub ch3: SimplePwmChannel<'d, T>,
170 pub ch4: SimplePwmChannel<'d, T>,
172}
173
174pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
176 inner: Timer<'d, T>,
177}
178
179impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
180 pub fn new(
182 tim: Peri<'d, T>,
183 _ch1: Option<PwmPin<'d, T, Ch1>>,
184 _ch2: Option<PwmPin<'d, T, Ch2>>,
185 _ch3: Option<PwmPin<'d, T, Ch3>>,
186 _ch4: Option<PwmPin<'d, T, Ch4>>,
187 freq: Hertz,
188 counting_mode: CountingMode,
189 ) -> Self {
190 Self::new_inner(tim, freq, counting_mode)
191 }
192
193 fn new_inner(tim: Peri<'d, T>, freq: Hertz, counting_mode: CountingMode) -> Self {
194 let mut this = Self { inner: Timer::new(tim) };
195
196 this.inner.set_counting_mode(counting_mode);
197 this.set_frequency(freq);
198 this.inner.enable_outputs(); this.inner.start();
200
201 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
202 .iter()
203 .for_each(|&channel| {
204 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
205
206 this.inner.set_output_compare_preload(channel, true);
207 });
208
209 this
210 }
211
212 pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> {
216 SimplePwmChannel {
217 timer: unsafe { self.inner.clone_unchecked() },
218 channel,
219 }
220 }
221
222 pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> {
228 self.channel(Channel::Ch1)
229 }
230
231 pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> {
237 self.channel(Channel::Ch2)
238 }
239
240 pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> {
246 self.channel(Channel::Ch3)
247 }
248
249 pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> {
255 self.channel(Channel::Ch4)
256 }
257
258 pub fn split(self) -> SimplePwmChannels<'static, T>
264 where
265 'd: 'static,
267 {
268 let timer = ManuallyDrop::new(self.inner);
270
271 let ch = |channel| SimplePwmChannel {
272 timer: unsafe { timer.clone_unchecked() },
273 channel,
274 };
275
276 SimplePwmChannels {
277 ch1: ch(Channel::Ch1),
278 ch2: ch(Channel::Ch2),
279 ch3: ch(Channel::Ch3),
280 ch4: ch(Channel::Ch4),
281 }
282 }
283
284 pub fn set_frequency(&mut self, freq: Hertz) {
289 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
291 2u8
292 } else {
293 1u8
294 };
295 self.inner.set_frequency_internal(freq * multiplier, 16);
296 }
297
298 pub fn max_duty_cycle(&self) -> u16 {
302 let max = self.inner.get_max_compare_value();
303 assert!(max < u16::MAX as u32);
304 max as u16 + 1
305 }
306
307 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) {
312 #[allow(clippy::let_unit_value)] let req = dma.request();
314
315 let original_duty_state = self.channel(channel).current_duty_cycle();
316 let original_enable_state = self.channel(channel).is_enabled();
317 let original_update_dma_state = self.inner.get_update_dma_state();
318
319 if !original_update_dma_state {
320 self.inner.enable_update_dma(true);
321 }
322
323 if !original_enable_state {
324 self.channel(channel).enable();
325 }
326
327 unsafe {
328 #[cfg(not(any(bdma, gpdma)))]
329 use crate::dma::{Burst, FifoThreshold};
330 use crate::dma::{Transfer, TransferOptions};
331
332 let dma_transfer_option = TransferOptions {
333 #[cfg(not(any(bdma, gpdma)))]
334 fifo_threshold: Some(FifoThreshold::Full),
335 #[cfg(not(any(bdma, gpdma)))]
336 mburst: Burst::Incr8,
337 ..Default::default()
338 };
339
340 Transfer::new_write(
341 dma,
342 req,
343 duty,
344 self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16,
345 dma_transfer_option,
346 )
347 .await
348 };
349
350 if !original_enable_state {
352 self.channel(channel).disable();
353 }
354
355 self.channel(channel).set_duty_cycle(original_duty_state);
356
357 if !original_update_dma_state {
363 self.inner.enable_update_dma(false);
364 }
365 }
366
367 pub async fn waveform_up_multi_channel(
392 &mut self,
393 dma: Peri<'_, impl super::UpDma<T>>,
394 starting_channel: Channel,
395 ending_channel: Channel,
396 duty: &[u16],
397 ) {
398 let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32;
399 let start_ch_index = starting_channel.index();
400 let end_ch_index = ending_channel.index();
401
402 assert!(start_ch_index <= end_ch_index);
403
404 let ccrx_addr = self.inner.regs_gp16().ccr(start_ch_index).as_ptr() as u32;
405 self.inner
406 .regs_gp16()
407 .dcr()
408 .modify(|w| w.set_dba(((ccrx_addr - cr1_addr) / 4) as u8));
409 self.inner
410 .regs_gp16()
411 .dcr()
412 .modify(|w| w.set_dbl((end_ch_index - start_ch_index) as u8));
413
414 #[allow(clippy::let_unit_value)] let req = dma.request();
416
417 let original_update_dma_state = self.inner.get_update_dma_state();
418 if !original_update_dma_state {
419 self.inner.enable_update_dma(true);
420 }
421
422 unsafe {
423 #[cfg(not(any(bdma, gpdma)))]
424 use crate::dma::{Burst, FifoThreshold};
425 use crate::dma::{Transfer, TransferOptions};
426
427 let dma_transfer_option = TransferOptions {
428 #[cfg(not(any(bdma, gpdma)))]
429 fifo_threshold: Some(FifoThreshold::Full),
430 #[cfg(not(any(bdma, gpdma)))]
431 mburst: Burst::Incr4,
432 ..Default::default()
433 };
434
435 Transfer::new_write(
436 dma,
437 req,
438 duty,
439 self.inner.regs_gp16().dmar().as_ptr() as *mut u16,
440 dma_transfer_option,
441 )
442 .await
443 };
444
445 if !original_update_dma_state {
446 self.inner.enable_update_dma(false);
447 }
448 }
449}
450
451impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
452 pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
454 use crate::pac::timer::vals::Ccds;
455
456 #[allow(clippy::let_unit_value)] let req = dma.request();
458
459 let cc_channel = C::CHANNEL;
460
461 let original_duty_state = self.channel(cc_channel).current_duty_cycle();
462 let original_enable_state = self.channel(cc_channel).is_enabled();
463 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE;
464 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
465
466 if !original_cc_dma_on_update {
468 self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
469 }
470
471 if !original_cc_dma_enabled {
472 self.inner.set_cc_dma_enable_state(cc_channel, true);
473 }
474
475 if !original_enable_state {
476 self.channel(cc_channel).enable();
477 }
478
479 unsafe {
480 #[cfg(not(any(bdma, gpdma)))]
481 use crate::dma::{Burst, FifoThreshold};
482 use crate::dma::{Transfer, TransferOptions};
483
484 let dma_transfer_option = TransferOptions {
485 #[cfg(not(any(bdma, gpdma)))]
486 fifo_threshold: Some(FifoThreshold::Full),
487 #[cfg(not(any(bdma, gpdma)))]
488 mburst: Burst::Incr8,
489 ..Default::default()
490 };
491
492 match self.inner.bits() {
493 TimerBits::Bits16 => {
494 Transfer::new_write(
495 dma,
496 req,
497 duty,
498 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
499 dma_transfer_option,
500 )
501 .await
502 }
503 #[cfg(not(any(stm32l0)))]
504 TimerBits::Bits32 => {
505 #[cfg(not(any(bdma, gpdma)))]
506 panic!("unsupported timer bits");
507
508 #[cfg(any(bdma, gpdma))]
509 Transfer::new_write(
510 dma,
511 req,
512 duty,
513 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
514 dma_transfer_option,
515 )
516 .await
517 }
518 };
519 };
520
521 if !original_enable_state {
523 self.channel(cc_channel).disable();
524 }
525
526 self.channel(cc_channel).set_duty_cycle(original_duty_state);
527
528 if !original_cc_dma_enabled {
534 self.inner.set_cc_dma_enable_state(cc_channel, false);
535 }
536
537 if !original_cc_dma_on_update {
538 self.inner.set_cc_dma_selection(Ccds::ON_COMPARE)
539 }
540 }
541}
542
543impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
544 type Error = core::convert::Infallible;
545}
546
547impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for SimplePwmChannel<'d, T> {
548 fn max_duty_cycle(&self) -> u16 {
549 self.max_duty_cycle()
550 }
551
552 fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
553 self.set_duty_cycle(duty);
554 Ok(())
555 }
556
557 fn set_duty_cycle_fully_off(&mut self) -> Result<(), Self::Error> {
558 self.set_duty_cycle_fully_off();
559 Ok(())
560 }
561
562 fn set_duty_cycle_fully_on(&mut self) -> Result<(), Self::Error> {
563 self.set_duty_cycle_fully_on();
564 Ok(())
565 }
566
567 fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) -> Result<(), Self::Error> {
568 self.set_duty_cycle_fraction(num, denom);
569 Ok(())
570 }
571
572 fn set_duty_cycle_percent(&mut self, percent: u8) -> Result<(), Self::Error> {
573 self.set_duty_cycle_percent(percent);
574 Ok(())
575 }
576}
577
578impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
579 type Channel = Channel;
580 type Time = Hertz;
581 type Duty = u32;
582
583 fn disable(&mut self, channel: Self::Channel) {
584 self.inner.enable_channel(channel, false);
585 }
586
587 fn enable(&mut self, channel: Self::Channel) {
588 self.inner.enable_channel(channel, true);
589 }
590
591 fn get_period(&self) -> Self::Time {
592 self.inner.get_frequency()
593 }
594
595 fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
596 self.inner.get_compare_value(channel)
597 }
598
599 fn get_max_duty(&self) -> Self::Duty {
600 self.inner.get_max_compare_value() + 1
601 }
602
603 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
604 assert!(duty <= self.max_duty_cycle() as u32);
605 self.inner.set_compare_value(channel, duty)
606 }
607
608 fn set_period<P>(&mut self, period: P)
609 where
610 P: Into<Self::Time>,
611 {
612 self.inner.set_frequency(period.into());
613 }
614}