From ec97698085e79239b51429f59249a7f42bf04368 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 11:55:40 +0200 Subject: embassy_nrf::pwm: derive more traits for public structs --- embassy-nrf/src/pwm.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index e038f44b8..1fa8f183b 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -289,6 +289,8 @@ impl<'a> Drop for SequencePwm<'a> { } /// Configuration for the PWM as a whole. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub struct Config { /// Selects up mode or up-and-down mode for the counter @@ -326,7 +328,8 @@ impl Default for Config { /// Configuration per sequence #[non_exhaustive] -#[derive(Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SequenceConfig { /// Number of PWM periods to delay between each sequence sample pub refresh: u32, @@ -345,6 +348,8 @@ impl Default for SequenceConfig { /// A composition of a sequence buffer and its configuration. #[non_exhaustive] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Sequence<'s> { /// The words comprising the sequence. Must not exceed 32767 words. pub words: &'s [u16], @@ -496,6 +501,7 @@ impl<'d, 's> Drop for Sequencer<'d, 's> { /// How many times to run a single sequence #[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SingleSequenceMode { /// Run a single sequence n Times total. Times(u16), @@ -505,6 +511,7 @@ pub enum SingleSequenceMode { /// Which sequence to start a loop with #[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum StartSequence { /// Start with Sequence 0 Zero, @@ -514,6 +521,7 @@ pub enum StartSequence { /// How many loops to run two sequences #[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SequenceMode { /// Run two sequences n loops i.e. (n * (seq0 + seq1.unwrap_or(seq0))) Loop(u16), @@ -523,6 +531,7 @@ pub enum SequenceMode { /// PWM Base clock is system clock (16MHz) divided by prescaler #[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Prescaler { /// Divide by 1 Div1, @@ -544,6 +553,7 @@ pub enum Prescaler { /// How the sequence values are distributed across the channels #[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SequenceLoad { /// Provided sequence will be used across all channels Common, @@ -560,6 +570,7 @@ pub enum SequenceLoad { /// Selects up mode or up-and-down mode for the counter #[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum CounterMode { /// Up counter (edge-aligned PWM duty cycle) Up, -- cgit From 5be0e0e7f9d453fc695c1a3c5b8b8148d7a4852a Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 11:58:46 +0200 Subject: embassy_nrf::pwm: expose duty cycle polarity for SimplePwm --- embassy-nrf/src/pwm.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 1fa8f183b..e47922e5a 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -17,7 +17,7 @@ use crate::{interrupt, pac}; /// to simply set a duty cycle across up to four channels. pub struct SimplePwm<'d> { r: pac::pwm::Pwm, - duty: [u16; 4], + duty: [DutyCycle; 4], ch0: Option>, ch1: Option>, ch2: Option>, @@ -578,6 +578,84 @@ pub enum CounterMode { UpAndDown, } +/// Duty value and polarity for a single channel. +/// +/// If the channel has inverted polarity, the output is set high as long as the counter is below the duty value. +#[repr(transparent)] +#[derive(Eq, PartialEq, Clone, Copy)] +pub struct DutyCycle { + /// The raw duty cycle valuea. + /// + /// This has the duty cycle in the lower 15 bits. + /// The highest bit indicates that the duty cycle has inverted polarity. + raw: u16, +} + +impl DutyCycle { + /// Make a new duty value with normal polarity. + /// + /// The value is truncated to 15 bits. + /// + /// The output is set high if the counter is at or above the duty value. + pub const fn normal(value: u16) -> Self { + let raw = value & 0x7FFF; + Self { raw } + } + + /// Make a new duty cycle with inverted polarity. + /// + /// The value is truncated to 15 bits. + /// + /// The output is set high if the counter is below the duty value. + pub const fn inverted(value: u16) -> Self { + let raw = value | 0x8000; + Self { raw } + } + + /// Adjust the polarity of the duty cycle (returns a new object). + #[must_use = "this function return a new object, it does not modify self"] + pub const fn with_inverted(self, inverted_polarity: bool) -> Self { + if inverted_polarity { + Self::inverted(self.value()) + } else { + Self::normal(self.value()) + } + } + + /// Gets the 15-bit value of the duty cycle. + pub const fn value(&self) -> u16 { + self.raw & 0x7FFF + } + + /// Checks if the duty period has inverted polarity. + /// + /// If the channel has inverted polarity, the output is set high as long as the counter is below the duty value. + pub const fn is_inverted(&self) -> bool { + self.raw & 0x8000 != 0 + } +} + +impl core::fmt::Debug for DutyCycle { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_struct("DutyCycle") + .field("value", &self.value()) + .field("inverted", &self.is_inverted()) + .finish() + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for DutyCycle { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "DutyCycle {{ value: {=u16}, inverted: {=bool} }}", + self.value(), + self.is_inverted(), + ); + } +} + impl<'d> SimplePwm<'d> { /// Create a new 1-channel PWM #[allow(unused_unsafe)] @@ -650,7 +728,7 @@ impl<'d> SimplePwm<'d> { ch1, ch2, ch3, - duty: [0; 4], + duty: [const { DutyCycle::normal(0) }; 4], }; // Disable all interrupts @@ -695,14 +773,14 @@ impl<'d> SimplePwm<'d> { self.r.enable().write(|w| w.set_enable(false)); } - /// Returns the current duty of the channel - pub fn duty(&self, channel: usize) -> u16 { + /// Returns the current duty of the channel. + pub fn duty(&self, channel: usize) -> DutyCycle { self.duty[channel] } - /// Sets duty cycle (15 bit) for a PWM channel. - pub fn set_duty(&mut self, channel: usize, duty: u16) { - self.duty[channel] = duty & 0x7FFF; + /// Sets duty cycle (15 bit) and polarity for a PWM channel. + pub fn set_duty(&mut self, channel: usize, duty: DutyCycle) { + self.duty[channel] = duty; // reload ptr in case self was moved self.r.seq(0).ptr().write_value((self.duty).as_ptr() as u32); -- cgit From b2dce7a67e0dc18c568da5758190e23778d025ef Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 11:59:42 +0200 Subject: embassy_nrf::pwm: allow setting all duty cycles of SimplePwm at once --- embassy-nrf/src/pwm.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index e47922e5a..7fbe9be9d 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -781,7 +781,23 @@ impl<'d> SimplePwm<'d> { /// Sets duty cycle (15 bit) and polarity for a PWM channel. pub fn set_duty(&mut self, channel: usize, duty: DutyCycle) { self.duty[channel] = duty; + self.sync_duty_cyles_to_peripheral(); + } + + /// Sets the duty cycle (15 bit) and polarity for all PWM channels. + /// + /// You can safely set the duty cycle of disabled PWM channels. + /// + /// When using this function, a single DMA transfer sets all the duty cycles. + /// If you call [`Self::set_duty()`] multiple times, + /// each duty cycle will be set by a separate DMA transfer. + pub fn set_all_duties(&mut self, duty: [DutyCycle; 4]) { + self.duty = duty; + self.sync_duty_cyles_to_peripheral(); + } + /// Transfer the duty cycles from `self` to the peripheral. + fn sync_duty_cyles_to_peripheral(&self) { // reload ptr in case self was moved self.r.seq(0).ptr().write_value((self.duty).as_ptr() as u32); -- cgit From 9c66ec1589ae2e55817e03d9e2bb8666050d054c Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 12:01:18 +0200 Subject: embassy_nrf::pwm: add channel idle level to config --- embassy-nrf/src/pwm.rs | 85 +++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 7fbe9be9d..6743674e8 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -6,7 +6,7 @@ use core::sync::atomic::{Ordering, compiler_fence}; use embassy_hal_internal::{Peri, PeripheralType}; -use crate::gpio::{AnyPin, DISCONNECTED, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive}; +use crate::gpio::{AnyPin, DISCONNECTED, Level, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive}; use crate::pac::gpio::vals as gpiovals; use crate::pac::pwm::vals; use crate::ppi::{Event, Task}; @@ -53,13 +53,11 @@ pub const PWM_CLK_HZ: u32 = 16_000_000; impl<'d> SequencePwm<'d> { /// Create a new 1-channel PWM - #[allow(unused_unsafe)] pub fn new_1ch(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result { Self::new_inner(pwm, Some(ch0.into()), None, None, None, config) } /// Create a new 2-channel PWM - #[allow(unused_unsafe)] pub fn new_2ch( pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, @@ -70,7 +68,6 @@ impl<'d> SequencePwm<'d> { } /// Create a new 3-channel PWM - #[allow(unused_unsafe)] pub fn new_3ch( pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, @@ -82,7 +79,6 @@ impl<'d> SequencePwm<'d> { } /// Create a new 4-channel PWM - #[allow(unused_unsafe)] pub fn new_4ch( pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, @@ -111,44 +107,27 @@ impl<'d> SequencePwm<'d> { ) -> Result { let r = T::regs(); - if let Some(pin) = &ch0 { - pin.set_low(); - pin.conf().write(|w| { - w.set_dir(gpiovals::Dir::OUTPUT); - w.set_input(gpiovals::Input::DISCONNECT); - convert_drive(w, config.ch0_drive); - }); - } - if let Some(pin) = &ch1 { - pin.set_low(); - pin.conf().write(|w| { - w.set_dir(gpiovals::Dir::OUTPUT); - w.set_input(gpiovals::Input::DISCONNECT); - convert_drive(w, config.ch1_drive); - }); - } - if let Some(pin) = &ch2 { - pin.set_low(); - pin.conf().write(|w| { - w.set_dir(gpiovals::Dir::OUTPUT); - w.set_input(gpiovals::Input::DISCONNECT); - convert_drive(w, config.ch2_drive); - }); - } - if let Some(pin) = &ch3 { - pin.set_low(); - pin.conf().write(|w| { - w.set_dir(gpiovals::Dir::OUTPUT); - w.set_input(gpiovals::Input::DISCONNECT); - convert_drive(w, config.ch3_drive); - }); + let channels = [ + (&ch0, config.ch0_drive, config.ch0_idle_level), + (&ch1, config.ch1_drive, config.ch1_idle_level), + (&ch2, config.ch2_drive, config.ch2_idle_level), + (&ch3, config.ch3_drive, config.ch3_idle_level), + ]; + for (i, (pin, drive, idle_level)) in channels.into_iter().enumerate() { + if let Some(pin) = pin { + match idle_level { + Level::Low => pin.set_low(), + Level::High => pin.set_high(), + } + pin.conf().write(|w| { + w.set_dir(gpiovals::Dir::OUTPUT); + w.set_input(gpiovals::Input::DISCONNECT); + convert_drive(w, drive); + }); + } + r.psel().out(i).write_value(pin.psel_bits()); } - r.psel().out(0).write_value(ch0.psel_bits()); - r.psel().out(1).write_value(ch1.psel_bits()); - r.psel().out(2).write_value(ch2.psel_bits()); - r.psel().out(3).write_value(ch3.psel_bits()); - // Disable all interrupts r.intenclr().write(|w| w.0 = 0xFFFF_FFFF); r.shorts().write(|_| ()); @@ -173,13 +152,7 @@ impl<'d> SequencePwm<'d> { .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8))); r.countertop().write(|w| w.set_countertop(config.max_duty)); - Ok(Self { - r: T::regs(), - ch0, - ch1, - ch2, - ch3, - }) + Ok(Self { r, ch0, ch1, ch2, ch3 }) } /// Returns reference to `Stopped` event endpoint for PPI. @@ -309,11 +282,19 @@ pub struct Config { pub ch2_drive: OutputDrive, /// Drive strength for the channel 3 line. pub ch3_drive: OutputDrive, + /// Output level for the channel 0 line when PWM if disabled. + pub ch0_idle_level: Level, + /// Output level for the channel 1 line when PWM if disabled. + pub ch1_idle_level: Level, + /// Output level for the channel 2 line when PWM if disabled. + pub ch2_idle_level: Level, + /// Output level for the channel 3 line when PWM if disabled. + pub ch3_idle_level: Level, } impl Default for Config { - fn default() -> Config { - Config { + fn default() -> Self { + Self { counter_mode: CounterMode::Up, max_duty: 1000, prescaler: Prescaler::Div16, @@ -322,6 +303,10 @@ impl Default for Config { ch1_drive: OutputDrive::Standard, ch2_drive: OutputDrive::Standard, ch3_drive: OutputDrive::Standard, + ch0_idle_level: Level::Low, + ch1_idle_level: Level::Low, + ch2_idle_level: Level::Low, + ch3_idle_level: Level::Low, } } } -- cgit From eba322b5108e16de2c57a55d96fcedee154b6303 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 12:02:39 +0200 Subject: embassy_nrf::pwm: add config argument to SimplePwm constructors --- embassy-nrf/src/pwm.rs | 118 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 28 deletions(-) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 6743674e8..00b3278c7 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -311,6 +311,53 @@ impl Default for Config { } } +/// Configuration for the simple PWM driver. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub struct SimpleConfig { + /// Selects up mode or up-and-down mode for the counter + pub counter_mode: CounterMode, + /// Top value to be compared against buffer values + pub max_duty: u16, + /// Configuration for PWM_CLK + pub prescaler: Prescaler, + /// Drive strength for the channel 0 line. + pub ch0_drive: OutputDrive, + /// Drive strength for the channel 1 line. + pub ch1_drive: OutputDrive, + /// Drive strength for the channel 2 line. + pub ch2_drive: OutputDrive, + /// Drive strength for the channel 3 line. + pub ch3_drive: OutputDrive, + /// Output level for the channel 0 line when PWM if disabled. + pub ch0_idle_level: Level, + /// Output level for the channel 1 line when PWM if disabled. + pub ch1_idle_level: Level, + /// Output level for the channel 2 line when PWM if disabled. + pub ch2_idle_level: Level, + /// Output level for the channel 3 line when PWM if disabled. + pub ch3_idle_level: Level, +} + +impl Default for SimpleConfig { + fn default() -> Self { + Self { + counter_mode: CounterMode::Up, + max_duty: 1000, + prescaler: Prescaler::Div16, + ch0_drive: OutputDrive::Standard, + ch1_drive: OutputDrive::Standard, + ch2_drive: OutputDrive::Standard, + ch3_drive: OutputDrive::Standard, + ch0_idle_level: Level::Low, + ch1_idle_level: Level::Low, + ch2_idle_level: Level::Low, + ch3_idle_level: Level::Low, + } + } +} + /// Configuration per sequence #[non_exhaustive] #[derive(Debug, Clone)] @@ -643,46 +690,48 @@ impl defmt::Format for DutyCycle { impl<'d> SimplePwm<'d> { /// Create a new 1-channel PWM - #[allow(unused_unsafe)] - pub fn new_1ch(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>) -> Self { - unsafe { Self::new_inner(pwm, Some(ch0.into()), None, None, None) } + pub fn new_1ch(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: &SimpleConfig) -> Self { + Self::new_inner(pwm, Some(ch0.into()), None, None, None, config) } /// Create a new 2-channel PWM - #[allow(unused_unsafe)] - pub fn new_2ch(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, ch1: Peri<'d, impl GpioPin>) -> Self { - Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None) + pub fn new_2ch( + pwm: Peri<'d, T>, + ch0: Peri<'d, impl GpioPin>, + ch1: Peri<'d, impl GpioPin>, + config: &SimpleConfig, + ) -> Self { + Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None, config) } /// Create a new 3-channel PWM - #[allow(unused_unsafe)] pub fn new_3ch( pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, ch1: Peri<'d, impl GpioPin>, ch2: Peri<'d, impl GpioPin>, + config: &SimpleConfig, ) -> Self { - unsafe { Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None) } + Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None, config) } /// Create a new 4-channel PWM - #[allow(unused_unsafe)] pub fn new_4ch( pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, ch1: Peri<'d, impl GpioPin>, ch2: Peri<'d, impl GpioPin>, ch3: Peri<'d, impl GpioPin>, + config: &SimpleConfig, ) -> Self { - unsafe { - Self::new_inner( - pwm, - Some(ch0.into()), - Some(ch1.into()), - Some(ch2.into()), - Some(ch3.into()), - ) - } + Self::new_inner( + pwm, + Some(ch0.into()), + Some(ch1.into()), + Some(ch2.into()), + Some(ch3.into()), + config, + ) } fn new_inner( @@ -691,24 +740,33 @@ impl<'d> SimplePwm<'d> { ch1: Option>, ch2: Option>, ch3: Option>, + config: &SimpleConfig, ) -> Self { let r = T::regs(); - for (i, ch) in [&ch0, &ch1, &ch2, &ch3].into_iter().enumerate() { - if let Some(pin) = ch { - pin.set_low(); - + let channels = [ + (&ch0, config.ch0_drive, config.ch0_idle_level), + (&ch1, config.ch1_drive, config.ch1_idle_level), + (&ch2, config.ch2_drive, config.ch2_idle_level), + (&ch3, config.ch3_drive, config.ch3_idle_level), + ]; + for (i, (pin, drive, idle_level)) in channels.into_iter().enumerate() { + if let Some(pin) = pin { + match idle_level { + Level::Low => pin.set_low(), + Level::High => pin.set_high(), + } pin.conf().write(|w| { w.set_dir(gpiovals::Dir::OUTPUT); w.set_input(gpiovals::Input::DISCONNECT); - w.set_drive(gpiovals::Drive::S0S1); + convert_drive(w, drive); }); } - r.psel().out(i).write_value(ch.psel_bits()); + r.psel().out(i).write_value(pin.psel_bits()); } let pwm = Self { - r: T::regs(), + r, ch0, ch1, ch2, @@ -732,9 +790,13 @@ impl<'d> SimplePwm<'d> { w.set_load(vals::Load::INDIVIDUAL); w.set_mode(vals::Mode::REFRESH_COUNT); }); - r.mode().write(|w| w.set_updown(vals::Updown::UP)); - r.prescaler().write(|w| w.set_prescaler(vals::Prescaler::DIV_16)); - r.countertop().write(|w| w.set_countertop(1000)); + r.mode().write(|w| match config.counter_mode { + CounterMode::UpAndDown => w.set_updown(vals::Updown::UP_AND_DOWN), + CounterMode::Up => w.set_updown(vals::Updown::UP), + }); + r.prescaler() + .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8))); + r.countertop().write(|w| w.set_countertop(config.max_duty)); r.loop_().write(|w| w.set_cnt(vals::LoopCnt::DISABLED)); pwm -- cgit From 3250345748cd25f209ff3426ae01bad55b2c8e9e Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 14:41:25 +0200 Subject: embassy_nrf: update CHANGELOG --- embassy-nrf/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 3df7bfd4c..8ce484646 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - added: Add basic RTC support for nRF54L - changed: apply trimming values from FICR.TRIMCNF on nrf53/54l - changed: do not panic on BufferedUarte overrun +- added: allow configuring the idle state of GPIO pins connected to PWM channels +- changed: allow configuring the PWM peripheral in the constructor of `SimplePwm` +- changed: support setting duty cycles with inverted polarity in `SimplePwm` +- added: support setting the duty cycles of all channels at once in `SimplePwm` ## 0.8.0 - 2025-09-30 -- cgit From 369959e654d095d0e3d95597693bd64fcdb50ec5 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 14:53:40 +0200 Subject: embassy_nrf: update examples --- examples/nrf52840/src/bin/i2s_monitor.rs | 9 ++++----- examples/nrf52840/src/bin/pwm.rs | 14 ++++++++------ examples/nrf52840/src/bin/pwm_servo.rs | 14 +++++++------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/examples/nrf52840/src/bin/i2s_monitor.rs b/examples/nrf52840/src/bin/i2s_monitor.rs index 66b429b09..a54659101 100644 --- a/examples/nrf52840/src/bin/i2s_monitor.rs +++ b/examples/nrf52840/src/bin/i2s_monitor.rs @@ -4,7 +4,7 @@ use defmt::{debug, error, info}; use embassy_executor::Spawner; use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth}; -use embassy_nrf::pwm::{Prescaler, SimplePwm}; +use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; use embassy_nrf::{bind_interrupts, peripherals}; use {defmt_rtt as _, panic_probe as _}; @@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) { I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); // Configure the PWM to use the pins corresponding to the RGB leds - let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); + let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24, &Default::default()); pwm.set_prescaler(Prescaler::Div1); pwm.set_max_duty(255); @@ -47,9 +47,8 @@ async fn main(_spawner: Spawner) { let rgb = rgb_from_rms(rms); debug!("RMS: {}, RGB: {:?}", rms, rgb); - for i in 0..3 { - pwm.set_duty(i, rgb[i].into()); - } + let duties = rgb.map(|byte| DutyCycle::normal(u16::from(byte))); + pwm.set_all_duties([duties[0], duties[1], duties[2], DutyCycle::normal(0)]); if let Err(err) = input_stream.receive().await { error!("{}", err); diff --git a/examples/nrf52840/src/bin/pwm.rs b/examples/nrf52840/src/bin/pwm.rs index a5bb1347a..02f9b4191 100644 --- a/examples/nrf52840/src/bin/pwm.rs +++ b/examples/nrf52840/src/bin/pwm.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_nrf::pwm::{Prescaler, SimplePwm}; +use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -71,7 +71,7 @@ static DUTY: [u16; 1024] = [ #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); - let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); + let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15, &Default::default()); pwm.set_prescaler(Prescaler::Div1); pwm.set_max_duty(32767); info!("pwm initialized!"); @@ -79,10 +79,12 @@ async fn main(_spawner: Spawner) { let mut i = 0; loop { i += 1; - pwm.set_duty(0, DUTY[i % 1024]); - pwm.set_duty(1, DUTY[(i + 256) % 1024]); - pwm.set_duty(2, DUTY[(i + 512) % 1024]); - pwm.set_duty(3, DUTY[(i + 768) % 1024]); + pwm.set_all_duties([ + DutyCycle::normal(DUTY[i % 1024]), + DutyCycle::normal(DUTY[(i + 256) % 1024]), + DutyCycle::normal(DUTY[(i + 512) % 1024]), + DutyCycle::normal(DUTY[(i + 768) % 1024]), + ]); Timer::after_millis(3).await; } } diff --git a/examples/nrf52840/src/bin/pwm_servo.rs b/examples/nrf52840/src/bin/pwm_servo.rs index d772d2f5d..93cb984e6 100644 --- a/examples/nrf52840/src/bin/pwm_servo.rs +++ b/examples/nrf52840/src/bin/pwm_servo.rs @@ -3,14 +3,14 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_nrf::pwm::{Prescaler, SimplePwm}; +use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); - let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05); + let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05, &Default::default()); // sg90 microervo requires 50hz or 20ms period // set_period can only set down to 125khz so we cant use it directly // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top @@ -24,23 +24,23 @@ async fn main(_spawner: Spawner) { loop { info!("45 deg"); // poor mans inverting, subtract our value from max_duty - pwm.set_duty(0, 2500 - 156); + pwm.set_duty(0, DutyCycle::normal(2500 - 156)); Timer::after_millis(5000).await; info!("90 deg"); - pwm.set_duty(0, 2500 - 187); + pwm.set_duty(0, DutyCycle::normal(2500 - 187)); Timer::after_millis(5000).await; info!("135 deg"); - pwm.set_duty(0, 2500 - 218); + pwm.set_duty(0, DutyCycle::normal(2500 - 218)); Timer::after_millis(5000).await; info!("180 deg"); - pwm.set_duty(0, 2500 - 250); + pwm.set_duty(0, DutyCycle::normal(2500 - 250)); Timer::after_millis(5000).await; info!("0 deg"); - pwm.set_duty(0, 2500 - 125); + pwm.set_duty(0, DutyCycle::normal(2500 - 125)); Timer::after_millis(5000).await; } } -- cgit From 7ef9a6453a0a2a286741d47fcb99170d802f7d7d Mon Sep 17 00:00:00 2001 From: Rob Wells Date: Mon, 27 Oct 2025 15:23:54 +0000 Subject: embassy-rp: doc comment spelling pass All changes but one are to documentation comments, and one to an ordinary comment. --- embassy-rp/CHANGELOG.md | 2 +- embassy-rp/src/block.rs | 4 ++-- embassy-rp/src/clocks.rs | 2 +- embassy-rp/src/i2c_slave.rs | 4 ++-- embassy-rp/src/multicore.rs | 2 +- embassy-rp/src/pio/mod.rs | 2 +- embassy-rp/src/pio_programs/i2s.rs | 18 +++++++++--------- embassy-rp/src/pio_programs/pwm.rs | 2 +- embassy-rp/src/pio_programs/spi.rs | 4 ++-- embassy-rp/src/pio_programs/uart.rs | 2 +- embassy-rp/src/rom_data/rp2040.rs | 2 +- embassy-rp/src/rtc/mod.rs | 2 +- embassy-rp/src/spi.rs | 2 +- embassy-rp/src/uart/mod.rs | 2 +- 14 files changed, 25 insertions(+), 25 deletions(-) diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index a99d04aa4..57ec13658 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate -- Fix typo in interrupt comment +- Fix several minor typos in documentation - Add PIO SPI - Add PIO I2S input - Add PIO onewire parasite power strong pullup diff --git a/embassy-rp/src/block.rs b/embassy-rp/src/block.rs index a3e1ad925..745883b83 100644 --- a/embassy-rp/src/block.rs +++ b/embassy-rp/src/block.rs @@ -240,7 +240,7 @@ impl UnpartitionedSpace { } } - /// Create a new unpartition space from run-time values. + /// Create a new unpartitioned space from run-time values. /// /// Get these from the ROM function `get_partition_table_info` with an argument of `PT_INFO`. pub const fn from_raw(permissions_and_location: u32, permissions_and_flags: u32) -> Self { @@ -714,7 +714,7 @@ impl PartitionTableBlock { new_table } - /// Add a a SHA256 hash of the Block + /// Add a SHA256 hash of the Block /// /// Adds a `HASH_DEF` covering all the previous items in the Block, and a /// `HASH_VALUE` with a SHA-256 hash of them. diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 56892d7a2..8bfb5129a 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -267,7 +267,7 @@ impl CoreVoltage { } } -/// CLock configuration. +/// Clock configuration. #[non_exhaustive] pub struct ClockConfig { /// Ring oscillator configuration. diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs index 770087bc8..0853709df 100644 --- a/embassy-rp/src/i2c_slave.rs +++ b/embassy-rp/src/i2c_slave.rs @@ -52,7 +52,7 @@ pub enum ReadStatus { Done, /// Transaction Incomplete, controller trying to read more bytes than were provided NeedMoreBytes, - /// Transaction Complere, but controller stopped reading bytes before we ran out + /// Transaction Complete, but controller stopped reading bytes before we ran out LeftoverBytes(u16), } @@ -240,7 +240,7 @@ impl<'d, T: Instance> I2cSlave<'d, T> { if p.ic_rxflr().read().rxflr() > 0 || me.pending_byte.is_some() { me.drain_fifo(buffer, &mut len); - // we're recieving data, set rx fifo watermark to 12 bytes (3/4 full) to reduce interrupt noise + // we're receiving data, set rx fifo watermark to 12 bytes (3/4 full) to reduce interrupt noise p.ic_rx_tl().write(|w| w.set_rx_tl(11)); } diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index 3b120e349..572d8db91 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -58,7 +58,7 @@ const PAUSE_TOKEN: u32 = 0xDEADBEEF; const RESUME_TOKEN: u32 = !0xDEADBEEF; static IS_CORE1_INIT: AtomicBool = AtomicBool::new(false); -/// Represents a partiticular CPU core (SIO_CPUID) +/// Represents a particular CPU core (SIO_CPUID) #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs index 38ee1f97c..92b2c603e 100644 --- a/embassy-rp/src/pio/mod.rs +++ b/embassy-rp/src/pio/mod.rs @@ -62,7 +62,7 @@ pub enum FifoJoin { #[cfg(feature = "_rp235x")] RxAsControl, /// FJOIN_RX_PUT | FJOIN_RX_GET: RX can be used as a scratch register, - /// not accesible from the CPU + /// not accessible from the CPU #[cfg(feature = "_rp235x")] PioScratch, } diff --git a/embassy-rp/src/pio_programs/i2s.rs b/embassy-rp/src/pio_programs/i2s.rs index 7e5f68ad6..5c49beecb 100644 --- a/embassy-rp/src/pio_programs/i2s.rs +++ b/embassy-rp/src/pio_programs/i2s.rs @@ -1,4 +1,4 @@ -//! Pio backed I2s output and output drivers +//! Pio backed I2S output and output drivers use fixed::traits::ToFixed; @@ -9,7 +9,7 @@ use crate::pio::{ Common, Config, Direction, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine, }; -/// This struct represents an i2s receiver & controller driver program +/// This struct represents an I2S receiver & controller driver program pub struct PioI2sInProgram<'d, PIO: Instance> { prg: LoadedProgram<'d, PIO>, } @@ -35,7 +35,7 @@ impl<'d, PIO: Instance> PioI2sInProgram<'d, PIO> { } } -/// Pio backed I2s input driver +/// Pio backed I2S input driver pub struct PioI2sIn<'d, P: Instance, const S: usize> { dma: Peri<'d, AnyChannel>, sm: StateMachine<'d, P, S>, @@ -50,7 +50,7 @@ impl<'d, P: Instance, const S: usize> PioI2sIn<'d, P, S> { // Whether or not to use the MCU's internal pull-down resistor, as the // Pico 2 is known to have problems with the inbuilt pulldowns, many // opt to just use an external pull down resistor to meet requirements of common - // i2s microphones such as the INMP441 + // I2S microphones such as the INMP441 data_pulldown: bool, data_pin: Peri<'d, impl PioPin>, bit_clock_pin: Peri<'d, impl PioPin>, @@ -90,13 +90,13 @@ impl<'d, P: Instance, const S: usize> PioI2sIn<'d, P, S> { Self { dma: dma.into(), sm } } - /// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer. + /// Return an in-progress dma transfer future. Awaiting it will guarantee a complete transfer. pub fn read<'b>(&'b mut self, buff: &'b mut [u32]) -> Transfer<'b, AnyChannel> { self.sm.rx().dma_pull(self.dma.reborrow(), buff, false) } } -/// This struct represents an i2s output driver program +/// This struct represents an I2S output driver program /// /// The sample bit-depth is set through scratch register `Y`. /// `Y` has to be set to sample bit-depth - 2. @@ -128,14 +128,14 @@ impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> { } } -/// Pio backed I2s output driver +/// Pio backed I2S output driver pub struct PioI2sOut<'d, P: Instance, const S: usize> { dma: Peri<'d, AnyChannel>, sm: StateMachine<'d, P, S>, } impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> { - /// Configure a state machine to output I2s + /// Configure a state machine to output I2S pub fn new( common: &mut Common<'d, P>, mut sm: StateMachine<'d, P, S>, @@ -179,7 +179,7 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> { Self { dma: dma.into(), sm } } - /// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer. + /// Return an in-progress dma transfer future. Awaiting it will guarantee a complete transfer. pub fn write<'b>(&'b mut self, buff: &'b [u32]) -> Transfer<'b, AnyChannel> { self.sm.tx().dma_push(self.dma.reborrow(), buff, false) } diff --git a/embassy-rp/src/pio_programs/pwm.rs b/embassy-rp/src/pio_programs/pwm.rs index ba06bb3c1..e4ad4a6f0 100644 --- a/embassy-rp/src/pio_programs/pwm.rs +++ b/embassy-rp/src/pio_programs/pwm.rs @@ -67,7 +67,7 @@ impl<'d, T: Instance, const SM: usize> PioPwm<'d, T, SM> { Self { sm, pin } } - /// Enable's the PIO program, continuing the wave generation from the PIO program. + /// Enables the PIO program, continuing the wave generation from the PIO program. pub fn start(&mut self) { self.sm.set_enable(true); } diff --git a/embassy-rp/src/pio_programs/spi.rs b/embassy-rp/src/pio_programs/spi.rs index b10fc6628..765ffaa06 100644 --- a/embassy-rp/src/pio_programs/spi.rs +++ b/embassy-rp/src/pio_programs/spi.rs @@ -1,4 +1,4 @@ -//! PIO backed SPi drivers +//! PIO backed SPI drivers use core::marker::PhantomData; @@ -83,7 +83,7 @@ pub enum Error { // No errors for now } -/// PIO based Spi driver. +/// PIO based SPI driver. /// Unlike other PIO programs, the PIO SPI driver owns and holds a reference to /// the PIO memory it uses. This is so that it can be reconfigured at runtime if /// desired. diff --git a/embassy-rp/src/pio_programs/uart.rs b/embassy-rp/src/pio_programs/uart.rs index 444efb5db..d59596dd1 100644 --- a/embassy-rp/src/pio_programs/uart.rs +++ b/embassy-rp/src/pio_programs/uart.rs @@ -130,7 +130,7 @@ impl<'d, PIO: Instance> PioUartRxProgram<'d, PIO> { } } -/// PIO backed Uart reciever +/// PIO backed Uart receiver pub struct PioUartRx<'d, PIO: Instance, const SM: usize> { sm_rx: StateMachine<'d, PIO, SM>, } diff --git a/embassy-rp/src/rom_data/rp2040.rs b/embassy-rp/src/rom_data/rp2040.rs index 5a74eddd6..27a8d8981 100644 --- a/embassy-rp/src/rom_data/rp2040.rs +++ b/embassy-rp/src/rom_data/rp2040.rs @@ -30,7 +30,7 @@ const DATA_TABLE: *const u16 = 0x0000_0016 as _; /// Address of the version number of the ROM. const VERSION_NUMBER: *const u8 = 0x0000_0013 as _; -/// Retrive rom content from a table using a code. +/// Retrieve rom content from a table using a code. fn rom_table_lookup(table: *const u16, tag: RomFnTableCode) -> T { unsafe { let rom_table_lookup_ptr: *const u32 = rom_hword_as_ptr(ROM_TABLE_LOOKUP_PTR); diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index 68fb3b765..054572903 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -47,7 +47,7 @@ impl<'d, T: Instance> Rtc<'d, T> { Self { inner } } - /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisable by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. + /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisible by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. /// /// Leap year checking is enabled by default. pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) { diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 559b3b909..d9410e78d 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -157,7 +157,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { /// Private function to apply SPI configuration (phase, polarity, frequency) settings. /// - /// Driver should be disabled before making changes and reenabled after the modifications + /// Driver should be disabled before making changes and re-enabled after the modifications /// are applied. fn apply_config(inner: &Peri<'d, T>, config: &Config) { let p = inner.regs(); diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 43187df2d..8be87a5d2 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -315,7 +315,7 @@ impl<'d, M: Mode> UartRx<'d, M> { } /// Returns Ok(len) if no errors occurred. Returns Err((len, err)) if an error was - /// encountered. in both cases, `len` is the number of *good* bytes copied into + /// encountered. In both cases, `len` is the number of *good* bytes copied into /// `buffer`. fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result { let r = self.info.regs; -- cgit From e282662f2408455d5f7e53c010c3bf0d8eeb99aa Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 27 Oct 2025 21:10:19 -0500 Subject: timer: add output compare values --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/timer/low_level.rs | 69 ++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 9848daf49..000d215b7 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: stm32/usart: add `eager_reads` option to control if buffered readers return as soon as possible or after more data is available ([#4668](https://github.com/embassy-rs/embassy/pull/4668)) - feat: stm32/usart: add `de_assertion_time` and `de_deassertion_time` config options - change: stm32/uart: BufferedUartRx now returns all available bytes from the internal buffer +- change: timer: added output compare values ## 0.4.0 - 2025-08-26 diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index ac039bb0d..7c02e7e62 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -143,20 +143,69 @@ pub enum OutputCompareMode { /// TIMx_CNTTIMx_CCRx else inactive. PwmMode2, - // TODO: there's more modes here depending on the chip family. + + #[cfg(timer_v2)] + /// In up-counting mode, the channel is active until a trigger + /// event is detected (on tim_trgi signal). Then, a comparison is performed as in PWM + /// mode 1 and the channels becomes active again at the next update. In down-counting + /// mode, the channel is inactive until a trigger event is detected (on tim_trgi signal). + /// Then, a comparison is performed as in PWM mode 1 and the channels becomes + /// inactive again at the next update. + OnePulseMode1, + + #[cfg(timer_v2)] + /// In up-counting mode, the channel is inactive until a + /// trigger event is detected (on tim_trgi signal). Then, a comparison is performed as in + /// PWM mode 2 and the channels becomes inactive again at the next update. In down + /// counting mode, the channel is active until a trigger event is detected (on tim_trgi + /// signal). Then, a comparison is performed as in PWM mode 1 and the channels + /// becomes active again at the next update. + OnePulseMode2, + + #[cfg(timer_v2)] + /// Combined PWM mode 1 - tim_oc1ref has the same behavior as in PWM mode 1. + /// tim_oc1refc is the logical OR between tim_oc1ref and tim_oc2ref. + CombinedPwmMode1, + + #[cfg(timer_v2)] + /// Combined PWM mode 2 - tim_oc1ref has the same behavior as in PWM mode 2. + /// tim_oc1refc is the logical AND between tim_oc1ref and tim_oc2ref. + CombinedPwmMode2, + + #[cfg(timer_v2)] + /// tim_oc1ref has the same behavior as in PWM mode 1. tim_oc1refc outputs tim_oc1ref + /// when the counter is counting up, tim_oc2ref when it is counting down. + AsymmetricPwmMode1, + + #[cfg(timer_v2)] + /// tim_oc1ref has the same behavior as in PWM mode 2. tim_oc1refc outputs tim_oc1ref + /// when the counter is counting up, tim_oc2ref when it is counting down. + AsymmetricPwmMode2, } -impl From for stm32_metapac::timer::vals::Ocm { +impl From for crate::pac::timer::vals::Ocm { fn from(mode: OutputCompareMode) -> Self { match mode { - OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, - OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVE_ON_MATCH, - OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVE_ON_MATCH, - OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, - OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCE_INACTIVE, - OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCE_ACTIVE, - OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWM_MODE1, - OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWM_MODE2, + OutputCompareMode::Frozen => crate::pac::timer::vals::Ocm::FROZEN, + OutputCompareMode::ActiveOnMatch => crate::pac::timer::vals::Ocm::ACTIVE_ON_MATCH, + OutputCompareMode::InactiveOnMatch => crate::pac::timer::vals::Ocm::INACTIVE_ON_MATCH, + OutputCompareMode::Toggle => crate::pac::timer::vals::Ocm::TOGGLE, + OutputCompareMode::ForceInactive => crate::pac::timer::vals::Ocm::FORCE_INACTIVE, + OutputCompareMode::ForceActive => crate::pac::timer::vals::Ocm::FORCE_ACTIVE, + OutputCompareMode::PwmMode1 => crate::pac::timer::vals::Ocm::PWM_MODE1, + OutputCompareMode::PwmMode2 => crate::pac::timer::vals::Ocm::PWM_MODE2, + #[cfg(timer_v2)] + OutputCompareMode::OnePulseMode1 => crate::pac::timer::vals::Ocm::RETRIGERRABLE_OPM_MODE_1, + #[cfg(timer_v2)] + OutputCompareMode::OnePulseMode2 => crate::pac::timer::vals::Ocm::RETRIGERRABLE_OPM_MODE_2, + #[cfg(timer_v2)] + OutputCompareMode::CombinedPwmMode1 => crate::pac::timer::vals::Ocm::COMBINED_PWM_MODE_1, + #[cfg(timer_v2)] + OutputCompareMode::CombinedPwmMode2 => crate::pac::timer::vals::Ocm::COMBINED_PWM_MODE_2, + #[cfg(timer_v2)] + OutputCompareMode::AsymmetricPwmMode1 => crate::pac::timer::vals::Ocm::ASYMMETRIC_PWM_MODE_1, + #[cfg(timer_v2)] + OutputCompareMode::AsymmetricPwmMode2 => crate::pac::timer::vals::Ocm::ASYMMETRIC_PWM_MODE_2, } } } -- cgit