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}