imxrt_hal/common/
flexpwm.rs

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