aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorMaarten de Vries <[email protected]>2025-10-15 11:58:46 +0200
committerMaarten de Vries <[email protected]>2025-10-15 14:42:06 +0200
commit5be0e0e7f9d453fc695c1a3c5b8b8148d7a4852a (patch)
treeea36650b5923f3c1809e1b24b4b8d43c38c7a207 /embassy-nrf/src
parentec97698085e79239b51429f59249a7f42bf04368 (diff)
embassy_nrf::pwm: expose duty cycle polarity for SimplePwm
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/pwm.rs92
1 files 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};
17/// to simply set a duty cycle across up to four channels. 17/// to simply set a duty cycle across up to four channels.
18pub struct SimplePwm<'d> { 18pub struct SimplePwm<'d> {
19 r: pac::pwm::Pwm, 19 r: pac::pwm::Pwm,
20 duty: [u16; 4], 20 duty: [DutyCycle; 4],
21 ch0: Option<Peri<'d, AnyPin>>, 21 ch0: Option<Peri<'d, AnyPin>>,
22 ch1: Option<Peri<'d, AnyPin>>, 22 ch1: Option<Peri<'d, AnyPin>>,
23 ch2: Option<Peri<'d, AnyPin>>, 23 ch2: Option<Peri<'d, AnyPin>>,
@@ -578,6 +578,84 @@ pub enum CounterMode {
578 UpAndDown, 578 UpAndDown,
579} 579}
580 580
581/// Duty value and polarity for a single channel.
582///
583/// If the channel has inverted polarity, the output is set high as long as the counter is below the duty value.
584#[repr(transparent)]
585#[derive(Eq, PartialEq, Clone, Copy)]
586pub struct DutyCycle {
587 /// The raw duty cycle valuea.
588 ///
589 /// This has the duty cycle in the lower 15 bits.
590 /// The highest bit indicates that the duty cycle has inverted polarity.
591 raw: u16,
592}
593
594impl DutyCycle {
595 /// Make a new duty value with normal polarity.
596 ///
597 /// The value is truncated to 15 bits.
598 ///
599 /// The output is set high if the counter is at or above the duty value.
600 pub const fn normal(value: u16) -> Self {
601 let raw = value & 0x7FFF;
602 Self { raw }
603 }
604
605 /// Make a new duty cycle with inverted polarity.
606 ///
607 /// The value is truncated to 15 bits.
608 ///
609 /// The output is set high if the counter is below the duty value.
610 pub const fn inverted(value: u16) -> Self {
611 let raw = value | 0x8000;
612 Self { raw }
613 }
614
615 /// Adjust the polarity of the duty cycle (returns a new object).
616 #[must_use = "this function return a new object, it does not modify self"]
617 pub const fn with_inverted(self, inverted_polarity: bool) -> Self {
618 if inverted_polarity {
619 Self::inverted(self.value())
620 } else {
621 Self::normal(self.value())
622 }
623 }
624
625 /// Gets the 15-bit value of the duty cycle.
626 pub const fn value(&self) -> u16 {
627 self.raw & 0x7FFF
628 }
629
630 /// Checks if the duty period has inverted polarity.
631 ///
632 /// If the channel has inverted polarity, the output is set high as long as the counter is below the duty value.
633 pub const fn is_inverted(&self) -> bool {
634 self.raw & 0x8000 != 0
635 }
636}
637
638impl core::fmt::Debug for DutyCycle {
639 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
640 f.debug_struct("DutyCycle")
641 .field("value", &self.value())
642 .field("inverted", &self.is_inverted())
643 .finish()
644 }
645}
646
647#[cfg(feature = "defmt")]
648impl defmt::Format for DutyCycle {
649 fn format(&self, f: defmt::Formatter) {
650 defmt::write!(
651 f,
652 "DutyCycle {{ value: {=u16}, inverted: {=bool} }}",
653 self.value(),
654 self.is_inverted(),
655 );
656 }
657}
658
581impl<'d> SimplePwm<'d> { 659impl<'d> SimplePwm<'d> {
582 /// Create a new 1-channel PWM 660 /// Create a new 1-channel PWM
583 #[allow(unused_unsafe)] 661 #[allow(unused_unsafe)]
@@ -650,7 +728,7 @@ impl<'d> SimplePwm<'d> {
650 ch1, 728 ch1,
651 ch2, 729 ch2,
652 ch3, 730 ch3,
653 duty: [0; 4], 731 duty: [const { DutyCycle::normal(0) }; 4],
654 }; 732 };
655 733
656 // Disable all interrupts 734 // Disable all interrupts
@@ -695,14 +773,14 @@ impl<'d> SimplePwm<'d> {
695 self.r.enable().write(|w| w.set_enable(false)); 773 self.r.enable().write(|w| w.set_enable(false));
696 } 774 }
697 775
698 /// Returns the current duty of the channel 776 /// Returns the current duty of the channel.
699 pub fn duty(&self, channel: usize) -> u16 { 777 pub fn duty(&self, channel: usize) -> DutyCycle {
700 self.duty[channel] 778 self.duty[channel]
701 } 779 }
702 780
703 /// Sets duty cycle (15 bit) for a PWM channel. 781 /// Sets duty cycle (15 bit) and polarity for a PWM channel.
704 pub fn set_duty(&mut self, channel: usize, duty: u16) { 782 pub fn set_duty(&mut self, channel: usize, duty: DutyCycle) {
705 self.duty[channel] = duty & 0x7FFF; 783 self.duty[channel] = duty;
706 784
707 // reload ptr in case self was moved 785 // reload ptr in case self was moved
708 self.r.seq(0).ptr().write_value((self.duty).as_ptr() as u32); 786 self.r.seq(0).ptr().write_value((self.duty).as_ptr() as u32);