Skip to main content

imxrt_hal/common/
flexpwm.rs

1//! Pulse width modulation.
2//!
3//! Each PWM peripheral, [`Pwm`], interacts with four submodules.
4//! Each submodule acts as a timer with multiple compare registers, called
5//! [`ValueRegister`]s. A comparison event
6//!
7//! - is signaled through a [`Status`] flag (see [`Pwm::status`]).
8//! - can generate an interrupt (see [`Pwm::interrupts`]).
9//! - sets a PWM output high or low, depending on the turn on / off values.
10//!
11//! The PWM driver does not implement any of the embedded-hal PWM traits. You should
12//! use these APIs to create your own PWM implementation that satisfies your driver.
13//!
14//! # Example
15//!
16//! The PWM submodule counts over the range of `i16` values. The counter runs at
17//! the IPG clock frequency. The PWM outputs produce independent, phase-shifted
18//! outputs.
19//!
20//! ```no_run
21//! use imxrt_hal as hal;
22//! use imxrt_ral as ral;
23//!
24//! use hal::flexpwm::{self, Pwm, SM::SM2, Channel::{A, B}};
25//!
26//! # || -> Option<()> {
27//! let pwm2 = unsafe { ral::pwm::PWM2::instance() };
28//! let mut pwm = Pwm::new::<2>(pwm2);
29//!
30//! // Keep running in wait, debug modes.
31//! pwm.set_debug_enable(SM2, true);
32//! pwm.set_wait_enable(SM2, true);
33//! // Run on the IPG clock.
34//! pwm.set_clock_select(SM2, flexpwm::ClockSelect::Ipg);
35//! // Divide the IPG clock by 1.
36//! pwm.set_prescaler(SM2, flexpwm::Prescaler::Prescaler1);
37//! // Allow PWM outputs to operate independently.
38//! pwm.set_pair_operation(SM2, flexpwm::PairOperation::Independent);
39//!
40//! // Reload every time the full reload value register compares.
41//! pwm.set_load_mode(SM2, flexpwm::LoadMode::reload_full());
42//! pwm.set_load_frequency(SM2, 1);
43//! // Count over the full range of i16 values.
44//! pwm.set_initial_count(SM2, i16::MIN);
45//! pwm.set_value(SM2, flexpwm::FULL_RELOAD_VALUE_REGISTER, i16::MAX);
46//!
47//! let mut gpio_b0_10 = // Handle to the pad, channel A
48//!     # unsafe { imxrt_iomuxc::imxrt1060::gpio_b0::GPIO_B0_10::new() };
49//! let mut gpio_b0_11 = // Handle to the pad, channel B
50//!     # unsafe { imxrt_iomuxc::imxrt1060::gpio_b0::GPIO_B0_11::new() };
51//! imxrt_iomuxc::flexpwm::prepare(&mut gpio_b0_10);
52//! imxrt_iomuxc::flexpwm::prepare(&mut gpio_b0_11);
53//!
54//! // Set the turn on / off count values.
55//! pwm.set_turn_on(SM2, A, i16::MIN / 2);
56//! pwm.set_turn_off(SM2, A, i16::MAX / 2);
57//! // Output B generates the same duty cycle as A
58//! // with a lagging phase shift of 5000 counts.
59//! pwm.set_turn_on(SM2, B, pwm.turn_on(SM2, A) + 5000);
60//! pwm.set_turn_off(SM2, B, pwm.turn_off(SM2, A) + 5000);
61//!
62//! // Enable the PWM outputs.
63//! pwm.set_output_enable(SM2.mask(), A);
64//! pwm.set_output_enable(SM2.mask(), B);
65//! // Load the values into the PWM registers.
66//! pwm.set_load_ok(SM2.mask());
67//! // Start running.
68//! pwm.set_run(SM2.mask());
69//! # Some(())}();
70//! ```
71
72use crate::ral::pwm;
73
74/// Any of the PWM peripheral instances.
75type AnyPwmInstance = crate::AnyInstance<pwm::RegisterBlock>;
76
77/// A PWM peripheral.
78///
79/// The PWM peripheral provides access to peripheral-wide registers
80/// and methods to control submodules and pin outputs.
81pub struct Pwm {
82    pwm: AnyPwmInstance,
83}
84
85bitflags::bitflags! {
86    /// Bitmask for representing submodules.
87    ///
88    /// `Mask` is used throughout the PWM API. The interpretation of the
89    /// bits depends on the function.
90    ///
91    /// If you have an [`SM`], use [`SM::mask()`] to easily obtain its bitmask.
92    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
93    pub struct Mask : u8 {
94        /// Submodule 0.
95        const SM0 = 1 << 0;
96        /// Submodule 1.
97        const SM1 = 1 << 1;
98        /// Submodule 2.
99        const SM2 = 1 << 2;
100        /// Submodule 3.
101        const SM3 = 1 << 3;
102    }
103}
104
105impl Pwm {
106    /// Create a new PWM driver from a peripheral instance.
107    pub fn new<const N: u8>(pwm: pwm::Instance<N>) -> Self {
108        self::new(crate::into_any(pwm))
109    }
110
111    // TODO: MCTRL should be byte accessible (unlike other PWM modules, which are explicitly
112    // documented as "not bye accessible"). If we could load and store directly from the low
113    // byte -- where LDOK and CLDOK reside -- we might be able to drop the &mut receiver on
114    // the LDOK methods. This requires us to re-define the MCTRL register into two halves.
115    // Ideally, this happens in the RAL, but it could also happen in our custom RAL module.
116    // Any solution needs to account for the differences between the 1010 and all other chips.
117
118    /// Read the `LDOK` bits.
119    ///
120    /// Note that the hardware will deassert `LDOK` after the values are loaded.
121    pub fn load_ok(&self) -> Mask {
122        let ldok = crate::ral::read_reg!(crate::ral::pwm, self.pwm, MCTRL, LDOK);
123        Mask::from_bits_truncate(ldok as u8)
124    }
125    /// Set `LDOK` for zero or more submodules.
126    ///
127    /// A *high bit* indicates which `LDOK` bit(s) will be *set*.
128    pub fn set_load_ok(&mut self, mask: Mask) {
129        crate::ral::modify_reg!(crate::ral::pwm, self.pwm, MCTRL, LDOK: mask.bits() as u16);
130    }
131    /// Clear `LDOK` for zero or more submodules.
132    ///
133    /// A *high bit* indicates which `LDOK` bit(s) will be *cleared*.
134    pub fn clear_load_ok(&mut self, mask: Mask) {
135        crate::ral::modify_reg!(crate::ral::pwm, self.pwm, MCTRL, CLDOK: mask.bits() as u16);
136    }
137    /// Read the `RUN` bit(s).
138    pub fn run(&self) -> Mask {
139        let run = crate::ral::read_reg!(crate::ral::pwm, self.pwm, MCTRL, RUN);
140        Mask::from_bits_truncate(run as u8)
141    }
142    /// Set or clear the `RUN` bit(s) for one or more submodules.
143    ///
144    /// This bitmask is written directly to the hardware. To perform a read-modify-write
145    /// operation on these bits, make sure to read the initial values with [`Pwm::run`].
146    pub fn set_run(&mut self, mask: Mask) {
147        crate::ral::modify_reg!(crate::ral::pwm, self.pwm, MCTRL, RUN: mask.bits() as u16);
148    }
149    /// Read a PWM channel's output enable bits.
150    pub fn output_enable(&self, channel: Channel) -> Mask {
151        let mask = match channel {
152            Channel::A => crate::ral::read_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMA_EN),
153            Channel::B => crate::ral::read_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMB_EN),
154        };
155        Mask::from_bits_truncate(mask as u8)
156    }
157    /// Set a PWM channel's output enable.
158    ///
159    /// A high bit indicates the channel is enabled. A low bit disables the channel.
160    pub fn set_output_enable(&mut self, mask: Mask, channel: Channel) {
161        let mask = mask.bits() as u16;
162        match channel {
163            Channel::A => crate::ral::modify_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMA_EN: mask),
164            Channel::B => crate::ral::modify_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMB_EN: mask),
165        }
166    }
167}
168
169/// Methods that operate on submodules.
170impl Pwm {
171    fn submodule(&self, sm: SM) -> &pwm::sm::RegisterBlock {
172        &self.pwm.SM[sm as usize]
173    }
174
175    /// Read the submodule's counter register.
176    pub fn sm_count(&self, sm: SM) -> i16 {
177        crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCNT) as _
178    }
179
180    /// Read a submodule's initial count register.
181    ///
182    /// This is the value loaded into the submodule counter
183    /// when a reload event happens. Note: this reads the
184    /// buffered value set with `set_initial_counter` when
185    /// the hardware is waiting to load the value.
186    pub fn initial_count(&self, sm: SM) -> i16 {
187        crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMINIT) as _
188    }
189
190    /// Set the submodule initial counter register.
191    ///
192    /// Note: this value is buffered. It is not reloaded
193    /// until the LDOK signal is set and the reload cycle
194    /// happens. You cannot write the value when LDOK is
195    /// set.
196    pub fn set_initial_count(&self, sm: SM, counter: i16) {
197        crate::ral::write_reg!(pwm::sm, self.submodule(sm), SMINIT, counter as _);
198    }
199
200    /// Returns submodule the load frequency.
201    ///
202    /// The load frequency describes how many PWM "opportuntities" it will take
203    /// before the hardware loads buffered register values into their registers.
204    /// This value is between 1 and 16.
205    ///
206    /// An "opportunity" is one of
207    ///
208    /// - a full cycle reload (VAL1 matches), if full reload is set.
209    /// - a half cycle reload (VAL0 matches), if half reload is set.
210    pub fn load_frequency(&self, sm: SM) -> u16 {
211        crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDFQ) + 1
212    }
213
214    /// Set the submodule load frequency.
215    ///
216    /// See [`load_frequency`](crate::flexpwm::Pwm::load_frequency) for a
217    /// description of load frequency. The implementation clamps the values
218    /// between 1 and 16.
219    pub fn set_load_frequency(&mut self, sm: SM, ldfq: u16) {
220        let ldfq = ldfq.clamp(1, 16) - 1;
221        crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDFQ: ldfq);
222    }
223
224    /// Returns the submodule prescaler value.
225    pub fn prescaler(&self, sm: SM) -> Prescaler {
226        let prescaler = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL, PRSC);
227
228        #[allow(clippy::assertions_on_constants)]
229        {
230            use pwm::sm::SMCTRL;
231            const _: () = assert!(SMCTRL::PRSC::mask >> SMCTRL::PRSC::offset == 7u16);
232            const _: () = assert!(Prescaler::Prescaler128 as u16 == 7u16);
233        }
234
235        // Safety: field is three bits wide. Prescaler represents all values in
236        // the enum. See the asserts above for tests.
237        unsafe { core::mem::transmute(prescaler) }
238    }
239
240    /// Set the PWM submodule clock prescaler.
241    pub fn set_prescaler(&mut self, sm: SM, prescaler: Prescaler) {
242        crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, PRSC: prescaler as u16)
243    }
244
245    /// Returns the pair operation setting.
246    pub fn pair_operation(&self, sm: SM) -> PairOperation {
247        let indep = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, INDEP);
248
249        #[allow(clippy::assertions_on_constants)]
250        {
251            use pwm::sm::SMCTRL2;
252            const _: () = assert!(SMCTRL2::INDEP::mask >> SMCTRL2::INDEP::offset == 1u16);
253        }
254
255        // Safety: field is one bit. Enum is two variants, representing all values
256        // in this one bit state.
257        unsafe { core::mem::transmute(indep) }
258    }
259
260    /// Set the pair operation setting.
261    pub fn set_pair_operation(&mut self, sm: SM, pair_operation: PairOperation) {
262        crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, INDEP: pair_operation as u16);
263    }
264
265    /// Returns `true` if debug enable is set.
266    ///
267    /// When set, the PWM continues to run when in debug mode. When clear, the
268    /// PWM stops in debug mode, and restarts when debug mode exits.
269    pub fn debug_enable(&self, sm: SM) -> bool {
270        crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, DBGEN == 1)
271    }
272
273    /// Set debug enable.
274    ///
275    /// See [`debug_enable`](Self::debug_enable) for more information on debug
276    /// enable.
277    pub fn set_debug_enable(&mut self, sm: SM, enable: bool) {
278        crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, DBGEN: enable as u16);
279    }
280
281    /// Returns `true` if wait enable is set.
282    ///
283    /// When set, the PWM continues to run when in wait mode. When clear, the PWM
284    /// stops in wait mode, and restarts when wait mode exits.
285    pub fn wait_enable(&self, sm: SM) -> bool {
286        crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, WAITEN == 1)
287    }
288
289    /// Set wait enable.
290    ///
291    /// See [`wait_enable`](Self::wait_enable) for more information on wait
292    /// enable.
293    pub fn set_wait_enable(&mut self, sm: SM, enable: bool) {
294        crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, WAITEN: enable as u16);
295    }
296
297    /// Returns the clock selection.
298    pub fn clock_select(&self, sm: SM) -> ClockSelect {
299        const IPG: u16 = ClockSelect::Ipg as u16;
300        const EXT: u16 = ClockSelect::External as u16;
301        const SM0: u16 = ClockSelect::Submodule0 as u16;
302
303        match crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, CLK_SEL) {
304            IPG => ClockSelect::Ipg,
305            EXT => ClockSelect::External,
306            SM0 => ClockSelect::Submodule0,
307            _ => unreachable!("Reserved value"),
308        }
309    }
310
311    /// Set the clock selection.
312    ///
313    /// Note that you cannot use submodule 0's clock as the submodule 0
314    /// source clock. Despite that caveat, this call does not check this
315    /// possible configuration.
316    ///
317    /// # Panics
318    ///
319    /// You cannot use submodule 0's clock for submodule 0. If the submodule 0 clock
320    /// is selected for submodule 0, this call panics.
321    pub fn set_clock_select(&mut self, sm: SM, clock_select: ClockSelect) {
322        assert!(SM::SM0 != sm || clock_select != ClockSelect::Submodule0);
323        crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, CLK_SEL: clock_select as u16);
324    }
325
326    /// Returns the load mode.
327    pub fn load_mode(&self, sm: SM) -> LoadMode {
328        let (immediate, full, half) =
329            crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDMOD, FULL, HALF);
330        if immediate != 0 {
331            LoadMode::Immediate
332        } else {
333            LoadMode::ReloadCycle {
334                full: full != 0,
335                half: half != 0,
336            }
337        }
338    }
339
340    /// Set the load mode.
341    ///
342    /// # Panics
343    ///
344    /// Panics if the load mode is reload cycle, yet neither `full` nor `half` is set.
345    /// Use the [`LoadMode`] helper methods to ensure one of these flags are set.
346    pub fn set_load_mode(&mut self, sm: SM, load_mode: LoadMode) {
347        match load_mode {
348            LoadMode::Immediate => {
349                crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDMOD: 1)
350            }
351            LoadMode::ReloadCycle { full, half } => {
352                assert!(
353                    full || half,
354                    "LoadMode::ReloadCycle must set at least full or half"
355                );
356                crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDMOD: 0, FULL: full as u16, HALF: half as u16)
357            }
358        }
359    }
360
361    /// Read the status flags.
362    pub fn status(&self, sm: SM) -> Status {
363        let sts = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMSTS);
364        Status::from_bits_truncate(sts)
365    }
366
367    /// Clear status flags.
368    ///
369    /// The high bits are cleared. The implementation will clear the non-W1C bits,
370    /// so it's safe to call this with [`Status::all()`].
371    pub fn clear_status(&self, sm: SM, status: Status) {
372        let sts = status & Status::W1C;
373        crate::ral::write_reg!(pwm::sm, self.submodule(sm), SMSTS, sts.bits())
374    }
375
376    /// Read the interrupt flags.
377    pub fn interrupts(&self, sm: SM) -> Interrupts {
378        let inten = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMINTEN);
379        Interrupts::from_bits_truncate(inten)
380    }
381
382    /// Set the interrupt flags.
383    pub fn set_interrupts(&self, sm: SM, interrupts: Interrupts) {
384        crate::ral::write_reg!(pwm::sm, self.submodule(sm), SMINTEN, interrupts.bits());
385    }
386
387    /// Read one of the six value registers.
388    ///
389    /// The return indicates the count value that will cause a comparison.
390    pub fn value(&self, sm: SM, value_register: ValueRegister) -> i16 {
391        let sm = self.submodule(sm);
392        (match value_register {
393            ValueRegister::Val0 => crate::ral::read_reg!(pwm::sm, sm, SMVAL0),
394            ValueRegister::Val1 => crate::ral::read_reg!(pwm::sm, sm, SMVAL1),
395            ValueRegister::Val2 => crate::ral::read_reg!(pwm::sm, sm, SMVAL2),
396            ValueRegister::Val3 => crate::ral::read_reg!(pwm::sm, sm, SMVAL3),
397            ValueRegister::Val4 => crate::ral::read_reg!(pwm::sm, sm, SMVAL4),
398            ValueRegister::Val5 => crate::ral::read_reg!(pwm::sm, sm, SMVAL5),
399        }) as _
400    }
401
402    /// Get the turn on value for a channel.
403    ///
404    /// This is the same as using [`turn_on()`] to produce a value register, then
405    /// calling [`value()`](Self::value) with that result.
406    pub fn turn_on(&self, sm: SM, channel: Channel) -> i16 {
407        self.value(sm, turn_on(channel))
408    }
409
410    /// Get the turn off value for a channel.
411    ///
412    /// This is the same as using [`turn_off()`] to produce a value register, then
413    /// calling [`value()`](Self::value) with that result.
414    pub fn turn_off(&self, sm: SM, channel: Channel) -> i16 {
415        self.value(sm, turn_off(channel))
416    }
417
418    /// Set one of the six value registers to compare at `value`.
419    pub fn set_value(&self, sm: SM, value_register: ValueRegister, value: i16) {
420        let value = value as u16;
421        let sm = self.submodule(sm);
422        match value_register {
423            ValueRegister::Val0 => crate::ral::write_reg!(pwm::sm, sm, SMVAL0, value),
424            ValueRegister::Val1 => crate::ral::write_reg!(pwm::sm, sm, SMVAL1, value),
425            ValueRegister::Val2 => crate::ral::write_reg!(pwm::sm, sm, SMVAL2, value),
426            ValueRegister::Val3 => crate::ral::write_reg!(pwm::sm, sm, SMVAL3, value),
427            ValueRegister::Val4 => crate::ral::write_reg!(pwm::sm, sm, SMVAL4, value),
428            ValueRegister::Val5 => crate::ral::write_reg!(pwm::sm, sm, SMVAL5, value),
429        }
430    }
431
432    /// Set the turn on compare for a channel.
433    ///
434    /// This is the same as using [`turn_on()`] to produce a value register, then
435    /// calling [`set_value()`](Self::set_value) with that result.
436    pub fn set_turn_on(&self, sm: SM, channel: Channel, compare: i16) {
437        self.set_value(sm, turn_on(channel), compare);
438    }
439
440    /// Set the turn off compare for a channel.
441    ///
442    /// This is the same as using [`turn_off()`] to produce a value register, then
443    /// calling [`set_value()`](Self::set_value) with that result.
444    pub fn set_turn_off(&self, sm: SM, channel: Channel, compare: i16) {
445        self.set_value(sm, turn_off(channel), compare);
446    }
447
448    /// Read the output masks for the PWM module.
449    pub fn output_masks(&self) -> OutputMasks {
450        // Masks are four bits wide. They fit within a u8.
451        let (pwm_a, pwm_b) = crate::ral::read_reg!(pwm, self.pwm, MASK, MASKA, MASKB);
452        OutputMasks {
453            pwm_a: Mask::from_bits_truncate(pwm_a as u8),
454            pwm_b: Mask::from_bits_truncate(pwm_b as u8),
455        }
456    }
457
458    /// Set the output masks for the PWM module.
459    ///
460    /// See [`OutputMasks`] to learn about output masking. The masking takes
461    /// effect at the next reload opportunity. (Although some MCUs might support
462    /// forced update, it's not standard across all MCUs, so it's not exported.)
463    ///
464    /// This call performs a single write. It does not read the existing mask
465    /// bits to maintain them. If you need to perform these incremental updates,
466    /// use [`output_masks`](Self::output_masks) to understand the prior state.
467    pub fn set_output_masks(&self, masks: OutputMasks) {
468        crate::ral::write_reg!(pwm, self.pwm, MASK,
469            MASKA: masks.pwm_a.bits() as u16,
470            MASKB: masks.pwm_b.bits() as u16,
471        );
472    }
473}
474
475/// The mask state of PWM outputs.
476///
477/// If a bit is high, the output is masked. Formally, it's diven to logic level 0
478/// in the IP block (before considering output polarity).
479#[derive(Clone, Copy, PartialEq, Eq)]
480#[non_exhaustive] // Leave option for pwm_x
481pub struct OutputMasks {
482    /// The PWM A outputs of a given submodule.
483    pub pwm_a: Mask,
484    /// The PWM B outputs of a given submodule.
485    pub pwm_b: Mask,
486}
487
488impl OutputMasks {
489    /// Returns a mask set with no outputs masked.
490    ///
491    /// After construction (in a constant context), you're free to manipulate
492    /// the mask bits.
493    pub const fn empty() -> Self {
494        Self {
495            pwm_a: Mask::empty(),
496            pwm_b: Mask::empty(),
497        }
498    }
499
500    /// Returns a mask set with all outputs masks.
501    pub const fn all() -> Self {
502        Self {
503            pwm_a: Mask::all(),
504            pwm_b: Mask::all(),
505        }
506    }
507}
508
509#[inline(never)]
510fn new(pwm: AnyPwmInstance) -> Pwm {
511    // Clear fault levels.
512    crate::ral::write_reg!(crate::ral::pwm, pwm, FCTRL0, FLVL: 0xF);
513    // Clear fault flags.
514    crate::ral::write_reg!(crate::ral::pwm, pwm, FSTS0, FFLAG: 0xF);
515
516    Pwm { pwm }
517}
518
519/// Index for submodule access.
520#[repr(usize)]
521#[derive(Clone, Copy, PartialEq, Eq)]
522pub enum SM {
523    /// Submodule 0.
524    SM0 = 0,
525    /// Submodule 1.
526    SM1 = 1,
527    /// Submodule 2.
528    SM2 = 2,
529    /// Submodule 3.
530    SM3 = 3,
531}
532
533impl SM {
534    /// Return this submodule's bitmask.
535    #[inline]
536    pub const fn mask(self) -> Mask {
537        Mask::from_bits_truncate(1 << (self as u8))
538    }
539}
540
541impl From<SM> for Mask {
542    #[inline]
543    fn from(value: SM) -> Self {
544        value.mask()
545    }
546}
547
548impl core::ops::BitOr for SM {
549    type Output = Mask;
550    #[inline]
551    fn bitor(self, rhs: Self) -> Self::Output {
552        self.mask() | rhs.mask()
553    }
554}
555
556impl core::ops::BitOr<Mask> for SM {
557    type Output = Mask;
558    #[inline]
559    fn bitor(self, rhs: Mask) -> Self::Output {
560        self.mask() | rhs
561    }
562}
563
564impl core::ops::BitOr<SM> for Mask {
565    type Output = Mask;
566    #[inline]
567    fn bitor(self, rhs: SM) -> Self::Output {
568        self | rhs.mask()
569    }
570}
571
572/// PWM clock prescaler.
573///
574/// Affects all timing, except for the glitch filters.
575#[cfg_attr(feature = "defmt", derive(defmt::Format))]
576#[derive(Debug, Clone, Copy, PartialEq, Eq)]
577#[repr(u16)]
578pub enum Prescaler {
579    /// Divide the PWM clock by 1.
580    Prescaler1,
581    /// Divide the PWM clock by 2.
582    Prescaler2,
583    /// Divide the PWM clock by 4.
584    Prescaler4,
585    /// Divide the PWM clock by 8.
586    Prescaler8,
587    /// Divide the PWM clock by 16.
588    Prescaler16,
589    /// Divide the PWM clock by 32.
590    Prescaler32,
591    /// Divide the PWM clock by 64.
592    Prescaler64,
593    /// Divide the PWM clock by 128.
594    Prescaler128,
595}
596
597impl Prescaler {
598    /// Returns the prescalar value as a divisor.
599    pub const fn divider(self) -> u32 {
600        1 << self as u32
601    }
602}
603
604/// Describes how PWM channels A and B operate.
605#[cfg_attr(feature = "defmt", derive(defmt::Format))]
606#[derive(Debug, Clone, Copy, PartialEq, Eq)]
607#[repr(u16)]
608pub enum PairOperation {
609    /// A and B form a complementary pair.
610    Complementary,
611    /// A and B operate independently.
612    Independent,
613}
614
615/// PWM input clock selection.
616#[cfg_attr(feature = "defmt", derive(defmt::Format))]
617#[derive(Debug, Clone, Copy, PartialEq, Eq)]
618#[repr(u16)]
619pub enum ClockSelect {
620    /// Derive from the IPG clock.
621    Ipg,
622    /// Use EXT_CLK, an external clock.
623    External,
624    /// Use submodule 0's clock.
625    ///
626    /// The clock is controlled by SM0's run bit. It's
627    /// affected by the SM0 prescaler.
628    ///
629    /// You cannot use this clock for submodule 0 itself.
630    Submodule0,
631}
632
633/// PWM (re)load mode.
634///
635/// Use the associated methods to simply define `ReloadCycle`
636/// values.
637#[cfg_attr(feature = "defmt", derive(defmt::Format))]
638#[derive(Debug, Clone, Copy, PartialEq, Eq)]
639pub enum LoadMode {
640    /// Reload on the next cycle after `LDOK` is set.
641    ///
642    /// One of these should be set. You may set both
643    /// to increase the reload opportunity frequency.
644    ReloadCycle {
645        /// Reload on a full cycle (VAL1 compares).
646        full: bool,
647        /// Reload on a half cycle (VAL0 compares).
648        half: bool,
649    },
650    /// Reload immediately after `LDOK` is set.
651    Immediate,
652}
653
654impl LoadMode {
655    /// Full reload cycle.
656    pub const fn reload_full() -> Self {
657        Self::ReloadCycle {
658            full: true,
659            half: false,
660        }
661    }
662    /// Half reload cycle.
663    pub const fn reload_half() -> Self {
664        Self::ReloadCycle {
665            full: false,
666            half: true,
667        }
668    }
669    /// Full and half reload cycle.
670    pub const fn reload_both() -> Self {
671        Self::ReloadCycle {
672            full: true,
673            half: true,
674        }
675    }
676}
677
678bitflags::bitflags! {
679    /// Status register flags.
680    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
681    pub struct Status : u16 {
682        /// Registers updated flag.
683        ///
684        /// This read-only flag is set to 1 when there's a
685        /// buffered value that the hardware will load on
686        /// the next LDOK assertion. Use this flag to know
687        /// if there is data in a buffered register.
688        const REGISTER_UPDATED = 1 << 14;
689        /// Reload error flag.
690        ///
691        /// Set when a reload cycle passed, there's something
692        /// in the buffered registers, and LDOK was 0. Cleared
693        /// by writing 1.
694        const RELOAD_ERROR = 1 << 13;
695        /// Reload flag.
696        ///
697        /// Set at the beginning of every reload cycle, regardless
698        /// of LDOK. Cleared by writing 1.
699        const RELOAD = 1 << 12;
700
701        /// VAL5 compared to the counter value.
702        const COMPARE_VAL5 = 1 << 5;
703        /// VAL4 compared to the counter value.
704        const COMPARE_VAL4 = 1 << 4;
705        /// VAL3 compared to the counter value.
706        const COMPARE_VAL3 = 1 << 3;
707        /// VAL2 compared to the counter value.
708        const COMPARE_VAL2 = 1 << 2;
709        /// VAL1 compared to the counter value.
710        const COMPARE_VAL1 = 1 << 1;
711        /// VAL0 compared to the counter value.
712        const COMPARE_VAL0 = 1 << 0;
713    }
714}
715
716impl Status {
717    /// The set of write-1-clear status bits.
718    pub const W1C: Status = Self::REGISTER_UPDATED.complement();
719}
720
721bitflags::bitflags! {
722    /// Interrupt flags.
723    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
724    pub struct Interrupts : u16 {
725        /// Reload error interrupt enable.
726        const RELOAD_ERROR = 1 << 13;
727        /// Reload interrupt enable.
728        const RELOAD = 1 << 12;
729
730        /// VAL5 compare interrupt enable.
731        const COMPARE_VAL5 = 1 << 5;
732        /// VAL4 compare interrupt enable.
733        const COMPARE_VAL4 = 1 << 4;
734        /// VAL3 compare interrupt enable.
735        const COMPARE_VAL3 = 1 << 3;
736        /// VAL2 compare interrupt enable.
737        const COMPARE_VAL2 = 1 << 2;
738        /// VAL1 compare interrupt enable.
739        const COMPARE_VAL1 = 1 << 1;
740        /// VAL0 compare interrupt enable.
741        const COMPARE_VAL0 = 1 << 0;
742    }
743}
744
745/// PWM value registers.
746///
747/// These value registers describe when PWM counters reset, and when outputs
748/// turn on and off. Consider using more descriptive constants, enums, and
749/// const functions to describe these values.
750#[cfg_attr(feature = "defmt", derive(defmt::Format))]
751#[derive(Debug, Clone, Copy, PartialEq, Eq)]
752pub enum ValueRegister {
753    /// The [`HALF_RELOAD_VALUE_REGISTER`].
754    Val0,
755    /// The [`FULL_RELOAD_VALUE_REGISTER`].
756    Val1,
757    /// The [`turn_on()`] register for [`Channel::A`].
758    Val2,
759    /// The [`turn_off()`] register for [`Channel::A`].
760    Val3,
761    /// The [`turn_on()`] register for [`Channel::B`].
762    Val4,
763    /// The [`turn_off()`] register for [`Channel::B`].
764    Val5,
765}
766
767/// The full reload value register.
768///
769/// When this register compares to the counter value, the counter
770/// resets.
771pub const FULL_RELOAD_VALUE_REGISTER: ValueRegister = ValueRegister::Val1;
772/// The half reload value register.
773///
774/// When this register compares to the counter value, it represents
775/// a half reload opportunity.
776pub const HALF_RELOAD_VALUE_REGISTER: ValueRegister = ValueRegister::Val0;
777
778/// Returns the "turn on" value register for an output channel.
779///
780/// When the counter compares to this value register, the PWM output
781/// turns on.
782pub const fn turn_on(channel: Channel) -> ValueRegister {
783    match channel {
784        Channel::A => ValueRegister::Val2,
785        Channel::B => ValueRegister::Val4,
786    }
787}
788
789/// Returns the "turn off" value register for an output channel.
790///
791/// When the counter compares to this value register, the PWM output
792/// turns off.
793pub const fn turn_off(channel: Channel) -> ValueRegister {
794    match channel {
795        Channel::A => ValueRegister::Val3,
796        Channel::B => ValueRegister::Val5,
797    }
798}
799
800/// PWM channels.
801#[cfg_attr(feature = "defmt", derive(defmt::Format))]
802#[derive(Debug, Clone, Copy, PartialEq, Eq)]
803pub enum Channel {
804    /// Channel A.
805    A,
806    /// Channel B.
807    B,
808}