1#![macro_use]
4
5use core::sync::atomic::{compiler_fence, Ordering};
6
7use embassy_hal_internal::{Peri, PeripheralType};
8
9use crate::gpio::{convert_drive, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, DISCONNECTED};
10use crate::pac::gpio::vals as gpiovals;
11use crate::pac::pwm::vals;
12use crate::ppi::{Event, Task};
13use crate::util::slice_in_ram_or;
14use crate::{interrupt, pac};
15
16pub struct SimplePwm<'d> {
19 r: pac::pwm::Pwm,
20 duty: [u16; 4],
21 ch0: Option<Peri<'d, AnyPin>>,
22 ch1: Option<Peri<'d, AnyPin>>,
23 ch2: Option<Peri<'d, AnyPin>>,
24 ch3: Option<Peri<'d, AnyPin>>,
25}
26
27pub struct SequencePwm<'d> {
30 r: pac::pwm::Pwm,
31 ch0: Option<Peri<'d, AnyPin>>,
32 ch1: Option<Peri<'d, AnyPin>>,
33 ch2: Option<Peri<'d, AnyPin>>,
34 ch3: Option<Peri<'d, AnyPin>>,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40#[non_exhaustive]
41pub enum Error {
42 SequenceTooLong,
44 SequenceTimesAtLeastOne,
46 BufferNotInRAM,
48}
49
50const MAX_SEQUENCE_LEN: usize = 32767;
51pub const PWM_CLK_HZ: u32 = 16_000_000;
53
54impl<'d> SequencePwm<'d> {
55 #[allow(unused_unsafe)]
57 pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result<Self, Error> {
58 Self::new_inner(pwm, Some(ch0.into()), None, None, None, config)
59 }
60
61 #[allow(unused_unsafe)]
63 pub fn new_2ch<T: Instance>(
64 pwm: Peri<'d, T>,
65 ch0: Peri<'d, impl GpioPin>,
66 ch1: Peri<'d, impl GpioPin>,
67 config: Config,
68 ) -> Result<Self, Error> {
69 Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None, config)
70 }
71
72 #[allow(unused_unsafe)]
74 pub fn new_3ch<T: Instance>(
75 pwm: Peri<'d, T>,
76 ch0: Peri<'d, impl GpioPin>,
77 ch1: Peri<'d, impl GpioPin>,
78 ch2: Peri<'d, impl GpioPin>,
79 config: Config,
80 ) -> Result<Self, Error> {
81 Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None, config)
82 }
83
84 #[allow(unused_unsafe)]
86 pub fn new_4ch<T: Instance>(
87 pwm: Peri<'d, T>,
88 ch0: Peri<'d, impl GpioPin>,
89 ch1: Peri<'d, impl GpioPin>,
90 ch2: Peri<'d, impl GpioPin>,
91 ch3: Peri<'d, impl GpioPin>,
92 config: Config,
93 ) -> Result<Self, Error> {
94 Self::new_inner(
95 pwm,
96 Some(ch0.into()),
97 Some(ch1.into()),
98 Some(ch2.into()),
99 Some(ch3.into()),
100 config,
101 )
102 }
103
104 fn new_inner<T: Instance>(
105 _pwm: Peri<'d, T>,
106 ch0: Option<Peri<'d, AnyPin>>,
107 ch1: Option<Peri<'d, AnyPin>>,
108 ch2: Option<Peri<'d, AnyPin>>,
109 ch3: Option<Peri<'d, AnyPin>>,
110 config: Config,
111 ) -> Result<Self, Error> {
112 let r = T::regs();
113
114 if let Some(pin) = &ch0 {
115 pin.set_low();
116 pin.conf().write(|w| {
117 w.set_dir(gpiovals::Dir::OUTPUT);
118 w.set_input(gpiovals::Input::DISCONNECT);
119 convert_drive(w, config.ch0_drive);
120 });
121 }
122 if let Some(pin) = &ch1 {
123 pin.set_low();
124 pin.conf().write(|w| {
125 w.set_dir(gpiovals::Dir::OUTPUT);
126 w.set_input(gpiovals::Input::DISCONNECT);
127 convert_drive(w, config.ch1_drive);
128 });
129 }
130 if let Some(pin) = &ch2 {
131 pin.set_low();
132 pin.conf().write(|w| {
133 w.set_dir(gpiovals::Dir::OUTPUT);
134 w.set_input(gpiovals::Input::DISCONNECT);
135 convert_drive(w, config.ch2_drive);
136 });
137 }
138 if let Some(pin) = &ch3 {
139 pin.set_low();
140 pin.conf().write(|w| {
141 w.set_dir(gpiovals::Dir::OUTPUT);
142 w.set_input(gpiovals::Input::DISCONNECT);
143 convert_drive(w, config.ch3_drive);
144 });
145 }
146
147 r.psel().out(0).write_value(ch0.psel_bits());
148 r.psel().out(1).write_value(ch1.psel_bits());
149 r.psel().out(2).write_value(ch2.psel_bits());
150 r.psel().out(3).write_value(ch3.psel_bits());
151
152 r.intenclr().write(|w| w.0 = 0xFFFF_FFFF);
154 r.shorts().write(|_| ());
155 r.events_stopped().write_value(0);
156 r.events_loopsdone().write_value(0);
157 r.events_seqend(0).write_value(0);
158 r.events_seqend(1).write_value(0);
159 r.events_pwmperiodend().write_value(0);
160 r.events_seqstarted(0).write_value(0);
161 r.events_seqstarted(1).write_value(0);
162
163 r.decoder().write(|w| {
164 w.set_load(vals::Load::from_bits(config.sequence_load as u8));
165 w.set_mode(vals::Mode::REFRESH_COUNT);
166 });
167
168 r.mode().write(|w| match config.counter_mode {
169 CounterMode::UpAndDown => w.set_updown(vals::Updown::UP_AND_DOWN),
170 CounterMode::Up => w.set_updown(vals::Updown::UP),
171 });
172 r.prescaler()
173 .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8)));
174 r.countertop().write(|w| w.set_countertop(config.max_duty));
175
176 Ok(Self {
177 r: T::regs(),
178 ch0,
179 ch1,
180 ch2,
181 ch3,
182 })
183 }
184
185 #[inline(always)]
187 pub fn event_stopped(&self) -> Event<'d> {
188 Event::from_reg(self.r.events_stopped())
189 }
190
191 #[inline(always)]
193 pub fn event_loops_done(&self) -> Event<'d> {
194 Event::from_reg(self.r.events_loopsdone())
195 }
196
197 #[inline(always)]
199 pub fn event_pwm_period_end(&self) -> Event<'d> {
200 Event::from_reg(self.r.events_pwmperiodend())
201 }
202
203 #[inline(always)]
205 pub fn event_seq_end(&self) -> Event<'d> {
206 Event::from_reg(self.r.events_seqend(0))
207 }
208
209 #[inline(always)]
211 pub fn event_seq1_end(&self) -> Event<'d> {
212 Event::from_reg(self.r.events_seqend(1))
213 }
214
215 #[inline(always)]
217 pub fn event_seq0_started(&self) -> Event<'d> {
218 Event::from_reg(self.r.events_seqstarted(0))
219 }
220
221 #[inline(always)]
223 pub fn event_seq1_started(&self) -> Event<'d> {
224 Event::from_reg(self.r.events_seqstarted(1))
225 }
226
227 #[inline(always)]
232 pub unsafe fn task_start_seq0(&self) -> Task<'d> {
233 Task::from_reg(self.r.tasks_seqstart(0))
234 }
235
236 #[inline(always)]
241 pub unsafe fn task_start_seq1(&self) -> Task<'d> {
242 Task::from_reg(self.r.tasks_seqstart(1))
243 }
244
245 #[inline(always)]
250 pub unsafe fn task_next_step(&self) -> Task<'d> {
251 Task::from_reg(self.r.tasks_nextstep())
252 }
253
254 #[inline(always)]
259 pub unsafe fn task_stop(&self) -> Task<'d> {
260 Task::from_reg(self.r.tasks_stop())
261 }
262}
263
264impl<'a> Drop for SequencePwm<'a> {
265 fn drop(&mut self) {
266 if let Some(pin) = &self.ch0 {
267 pin.set_low();
268 pin.conf().write(|_| ());
269 self.r.psel().out(0).write_value(DISCONNECTED);
270 }
271 if let Some(pin) = &self.ch1 {
272 pin.set_low();
273 pin.conf().write(|_| ());
274 self.r.psel().out(1).write_value(DISCONNECTED);
275 }
276 if let Some(pin) = &self.ch2 {
277 pin.set_low();
278 pin.conf().write(|_| ());
279 self.r.psel().out(2).write_value(DISCONNECTED);
280 }
281 if let Some(pin) = &self.ch3 {
282 pin.set_low();
283 pin.conf().write(|_| ());
284 self.r.psel().out(3).write_value(DISCONNECTED);
285 }
286
287 self.r.enable().write(|w| w.set_enable(false));
288 }
289}
290
291#[non_exhaustive]
293pub struct Config {
294 pub counter_mode: CounterMode,
296 pub max_duty: u16,
298 pub prescaler: Prescaler,
300 pub sequence_load: SequenceLoad,
302 pub ch0_drive: OutputDrive,
304 pub ch1_drive: OutputDrive,
306 pub ch2_drive: OutputDrive,
308 pub ch3_drive: OutputDrive,
310}
311
312impl Default for Config {
313 fn default() -> Config {
314 Config {
315 counter_mode: CounterMode::Up,
316 max_duty: 1000,
317 prescaler: Prescaler::Div16,
318 sequence_load: SequenceLoad::Common,
319 ch0_drive: OutputDrive::Standard,
320 ch1_drive: OutputDrive::Standard,
321 ch2_drive: OutputDrive::Standard,
322 ch3_drive: OutputDrive::Standard,
323 }
324 }
325}
326
327#[non_exhaustive]
329#[derive(Clone)]
330pub struct SequenceConfig {
331 pub refresh: u32,
333 pub end_delay: u32,
335}
336
337impl Default for SequenceConfig {
338 fn default() -> SequenceConfig {
339 SequenceConfig {
340 refresh: 0,
341 end_delay: 0,
342 }
343 }
344}
345
346#[non_exhaustive]
348pub struct Sequence<'s> {
349 pub words: &'s [u16],
351 pub config: SequenceConfig,
353}
354
355impl<'s> Sequence<'s> {
356 pub fn new(words: &'s [u16], config: SequenceConfig) -> Self {
358 Self { words, config }
359 }
360}
361
362#[non_exhaustive]
365pub struct SingleSequencer<'d, 's> {
366 sequencer: Sequencer<'d, 's>,
367}
368
369impl<'d, 's> SingleSequencer<'d, 's> {
370 pub fn new(pwm: &'s mut SequencePwm<'d>, words: &'s [u16], config: SequenceConfig) -> Self {
372 Self {
373 sequencer: Sequencer::new(pwm, Sequence::new(words, config), None),
374 }
375 }
376
377 #[inline(always)]
379 pub fn start(&self, times: SingleSequenceMode) -> Result<(), Error> {
380 let (start_seq, times) = match times {
381 SingleSequenceMode::Times(n) if n == 1 => (StartSequence::One, SequenceMode::Loop(1)),
382 SingleSequenceMode::Times(n) if n & 1 == 1 => (StartSequence::One, SequenceMode::Loop((n / 2) + 1)),
383 SingleSequenceMode::Times(n) => (StartSequence::Zero, SequenceMode::Loop(n / 2)),
384 SingleSequenceMode::Infinite => (StartSequence::Zero, SequenceMode::Infinite),
385 };
386 self.sequencer.start(start_seq, times)
387 }
388
389 #[inline(always)]
393 pub fn stop(&self) {
394 self.sequencer.stop();
395 }
396}
397
398#[non_exhaustive]
404pub struct Sequencer<'d, 's> {
405 _pwm: &'s mut SequencePwm<'d>,
406 sequence0: Sequence<'s>,
407 sequence1: Option<Sequence<'s>>,
408}
409
410impl<'d, 's> Sequencer<'d, 's> {
411 pub fn new(pwm: &'s mut SequencePwm<'d>, sequence0: Sequence<'s>, sequence1: Option<Sequence<'s>>) -> Self {
414 Sequencer {
415 _pwm: pwm,
416 sequence0,
417 sequence1,
418 }
419 }
420
421 #[inline(always)]
423 pub fn start(&self, start_seq: StartSequence, times: SequenceMode) -> Result<(), Error> {
424 let sequence0 = &self.sequence0;
425 let alt_sequence = self.sequence1.as_ref().unwrap_or(&self.sequence0);
426
427 slice_in_ram_or(sequence0.words, Error::BufferNotInRAM)?;
428 slice_in_ram_or(alt_sequence.words, Error::BufferNotInRAM)?;
429
430 if sequence0.words.len() > MAX_SEQUENCE_LEN || alt_sequence.words.len() > MAX_SEQUENCE_LEN {
431 return Err(Error::SequenceTooLong);
432 }
433
434 if let SequenceMode::Loop(0) = times {
435 return Err(Error::SequenceTimesAtLeastOne);
436 }
437
438 self.stop();
439
440 let r = self._pwm.r;
441
442 r.seq(0).refresh().write(|w| w.0 = sequence0.config.refresh);
443 r.seq(0).enddelay().write(|w| w.0 = sequence0.config.end_delay);
444 r.seq(0).ptr().write_value(sequence0.words.as_ptr() as u32);
445 r.seq(0).cnt().write(|w| w.0 = sequence0.words.len() as u32);
446
447 r.seq(1).refresh().write(|w| w.0 = alt_sequence.config.refresh);
448 r.seq(1).enddelay().write(|w| w.0 = alt_sequence.config.end_delay);
449 r.seq(1).ptr().write_value(alt_sequence.words.as_ptr() as u32);
450 r.seq(1).cnt().write(|w| w.0 = alt_sequence.words.len() as u32);
451
452 r.enable().write(|w| w.set_enable(true));
453
454 compiler_fence(Ordering::SeqCst);
456
457 let seqstart_index = if start_seq == StartSequence::One { 1 } else { 0 };
458
459 match times {
460 SequenceMode::Loop(n) => {
461 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::from_bits(n)));
462 }
463 SequenceMode::Infinite => {
465 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::from_bits(1)));
466 r.shorts().write(|w| w.set_loopsdone_seqstart0(true));
467 }
468 }
469
470 r.tasks_seqstart(seqstart_index).write_value(1);
471
472 Ok(())
473 }
474
475 #[inline(always)]
479 pub fn stop(&self) {
480 let r = self._pwm.r;
481
482 r.shorts().write(|_| ());
483
484 compiler_fence(Ordering::SeqCst);
485
486 r.tasks_stop().write_value(1);
487 r.enable().write(|w| w.set_enable(false));
488 }
489}
490
491impl<'d, 's> Drop for Sequencer<'d, 's> {
492 fn drop(&mut self) {
493 self.stop();
494 }
495}
496
497#[derive(Debug, Eq, PartialEq, Clone, Copy)]
499pub enum SingleSequenceMode {
500 Times(u16),
502 Infinite,
504}
505
506#[derive(Debug, Eq, PartialEq, Clone, Copy)]
508pub enum StartSequence {
509 Zero,
511 One,
513}
514
515#[derive(Debug, Eq, PartialEq, Clone, Copy)]
517pub enum SequenceMode {
518 Loop(u16),
520 Infinite,
522}
523
524#[derive(Debug, Eq, PartialEq, Clone, Copy)]
526pub enum Prescaler {
527 Div1,
529 Div2,
531 Div4,
533 Div8,
535 Div16,
537 Div32,
539 Div64,
541 Div128,
543}
544
545#[derive(Debug, Eq, PartialEq, Clone, Copy)]
547pub enum SequenceLoad {
548 Common,
550 Grouped,
553 Individual,
556 Waveform,
559}
560
561#[derive(Debug, Eq, PartialEq, Clone, Copy)]
563pub enum CounterMode {
564 Up,
566 UpAndDown,
568}
569
570impl<'d> SimplePwm<'d> {
571 #[allow(unused_unsafe)]
573 pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>) -> Self {
574 unsafe { Self::new_inner(pwm, Some(ch0.into()), None, None, None) }
575 }
576
577 #[allow(unused_unsafe)]
579 pub fn new_2ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, ch1: Peri<'d, impl GpioPin>) -> Self {
580 Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None)
581 }
582
583 #[allow(unused_unsafe)]
585 pub fn new_3ch<T: Instance>(
586 pwm: Peri<'d, T>,
587 ch0: Peri<'d, impl GpioPin>,
588 ch1: Peri<'d, impl GpioPin>,
589 ch2: Peri<'d, impl GpioPin>,
590 ) -> Self {
591 unsafe { Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None) }
592 }
593
594 #[allow(unused_unsafe)]
596 pub fn new_4ch<T: Instance>(
597 pwm: Peri<'d, T>,
598 ch0: Peri<'d, impl GpioPin>,
599 ch1: Peri<'d, impl GpioPin>,
600 ch2: Peri<'d, impl GpioPin>,
601 ch3: Peri<'d, impl GpioPin>,
602 ) -> Self {
603 unsafe {
604 Self::new_inner(
605 pwm,
606 Some(ch0.into()),
607 Some(ch1.into()),
608 Some(ch2.into()),
609 Some(ch3.into()),
610 )
611 }
612 }
613
614 fn new_inner<T: Instance>(
615 _pwm: Peri<'d, T>,
616 ch0: Option<Peri<'d, AnyPin>>,
617 ch1: Option<Peri<'d, AnyPin>>,
618 ch2: Option<Peri<'d, AnyPin>>,
619 ch3: Option<Peri<'d, AnyPin>>,
620 ) -> Self {
621 let r = T::regs();
622
623 for (i, ch) in [&ch0, &ch1, &ch2, &ch3].into_iter().enumerate() {
624 if let Some(pin) = ch {
625 pin.set_low();
626
627 pin.conf().write(|w| {
628 w.set_dir(gpiovals::Dir::OUTPUT);
629 w.set_input(gpiovals::Input::DISCONNECT);
630 w.set_drive(gpiovals::Drive::S0S1);
631 });
632 }
633 r.psel().out(i).write_value(ch.psel_bits());
634 }
635
636 let pwm = Self {
637 r: T::regs(),
638 ch0,
639 ch1,
640 ch2,
641 ch3,
642 duty: [0; 4],
643 };
644
645 r.intenclr().write(|w| w.0 = 0xFFFF_FFFF);
647 r.shorts().write(|_| ());
648
649 r.enable().write(|w| w.set_enable(true));
651
652 r.seq(0).ptr().write_value((pwm.duty).as_ptr() as u32);
653 r.seq(0).cnt().write(|w| w.0 = 4);
654 r.seq(0).refresh().write(|w| w.0 = 0);
655 r.seq(0).enddelay().write(|w| w.0 = 0);
656
657 r.decoder().write(|w| {
658 w.set_load(vals::Load::INDIVIDUAL);
659 w.set_mode(vals::Mode::REFRESH_COUNT);
660 });
661 r.mode().write(|w| w.set_updown(vals::Updown::UP));
662 r.prescaler().write(|w| w.set_prescaler(vals::Prescaler::DIV_16));
663 r.countertop().write(|w| w.set_countertop(1000));
664 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::DISABLED));
665
666 pwm
667 }
668
669 #[inline(always)]
671 pub fn is_enabled(&self) -> bool {
672 self.r.enable().read().enable()
673 }
674
675 #[inline(always)]
677 pub fn enable(&self) {
678 self.r.enable().write(|w| w.set_enable(true));
679 }
680
681 #[inline(always)]
683 pub fn disable(&self) {
684 self.r.enable().write(|w| w.set_enable(false));
685 }
686
687 pub fn duty(&self, channel: usize) -> u16 {
689 self.duty[channel]
690 }
691
692 pub fn set_duty(&mut self, channel: usize, duty: u16) {
694 self.duty[channel] = duty & 0x7FFF;
695
696 self.r.seq(0).ptr().write_value((self.duty).as_ptr() as u32);
698
699 compiler_fence(Ordering::SeqCst);
701
702 self.r.events_seqend(0).write_value(0);
703
704 self.r.tasks_seqstart(0).write_value(1);
706
707 if self.is_enabled() {
710 while self.r.events_seqend(0).read() == 0 {}
711 }
712 }
713
714 #[inline(always)]
716 pub fn set_prescaler(&self, div: Prescaler) {
717 self.r
718 .prescaler()
719 .write(|w| w.set_prescaler(vals::Prescaler::from_bits(div as u8)));
720 }
721
722 #[inline(always)]
724 pub fn prescaler(&self) -> Prescaler {
725 match self.r.prescaler().read().prescaler().to_bits() {
726 0 => Prescaler::Div1,
727 1 => Prescaler::Div2,
728 2 => Prescaler::Div4,
729 3 => Prescaler::Div8,
730 4 => Prescaler::Div16,
731 5 => Prescaler::Div32,
732 6 => Prescaler::Div64,
733 7 => Prescaler::Div128,
734 _ => unreachable!(),
735 }
736 }
737
738 #[inline(always)]
740 pub fn set_max_duty(&self, duty: u16) {
741 self.r.countertop().write(|w| w.set_countertop(duty.min(32767u16)));
742 }
743
744 #[inline(always)]
746 pub fn max_duty(&self) -> u16 {
747 self.r.countertop().read().countertop()
748 }
749
750 #[inline(always)]
752 pub fn set_period(&self, freq: u32) {
753 let clk = PWM_CLK_HZ >> (self.prescaler() as u8);
754 let duty = clk / freq;
755 self.set_max_duty(duty.min(32767) as u16);
756 }
757
758 #[inline(always)]
760 pub fn period(&self) -> u32 {
761 let clk = PWM_CLK_HZ >> (self.prescaler() as u8);
762 let max_duty = self.max_duty() as u32;
763 clk / max_duty
764 }
765
766 #[inline(always)]
768 pub fn set_ch0_drive(&self, drive: OutputDrive) {
769 if let Some(pin) = &self.ch0 {
770 pin.conf().modify(|w| convert_drive(w, drive));
771 }
772 }
773
774 #[inline(always)]
776 pub fn set_ch1_drive(&self, drive: OutputDrive) {
777 if let Some(pin) = &self.ch1 {
778 pin.conf().modify(|w| convert_drive(w, drive));
779 }
780 }
781
782 #[inline(always)]
784 pub fn set_ch2_drive(&self, drive: OutputDrive) {
785 if let Some(pin) = &self.ch2 {
786 pin.conf().modify(|w| convert_drive(w, drive));
787 }
788 }
789
790 #[inline(always)]
792 pub fn set_ch3_drive(&self, drive: OutputDrive) {
793 if let Some(pin) = &self.ch3 {
794 pin.conf().modify(|w| convert_drive(w, drive));
795 }
796 }
797}
798
799impl<'a> Drop for SimplePwm<'a> {
800 fn drop(&mut self) {
801 let r = &self.r;
802
803 self.disable();
804
805 if let Some(pin) = &self.ch0 {
806 pin.set_low();
807 pin.conf().write(|_| ());
808 r.psel().out(0).write_value(DISCONNECTED);
809 }
810 if let Some(pin) = &self.ch1 {
811 pin.set_low();
812 pin.conf().write(|_| ());
813 r.psel().out(1).write_value(DISCONNECTED);
814 }
815 if let Some(pin) = &self.ch2 {
816 pin.set_low();
817 pin.conf().write(|_| ());
818 r.psel().out(2).write_value(DISCONNECTED);
819 }
820 if let Some(pin) = &self.ch3 {
821 pin.set_low();
822 pin.conf().write(|_| ());
823 r.psel().out(3).write_value(DISCONNECTED);
824 }
825 }
826}
827
828pub(crate) trait SealedInstance {
829 fn regs() -> pac::pwm::Pwm;
830}
831
832#[allow(private_bounds)]
834pub trait Instance: SealedInstance + PeripheralType + 'static {
835 type Interrupt: interrupt::typelevel::Interrupt;
837}
838
839macro_rules! impl_pwm {
840 ($type:ident, $pac_type:ident, $irq:ident) => {
841 impl crate::pwm::SealedInstance for peripherals::$type {
842 fn regs() -> pac::pwm::Pwm {
843 pac::$pac_type
844 }
845 }
846 impl crate::pwm::Instance for peripherals::$type {
847 type Interrupt = crate::interrupt::typelevel::$irq;
848 }
849 };
850}