rp2040_hal/pwm/
mod.rs

1//! Pulse Width Modulation (PWM)
2//!
3//! First you must create a Slices struct which contains all the pwm slices.
4//!
5//! ```no_run
6//! use rp2040_hal::{prelude::*, pwm::{InputHighRunning, Slices}};
7//!
8//!
9//! let mut pac = rp2040_pac::Peripherals::take().unwrap();
10//!
11//! // Init PWMs
12//! let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
13//!
14//! // Configure PWM4
15//! let mut pwm = pwm_slices.pwm4;
16//! pwm.set_ph_correct();
17//! pwm.enable();
18//!
19//! // Set to run when b channel is high
20//! let pwm  = pwm.into_mode::<InputHighRunning>();
21//! ```
22//!
23//! Once you have the PWM slice struct, you can add individual pins:
24//!
25//! ```no_run
26//! # use rp2040_hal::{prelude::*, gpio::Pins, Sio, pwm::{InputHighRunning, Slices}};
27//! # let mut pac = rp2040_pac::Peripherals::take().unwrap();
28//! # let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
29//! # let mut pwm = pwm_slices.pwm4.into_mode::<InputHighRunning>();
30//! # let mut pac = rp2040_pac::Peripherals::take().unwrap();
31//! #
32//! # let sio = Sio::new(pac.SIO);
33//! # let pins = Pins::new(
34//! #     pac.IO_BANK0,
35//! #     pac.PADS_BANK0,
36//! #     sio.gpio_bank0,
37//! #     &mut pac.RESETS,
38//! # );
39//! #
40//! use embedded_hal::pwm::SetDutyCycle;
41//!
42//! // Use B channel (which inputs from GPIO 25)
43//! let mut channel_b = pwm.channel_b;
44//! let channel_pin_b = channel_b.input_from(pins.gpio25);
45//!
46//! // Use A channel (which outputs to GPIO 24)
47//! let mut channel_a = pwm.channel_a;
48//! let channel_pin_a = channel_a.output_to(pins.gpio24);
49//!
50//! // Set duty cycle
51//! channel_a.set_duty_cycle(0x00ff);
52//! let max_duty_cycle = channel_a.max_duty_cycle();
53//! channel_a.set_inverted(); // Invert the output
54//! channel_a.clr_inverted(); // Don't invert the output
55//! ```
56//!
57//! The following configuration options are also available:
58//!
59//! ```no_run
60//! # use rp2040_hal::{prelude::*, pwm::Slices};
61//! # let mut pac = rp2040_pac::Peripherals::take().unwrap();
62//! # let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
63//! # let mut pwm = pwm_slices.pwm4;
64//! pwm.set_ph_correct(); // Run in phase correct mode
65//! pwm.clr_ph_correct(); // Don't run in phase correct mode
66//!
67//! pwm.set_div_int(1u8); // To set integer part of clock divider
68//! pwm.set_div_frac(0u8); // To set fractional part of clock divider
69//!
70//! pwm.get_top(); // To get the TOP register
71//! pwm.set_top(u16::MAX); // To set the TOP register
72//!
73//! ```
74//!
75//! default_config() sets ph_correct to false, the clock divider to 1, does not invert the output, sets top to 65535, and resets the counter.
76//! min_config() leaves those registers in the state they were before it was called (Careful, this can lead to unexpected behavior)
77//! It's recommended to only call min_config() after calling default_config() on a pin that shares a PWM block.
78
79use core::convert::Infallible;
80use core::marker::PhantomData;
81
82use embedded_dma::Word;
83use embedded_hal::pwm::{ErrorType, SetDutyCycle};
84
85use crate::{
86    atomic_register_access::{write_bitmask_clear, write_bitmask_set},
87    dma::{EndlessWriteTarget, WriteTarget},
88    gpio::{bank0::*, AnyPin, FunctionPwm, Pin, ValidFunction},
89    pac::{self, dma::ch::ch_al1_ctrl::TREQ_SEL_A, PWM},
90    resets::SubsystemReset,
91    typelevel::{Is, Sealed},
92};
93
94pub mod dyn_slice;
95pub use dyn_slice::*;
96
97mod reg;
98
99use reg::RegisterInterface;
100
101/// Used to pin traits to a specific channel (A or B)
102pub trait ChannelId: Sealed {
103    /// Corresponding [`DynChannelId`]
104    const DYN: DynChannelId;
105}
106
107/// Channel A
108///
109/// These are attached to the even gpio pins and can only do PWM output
110pub enum A {}
111
112/// Channel B
113///
114/// These are attached to the odd gpio pins and can do PWM output and edge counting for input
115pub enum B {}
116
117impl ChannelId for A {
118    const DYN: DynChannelId = DynChannelId::A;
119}
120impl ChannelId for B {
121    const DYN: DynChannelId = DynChannelId::B;
122}
123impl Sealed for A {}
124impl Sealed for B {}
125
126/// Counter is free-running, and will count continuously whenever the slice is enabled
127pub struct FreeRunning;
128/// Count continuously when a high level is detected on the B pin
129pub struct InputHighRunning;
130/// Count once with each rising edge detected on the B pin
131pub struct CountRisingEdge;
132/// Count once with each falling edge detected on the B pin
133pub struct CountFallingEdge;
134
135/// Type-level marker for tracking which slice modes are valid for which slices
136pub trait ValidSliceMode<I: SliceId>: Sealed + SliceMode {}
137
138/// Type-level marker for tracking which slice modes are valid for which slices
139pub trait ValidSliceInputMode<I: SliceId>: Sealed + ValidSliceMode<I> {}
140
141/// Mode for slice
142pub trait SliceMode: Sealed + Sized {
143    /// Corresponding [`DynSliceMode`]
144    const DYN: DynSliceMode;
145}
146
147impl Sealed for FreeRunning {}
148impl SliceMode for FreeRunning {
149    const DYN: DynSliceMode = DynSliceMode::FreeRunning;
150}
151impl Sealed for InputHighRunning {}
152impl SliceMode for InputHighRunning {
153    const DYN: DynSliceMode = DynSliceMode::InputHighRunning;
154}
155impl Sealed for CountRisingEdge {}
156impl SliceMode for CountRisingEdge {
157    const DYN: DynSliceMode = DynSliceMode::CountRisingEdge;
158}
159impl Sealed for CountFallingEdge {}
160impl SliceMode for CountFallingEdge {
161    const DYN: DynSliceMode = DynSliceMode::CountFallingEdge;
162}
163
164impl<I: SliceId> ValidSliceMode<I> for FreeRunning {}
165impl<I: SliceId> ValidSliceMode<I> for InputHighRunning {}
166impl<I: SliceId> ValidSliceMode<I> for CountRisingEdge {}
167impl<I: SliceId> ValidSliceMode<I> for CountFallingEdge {}
168impl<I: SliceId> ValidSliceInputMode<I> for InputHighRunning {}
169impl<I: SliceId> ValidSliceInputMode<I> for CountRisingEdge {}
170impl<I: SliceId> ValidSliceInputMode<I> for CountFallingEdge {}
171
172//==============================================================================
173//  Slice IDs
174//==============================================================================
175
176/// Type-level `enum` for slice IDs
177pub trait SliceId: Sealed {
178    /// Corresponding [`DynSliceId`]
179    const DYN: DynSliceId;
180    /// [`SliceMode`] at reset
181    type Reset;
182
183    /// Get DREQ number of PWM wrap.
184    const WRAP_DREQ: u8 = TREQ_SEL_A::PWM_WRAP0 as u8 + Self::DYN.num;
185}
186
187macro_rules! slice_id {
188    ($Id:ident, $NUM:literal, $reset : ident) => {
189        $crate::paste::paste! {
190            #[doc = "Slice ID representing slice " $NUM]
191            pub enum $Id {}
192            impl Sealed for $Id {}
193            impl SliceId for $Id {
194                type Reset = $reset;
195                const DYN: DynSliceId = DynSliceId { num: $NUM };
196            }
197        }
198    };
199}
200
201//==============================================================================
202//  AnySlice
203//==============================================================================
204
205/// Type class for [`Slice`] types
206///
207/// This trait uses the [`AnyKind`] trait pattern to create a [type class] for
208/// [`Slice`] types. See the `AnyKind` documentation for more details on the
209/// pattern.
210///
211/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
212/// [type class]: crate::typelevel#type-classes
213pub trait AnySlice
214where
215    Self: Sealed,
216    Self: Is<Type = SpecificSlice<Self>>,
217    <Self as AnySlice>::Mode: ValidSliceMode<<Self as AnySlice>::Id>,
218{
219    /// [`SliceId`] of the corresponding [`Slice`]
220    type Id: SliceId;
221    /// [`SliceMode`] of the corresponding [`Slice`]
222    type Mode: SliceMode;
223}
224
225impl<S, M> Sealed for Slice<S, M>
226where
227    S: SliceId,
228    M: ValidSliceMode<S>,
229{
230}
231
232impl<S, M> AnySlice for Slice<S, M>
233where
234    S: SliceId,
235    M: ValidSliceMode<S>,
236{
237    type Id = S;
238    type Mode = M;
239}
240
241/// Type alias to recover the specific [`Slice`] type from an implementation of
242/// [`AnySlice`]
243///
244/// See the [`AnyKind`] documentation for more details on the pattern.
245///
246/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
247type SpecificSlice<S> = Slice<<S as AnySlice>::Id, <S as AnySlice>::Mode>;
248
249//==============================================================================
250//  Registers
251//==============================================================================
252
253/// Provide a safe register interface for [`Slice`]s
254///
255/// This `struct` takes ownership of a [`SliceId`] and provides an API to
256/// access the corresponding registers.
257struct Registers<I: SliceId> {
258    id: PhantomData<I>,
259}
260
261// [`Registers`] takes ownership of the [`SliceId`], and [`Slice`] guarantees that
262// each slice is a singleton, so this implementation is safe.
263unsafe impl<I: SliceId> RegisterInterface for Registers<I> {
264    #[inline]
265    fn id(&self) -> DynSliceId {
266        I::DYN
267    }
268}
269
270impl<I: SliceId> Registers<I> {
271    /// Create a new instance of [`Registers`]
272    ///
273    /// # Safety
274    ///
275    /// Users must never create two simultaneous instances of this `struct` with
276    /// the same [`SliceId`]
277    #[inline]
278    unsafe fn new() -> Self {
279        Registers { id: PhantomData }
280    }
281
282    /// Provide a type-level equivalent for the
283    /// [`RegisterInterface::change_mode`] method.
284    #[inline]
285    fn change_mode<M: ValidSliceMode<I>>(&mut self) {
286        RegisterInterface::do_change_mode(self, M::DYN);
287    }
288}
289
290/// Pwm slice
291pub struct Slice<I, M>
292where
293    I: SliceId,
294    M: ValidSliceMode<I>,
295{
296    regs: Registers<I>,
297    mode: PhantomData<M>,
298    /// Channel A (always output)
299    pub channel_a: Channel<Self, A>,
300    /// Channel B (input or output)
301    pub channel_b: Channel<Self, B>,
302}
303
304impl<I, M> Slice<I, M>
305where
306    I: SliceId,
307    M: ValidSliceMode<I>,
308{
309    /// Create a new [`Slice`]
310    ///
311    /// # Safety
312    ///
313    /// Each [`Slice`] must be a singleton. For a given [`SliceId`], there must be
314    /// at most one corresponding [`Slice`] in existence at any given time.
315    /// Violating this requirement is `unsafe`.
316    #[inline]
317    pub(crate) unsafe fn new() -> Slice<I, M> {
318        Slice {
319            regs: Registers::new(),
320            mode: PhantomData,
321            channel_a: Channel::new(0),
322            channel_b: Channel::new(0),
323        }
324    }
325
326    /// Convert the slice to the requested [`SliceMode`]
327    #[inline]
328    pub fn into_mode<N: ValidSliceMode<I>>(mut self) -> Slice<I, N> {
329        if N::DYN != M::DYN {
330            self.regs.change_mode::<N>();
331        }
332        // Safe because we drop the existing slice
333        unsafe { Slice::new() }
334    }
335
336    /// Set a default config for the slice
337    pub fn default_config(&mut self) {
338        self.regs.write_ph_correct(false);
339        self.regs.write_div_int(1); // No divisor
340        self.regs.write_div_frac(0); // No divisor
341        self.regs.write_inv_a(false); //Don't invert the channel
342        self.regs.write_inv_b(false); //Don't invert the channel
343        self.regs.write_top(0xfffe); // Wrap at 0xfffe, so cc = 0xffff can indicate 100% duty cycle
344        self.regs.write_ctr(0x0000); //Reset the counter
345        self.regs.write_cc_a(0); //Default duty cycle of 0%
346        self.regs.write_cc_b(0); //Default duty cycle of 0%
347    }
348
349    /// Advance the phase with one count
350    ///
351    /// Counter must be running at less than full speed (div_int + div_frac / 16 > 1)
352    #[inline]
353    pub fn advance_phase(&mut self) {
354        self.regs.advance_phase()
355    }
356
357    /// Retard the phase with one count
358    ///
359    /// Counter must be running at less than full speed (div_int + div_frac / 16 > 1)
360    #[inline]
361    pub fn retard_phase(&mut self) {
362        self.regs.retard_phase()
363    }
364
365    /// Enable phase correct mode
366    #[inline]
367    pub fn set_ph_correct(&mut self) {
368        self.regs.write_ph_correct(true)
369    }
370
371    /// Disables phase correct mode
372    #[inline]
373    pub fn clr_ph_correct(&mut self) {
374        self.regs.write_ph_correct(false)
375    }
376
377    /// Enable slice
378    #[inline]
379    pub fn enable(&mut self) {
380        self.regs.write_enable(true);
381    }
382
383    /// Disable slice
384    #[inline]
385    pub fn disable(&mut self) {
386        self.regs.write_enable(false)
387    }
388
389    /// Sets the integer part of the clock divider
390    #[inline]
391    pub fn set_div_int(&mut self, value: u8) {
392        self.regs.write_div_int(value)
393    }
394
395    /// Sets the fractional part of the clock divider
396    #[inline]
397    pub fn set_div_frac(&mut self, value: u8) {
398        self.regs.write_div_frac(value)
399    }
400
401    /// Get the counter register value
402    #[inline]
403    pub fn get_counter(&self) -> u16 {
404        self.regs.read_ctr()
405    }
406
407    /// Set the counter register value
408    #[inline]
409    pub fn set_counter(&mut self, value: u16) {
410        self.regs.write_ctr(value)
411    }
412
413    /// Get the top register value
414    #[inline]
415    pub fn get_top(&self) -> u16 {
416        self.regs.read_top()
417    }
418
419    /// Sets the top register value
420    ///
421    /// Don't set this to 0xffff if you need true 100% duty cycle:
422    ///
423    /// The CC register, which is used to configure the duty cycle,
424    /// must be set to TOP + 1 for 100% duty cycle, but also is a
425    /// 16 bit register.
426    ///
427    /// In case you do set TOP to 0xffff, [`SetDutyCycle::set_duty_cycle`]
428    /// will slightly violate the trait's documentation, as
429    /// `SetDutyCycle::set_duty_cycle_fully_on` and other calls that
430    /// should lead to 100% duty cycle will only reach a duty cycle of
431    /// about 99.998%.
432    #[inline]
433    pub fn set_top(&mut self, value: u16) {
434        self.regs.write_top(value)
435    }
436
437    /// Create the interrupt bitmask corresponding to this slice
438    #[inline]
439    fn bitmask(&self) -> u32 {
440        1 << I::DYN.num
441    }
442
443    /// Enable the PWM_IRQ_WRAP interrupt when this slice overflows.
444    #[inline]
445    pub fn enable_interrupt(&mut self) {
446        unsafe {
447            let pwm = &(*pac::PWM::ptr());
448            let reg = pwm.inte().as_ptr();
449            write_bitmask_set(reg, self.bitmask());
450        }
451    }
452
453    /// Disable the PWM_IRQ_WRAP interrupt for this slice.
454    #[inline]
455    pub fn disable_interrupt(&mut self) {
456        unsafe {
457            let pwm = &(*pac::PWM::ptr());
458            let reg = pwm.inte().as_ptr();
459            write_bitmask_clear(reg, self.bitmask());
460        };
461    }
462
463    /// Did this slice trigger an overflow interrupt?
464    ///
465    /// This reports the raw interrupt flag, without considering masking or
466    /// forcing bits. It may return true even if the interrupt is disabled
467    /// or false even if the interrupt is forced.
468    #[inline]
469    pub fn has_overflown(&self) -> bool {
470        let mask = self.bitmask();
471        unsafe { (*pac::PWM::ptr()).intr().read().bits() & mask == mask }
472    }
473
474    /// Mark the interrupt handled for this slice.
475    #[inline]
476    pub fn clear_interrupt(&mut self) {
477        unsafe { (*pac::PWM::ptr()).intr().write(|w| w.bits(self.bitmask())) };
478    }
479
480    /// Force the interrupt. This bit is not cleared by hardware and must be manually cleared to
481    /// stop the interrupt from continuing to be asserted.
482    #[inline]
483    pub fn force_interrupt(&mut self) {
484        unsafe {
485            let pwm = &(*pac::PWM::ptr());
486            let reg = pwm.intf().as_ptr();
487            write_bitmask_set(reg, self.bitmask());
488        }
489    }
490
491    /// Clear force interrupt. This bit is not cleared by hardware and must be manually cleared to
492    /// stop the interrupt from continuing to be asserted.
493    #[inline]
494    pub fn clear_force_interrupt(&mut self) {
495        unsafe {
496            let pwm = &(*pac::PWM::ptr());
497            let reg = pwm.intf().as_ptr();
498            write_bitmask_clear(reg, self.bitmask());
499        }
500    }
501}
502
503macro_rules! pwm {
504    ($PWMX:ident, [
505        $($SXi:ident: ($slice:literal, [$($pin_a:ident, $pin_b:ident),*], $i:expr)),+
506    ]) => {
507        $(
508            slice_id!($SXi, $slice, FreeRunning);
509
510            $(
511                impl ValidPwmOutputPin<$SXi, A> for $pin_a {}
512                impl ValidPwmOutputPin<$SXi, B> for $pin_b {}
513                impl ValidPwmInputPin<$SXi> for $pin_b {}
514            )*
515        )+
516
517        $crate::paste::paste!{
518
519            /// Collection of all the individual [`Slices`]s
520            pub struct Slices {
521                _pwm: $PWMX,
522                $(
523                    #[doc = "Slice " $SXi]
524                    pub [<$SXi:lower>] : Slice<$SXi,<$SXi as SliceId>::Reset>,
525                )+
526            }
527
528            impl Slices {
529                /// Take ownership of the PAC peripheral and split it into discrete [`Slice`]s
530                pub fn new(pwm: $PWMX, reset : &mut crate::pac::RESETS) -> Self {
531                    pwm.reset_bring_up(reset);
532                    unsafe {
533                        Self {
534                            _pwm: pwm,
535                            $(
536                                [<$SXi:lower>]: Slice::new(),
537                            )+
538                        }
539                    }
540                }
541            }
542        }
543    }
544}
545
546pwm! {
547    PWM, [
548        Pwm0: (0, [Gpio0, Gpio1, Gpio16, Gpio17], 0),
549        Pwm1: (1, [Gpio2, Gpio3, Gpio18, Gpio19], 1),
550        Pwm2: (2, [Gpio4, Gpio5, Gpio20, Gpio21], 2),
551        Pwm3: (3, [Gpio6, Gpio7, Gpio22, Gpio23], 3),
552        Pwm4: (4, [Gpio8, Gpio9, Gpio24, Gpio25], 4),
553        Pwm5: (5, [Gpio10, Gpio11, Gpio26, Gpio27], 5),
554        Pwm6: (6, [Gpio12, Gpio13, Gpio28, Gpio29], 6),
555        Pwm7: (7, [Gpio14, Gpio15], 7)
556    ]
557}
558
559/// Marker trait for valid input pins (Channel B only)
560pub trait ValidPwmInputPin<S: SliceId>: ValidFunction<FunctionPwm> + Sealed {}
561/// Marker trait for valid output pins
562pub trait ValidPwmOutputPin<S: SliceId, C: ChannelId>: ValidFunction<FunctionPwm> + Sealed {}
563
564impl Slices {
565    /// Free the pwm registers from the pwm hal struct while consuming it.
566    pub fn free(self) -> PWM {
567        self._pwm
568    }
569
570    /// Enable multiple slices at the same time to make their counters sync up.
571    ///
572    /// You still need to call `slice` to get an actual slice
573    pub fn enable_simultaneous(&mut self, bits: u8) {
574        // Enable multiple slices at the same time
575        unsafe {
576            let reg = self._pwm.en().as_ptr();
577            write_bitmask_set(reg, bits as u32);
578        }
579    }
580
581    // /// Get pwm slice based on gpio pin
582    // pub fn borrow_mut_from_pin<
583    //     S: SliceId,
584    //     C: ChannelId,
585    //     G: PinId + BankPinId + ValidPwmOutputPin<S, C>,
586    //     PM: PinMode + ValidPinMode<G>,
587    //     SM:  ValidSliceMode<S>,
588    // >(&mut self, _: &Pin<G, PM>) -> &mut Slice<S, SM>{
589    //     match S::DYN {
590    //         DynSliceId{num} if num == 0 => &mut self.pwm0,
591    //         DynSliceId{num} if num == 1 => &mut self.pwm1,
592    //         DynSliceId{num} if num == 2 => &mut self.pwm2,
593    //         DynSliceId{num} if num == 3 => &mut self.pwm3,
594    //         DynSliceId{num} if num == 4 => &mut self.pwm4,
595    //         DynSliceId{num} if num == 5 => &mut self.pwm5,
596    //         DynSliceId{num} if num == 6 => &mut self.pwm6,
597    //         DynSliceId{num} if num == 7 => &mut self.pwm7,
598    //         _ => unreachable!()
599    //     }
600    // }
601}
602
603/// A Channel from the Pwm subsystem.
604///
605/// Its attached to one of the eight slices and can be an A or B side channel
606pub struct Channel<S: AnySlice, C: ChannelId> {
607    regs: Registers<S::Id>,
608    slice_mode: PhantomData<S::Mode>,
609    channel_id: PhantomData<C>,
610    duty_cycle: u16,
611    enabled: bool,
612}
613
614impl<S: AnySlice, C: ChannelId> Channel<S, C> {
615    pub(super) unsafe fn new(duty_cycle: u16) -> Self {
616        Channel {
617            regs: Registers::new(),
618            slice_mode: PhantomData,
619            channel_id: PhantomData,
620            duty_cycle, // stores the duty cycle while the channel is disabled
621            enabled: true,
622        }
623    }
624}
625
626impl<S: AnySlice, C: ChannelId> Sealed for Channel<S, C> {}
627
628impl<S: AnySlice> embedded_hal_0_2::PwmPin for Channel<S, A> {
629    type Duty = u16;
630
631    fn disable(&mut self) {
632        self.set_enabled(false);
633    }
634
635    fn enable(&mut self) {
636        self.set_enabled(true);
637    }
638
639    fn get_duty(&self) -> Self::Duty {
640        if self.enabled {
641            self.regs.read_cc_a()
642        } else {
643            self.duty_cycle
644        }
645    }
646
647    fn get_max_duty(&self) -> Self::Duty {
648        SetDutyCycle::max_duty_cycle(self)
649    }
650
651    fn set_duty(&mut self, duty: Self::Duty) {
652        let _ = SetDutyCycle::set_duty_cycle(self, duty);
653    }
654}
655
656impl<S: AnySlice> embedded_hal_0_2::PwmPin for Channel<S, B> {
657    type Duty = u16;
658
659    fn disable(&mut self) {
660        self.set_enabled(false);
661    }
662
663    fn enable(&mut self) {
664        self.set_enabled(true);
665    }
666
667    fn get_duty(&self) -> Self::Duty {
668        if self.enabled {
669            self.regs.read_cc_b()
670        } else {
671            self.duty_cycle
672        }
673    }
674
675    fn get_max_duty(&self) -> Self::Duty {
676        SetDutyCycle::max_duty_cycle(self)
677    }
678
679    fn set_duty(&mut self, duty: Self::Duty) {
680        let _ = SetDutyCycle::set_duty_cycle(self, duty);
681    }
682}
683
684impl<S: AnySlice> ErrorType for Channel<S, A> {
685    type Error = Infallible;
686}
687
688impl<S: AnySlice> SetDutyCycle for Channel<S, A> {
689    fn max_duty_cycle(&self) -> u16 {
690        self.regs.read_top().saturating_add(1)
691    }
692
693    fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
694        self.duty_cycle = duty;
695        if self.enabled {
696            self.regs.write_cc_a(duty)
697        }
698        Ok(())
699    }
700}
701
702impl<S: AnySlice> ErrorType for Channel<S, B> {
703    type Error = Infallible;
704}
705
706impl<S: AnySlice> SetDutyCycle for Channel<S, B> {
707    fn max_duty_cycle(&self) -> u16 {
708        self.regs.read_top().saturating_add(1)
709    }
710
711    fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
712        self.duty_cycle = duty;
713        if self.enabled {
714            self.regs.write_cc_b(duty)
715        }
716        Ok(())
717    }
718}
719
720impl<S: AnySlice> Channel<S, A> {
721    /// Enable or disable the PWM channel
722    pub fn set_enabled(&mut self, enable: bool) {
723        if enable && !self.enabled {
724            // Restore the duty cycle.
725            self.regs.write_cc_a(self.duty_cycle);
726            self.enabled = true;
727        } else if !enable && self.enabled {
728            // We can't disable it without disturbing the other channel so this
729            // just sets the duty cycle to zero.
730            self.duty_cycle = self.regs.read_cc_a();
731            self.regs.write_cc_a(0);
732            self.enabled = false;
733        }
734    }
735
736    /// Capture a gpio pin and use it as pwm output for channel A
737    pub fn output_to<P: AnyPin>(&mut self, pin: P) -> Pin<P::Id, FunctionPwm, P::Pull>
738    where
739        P::Id: ValidPwmOutputPin<S::Id, A>,
740    {
741        pin.into().into_function()
742    }
743
744    /// Invert channel output
745    #[inline]
746    pub fn set_inverted(&mut self) {
747        self.regs.write_inv_a(true)
748    }
749
750    /// Stop inverting channel output
751    #[inline]
752    pub fn clr_inverted(&mut self) {
753        self.regs.write_inv_a(false)
754    }
755}
756
757impl<S: AnySlice> Channel<S, B> {
758    /// Enable or disable the PWM channel
759    pub fn set_enabled(&mut self, enable: bool) {
760        if enable && !self.enabled {
761            // Restore the duty cycle.
762            self.regs.write_cc_b(self.duty_cycle);
763            self.enabled = true;
764        } else if !enable && self.enabled {
765            // We can't disable it without disturbing the other channel so this
766            // just sets the duty cycle to zero.
767            self.duty_cycle = self.regs.read_cc_b();
768            self.regs.write_cc_b(0);
769            self.enabled = false;
770        }
771    }
772
773    /// Capture a gpio pin and use it as pwm output for channel B
774    pub fn output_to<P: AnyPin>(&mut self, pin: P) -> Pin<P::Id, FunctionPwm, P::Pull>
775    where
776        P::Id: ValidPwmOutputPin<S::Id, B>,
777    {
778        pin.into().into_function()
779    }
780
781    /// Invert channel output
782    #[inline]
783    pub fn set_inverted(&mut self) {
784        self.regs.write_inv_b(true)
785    }
786
787    /// Stop inverting channel output
788    #[inline]
789    pub fn clr_inverted(&mut self) {
790        self.regs.write_inv_b(false)
791    }
792}
793
794impl<S: AnySlice> Channel<S, B>
795where
796    S::Mode: ValidSliceInputMode<S::Id>,
797{
798    /// Capture a gpio pin and use it as pwm input for channel B
799    pub fn input_from<P: AnyPin>(&mut self, pin: P) -> Pin<P::Id, FunctionPwm, P::Pull>
800    where
801        P::Id: ValidPwmInputPin<S::Id>,
802    {
803        pin.into().into_function()
804    }
805}
806
807impl<S: SliceId, M: ValidSliceMode<S>> Slice<S, M> {
808    /// Capture a gpio pin and use it as pwm output
809    pub fn output_to<P: AnyPin, C: ChannelId>(&mut self, pin: P) -> Pin<P::Id, FunctionPwm, P::Pull>
810    where
811        P::Id: ValidPwmOutputPin<S, C>,
812    {
813        pin.into().into_function()
814    }
815}
816
817impl<S: SliceId, M: ValidSliceInputMode<S>> Slice<S, M> {
818    /// Capture a gpio pin and use it as pwm input for channel B
819    pub fn input_from<P: AnyPin>(&mut self, pin: P) -> Pin<P::Id, FunctionPwm, P::Pull>
820    where
821        P::Id: ValidPwmInputPin<S>,
822    {
823        pin.into().into_function()
824    }
825}
826
827/// Type representing DMA access to PWM cc register.
828///
829/// Both channels are accessed together, because of narrow write replication.
830///
831/// ```no_run
832/// use cortex_m::singleton;
833/// use rp2040_hal::dma::{double_buffer, DMAExt};
834/// use rp2040_hal::pwm::{CcFormat, SliceDmaWrite, Slices};
835///
836///
837/// let mut pac = rp2040_pac::Peripherals::take().unwrap();
838///
839/// // Init PWMs
840/// let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
841///
842/// // Configure PWM4
843/// let mut pwm = pwm_slices.pwm4;
844/// pwm.enable();
845///
846/// let buf = singleton!(: [CcFormat; 4] = [CcFormat{a: 0x1000, b: 0x9000}; 4]).unwrap();
847/// let buf2 = singleton!(: [CcFormat; 4] = [CcFormat{a: 0xf000, b: 0x5000}; 4]).unwrap();
848///
849/// let dma = pac.DMA.split(&mut pac.RESETS);
850///
851/// let dma_pwm = SliceDmaWrite::from(pwm);
852///
853/// let dma_conf = double_buffer::Config::new((dma.ch0, dma.ch1), buf, dma_pwm.cc);
854/// ```
855pub struct SliceDmaWriteCc<S: SliceId, M: ValidSliceMode<S>> {
856    slice: PhantomData<S>,
857    mode: PhantomData<M>,
858}
859
860/// Type representing DMA access to PWM top register.
861///
862/// ```no_run
863/// use cortex_m::{prelude::*, singleton};
864/// use rp2040_hal::dma::{double_buffer, DMAExt};
865/// use rp2040_hal::pwm::{SliceDmaWrite, Slices, TopFormat};
866///
867///
868/// let mut pac = rp2040_pac::Peripherals::take().unwrap();
869///
870/// // Init PWMs
871/// let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
872///
873/// // Configure PWM4
874/// let mut pwm = pwm_slices.pwm4;
875/// pwm.enable();
876///
877/// // Just set to something mesurable.
878/// pwm.channel_a.set_duty(0x1000);
879/// pwm.channel_b.set_duty(0x1000);
880///
881/// let buf = singleton!(: [TopFormat; 4] = [TopFormat::new(0x7fff); 4]).unwrap();
882/// let buf2 = singleton!(: [TopFormat; 4] = [TopFormat::new(0xfffe); 4]).unwrap();
883///
884/// let dma = pac.DMA.split(&mut pac.RESETS);
885///
886/// // Reserve PWM slice for dma.
887/// let dma_pwm = SliceDmaWrite::from(pwm);
888///
889/// let dma_conf = double_buffer::Config::new((dma.ch0, dma.ch1), buf, dma_pwm.top);
890/// ```
891pub struct SliceDmaWriteTop<S: SliceId, M: ValidSliceMode<S>> {
892    slice: PhantomData<S>,
893    mode: PhantomData<M>,
894}
895
896/// PWM slice while used for DMA writes.
897/// ```no_run
898/// use rp2040_hal::{prelude::*, pwm::{SliceDmaWrite, Slices}};
899///
900///
901/// let mut pac = rp2040_pac::Peripherals::take().unwrap();
902///
903/// // Init PWMs
904/// let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
905///
906/// // Configure PWM4
907/// let mut pwm = pwm_slices.pwm4;
908/// pwm.enable();
909///
910/// // Use for DMA usage
911/// let dma_pwm = SliceDmaWrite::from(pwm);
912/// ```
913///
914pub struct SliceDmaWrite<S: SliceId, M: ValidSliceMode<S>> {
915    /// Part for top writes.
916    pub top: SliceDmaWriteTop<S, M>,
917
918    /// Part for cc writes.
919    pub cc: SliceDmaWriteCc<S, M>,
920    slice: Slice<S, M>,
921}
922
923impl<S: SliceId, M: ValidSliceMode<S>> From<Slice<S, M>> for SliceDmaWrite<S, M> {
924    fn from(value: Slice<S, M>) -> Self {
925        Self {
926            slice: value,
927            top: SliceDmaWriteTop {
928                slice: PhantomData,
929                mode: PhantomData,
930            },
931            cc: SliceDmaWriteCc {
932                slice: PhantomData,
933                mode: PhantomData,
934            },
935        }
936    }
937}
938
939impl<S: SliceId, M: ValidSliceMode<S>> From<SliceDmaWrite<S, M>> for Slice<S, M> {
940    fn from(value: SliceDmaWrite<S, M>) -> Self {
941        value.slice
942    }
943}
944
945/// Format for DMA transfers to PWM CC register.
946#[derive(Clone, Copy, Eq, PartialEq)]
947#[repr(C)]
948#[repr(align(4))]
949pub struct CcFormat {
950    /// CC register part for channel a.
951    pub a: u16,
952    /// CC register part for channel b.
953    pub b: u16,
954}
955
956unsafe impl Word for CcFormat {}
957
958/// Format for DMA transfers to PWM TOP register.
959///
960/// It is forbidden to use it as DMA write destination,
961/// it is safe but it might not be compatible with a future use of reserved register fields.
962#[derive(Clone, Copy, Eq)]
963#[repr(C)]
964#[repr(align(4))]
965pub struct TopFormat {
966    /// Valid register part.
967    pub top: u16,
968    /// Reserved part.
969    /// Should always be zero
970    reserved: u16,
971}
972
973impl PartialEq<TopFormat> for TopFormat {
974    fn eq(&self, other: &TopFormat) -> bool {
975        self.top == other.top
976    }
977}
978
979impl TopFormat {
980    /// Create a valid value.
981    pub fn new(top: u16) -> Self {
982        TopFormat { top, reserved: 0 }
983    }
984}
985
986impl Default for TopFormat {
987    fn default() -> Self {
988        Self::new(u16::MAX)
989    }
990}
991
992unsafe impl Word for TopFormat {}
993
994/// Safety: tx_address_count points to a register which is always a valid
995/// write target.
996unsafe impl<S: SliceId, M: ValidSliceMode<S>> WriteTarget for SliceDmaWriteCc<S, M> {
997    type TransmittedWord = CcFormat;
998
999    fn tx_treq() -> Option<u8> {
1000        Some(S::WRAP_DREQ)
1001    }
1002
1003    fn tx_address_count(&mut self) -> (u32, u32) {
1004        let regs = Registers {
1005            id: PhantomData::<S> {},
1006        };
1007        (regs.ch().cc().as_ptr() as u32, u32::MAX)
1008    }
1009
1010    fn tx_increment(&self) -> bool {
1011        false
1012    }
1013}
1014
1015/// Safety: tx_address_count points to a register which is always a valid
1016/// write target.
1017unsafe impl<S: SliceId, M: ValidSliceMode<S>> WriteTarget for SliceDmaWriteTop<S, M> {
1018    type TransmittedWord = TopFormat;
1019
1020    fn tx_treq() -> Option<u8> {
1021        Some(S::WRAP_DREQ)
1022    }
1023
1024    fn tx_address_count(&mut self) -> (u32, u32) {
1025        let regs = Registers {
1026            id: PhantomData::<S> {},
1027        };
1028        (regs.ch().top().as_ptr() as u32, u32::MAX)
1029    }
1030
1031    fn tx_increment(&self) -> bool {
1032        false
1033    }
1034}
1035
1036impl<S: SliceId, M: ValidSliceMode<S>> EndlessWriteTarget for SliceDmaWriteCc<S, M> {}
1037impl<S: SliceId, M: ValidSliceMode<S>> EndlessWriteTarget for SliceDmaWriteTop<S, M> {}