Skip to content

Commit 2824a16

Browse files
committed
embassy_nrf::pwm: add config argument to SimplePwm constructors
1 parent 25699b9 commit 2824a16

File tree

1 file changed

+90
-28
lines changed

1 file changed

+90
-28
lines changed

embassy-nrf/src/pwm.rs

Lines changed: 90 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,53 @@ impl Default for Config {
311311
}
312312
}
313313

314+
/// Configuration for the simple PWM driver.
315+
#[derive(Debug, Clone)]
316+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
317+
#[non_exhaustive]
318+
pub struct SimpleConfig {
319+
/// Selects up mode or up-and-down mode for the counter
320+
pub counter_mode: CounterMode,
321+
/// Top value to be compared against buffer values
322+
pub max_duty: u16,
323+
/// Configuration for PWM_CLK
324+
pub prescaler: Prescaler,
325+
/// Drive strength for the channel 0 line.
326+
pub ch0_drive: OutputDrive,
327+
/// Drive strength for the channel 1 line.
328+
pub ch1_drive: OutputDrive,
329+
/// Drive strength for the channel 2 line.
330+
pub ch2_drive: OutputDrive,
331+
/// Drive strength for the channel 3 line.
332+
pub ch3_drive: OutputDrive,
333+
/// Output level for the channel 0 line when PWM if disabled.
334+
pub ch0_idle_level: Level,
335+
/// Output level for the channel 1 line when PWM if disabled.
336+
pub ch1_idle_level: Level,
337+
/// Output level for the channel 2 line when PWM if disabled.
338+
pub ch2_idle_level: Level,
339+
/// Output level for the channel 3 line when PWM if disabled.
340+
pub ch3_idle_level: Level,
341+
}
342+
343+
impl Default for SimpleConfig {
344+
fn default() -> Self {
345+
Self {
346+
counter_mode: CounterMode::Up,
347+
max_duty: 1000,
348+
prescaler: Prescaler::Div16,
349+
ch0_drive: OutputDrive::Standard,
350+
ch1_drive: OutputDrive::Standard,
351+
ch2_drive: OutputDrive::Standard,
352+
ch3_drive: OutputDrive::Standard,
353+
ch0_idle_level: Level::Low,
354+
ch1_idle_level: Level::Low,
355+
ch2_idle_level: Level::Low,
356+
ch3_idle_level: Level::Low,
357+
}
358+
}
359+
}
360+
314361
/// Configuration per sequence
315362
#[non_exhaustive]
316363
#[derive(Debug, Clone)]
@@ -643,46 +690,48 @@ impl defmt::Format for DutyCycle {
643690

644691
impl<'d> SimplePwm<'d> {
645692
/// Create a new 1-channel PWM
646-
#[allow(unused_unsafe)]
647-
pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>) -> Self {
648-
unsafe { Self::new_inner(pwm, Some(ch0.into()), None, None, None) }
693+
pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: &SimpleConfig) -> Self {
694+
Self::new_inner(pwm, Some(ch0.into()), None, None, None, config)
649695
}
650696

651697
/// Create a new 2-channel PWM
652-
#[allow(unused_unsafe)]
653-
pub fn new_2ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, ch1: Peri<'d, impl GpioPin>) -> Self {
654-
Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None)
698+
pub fn new_2ch<T: Instance>(
699+
pwm: Peri<'d, T>,
700+
ch0: Peri<'d, impl GpioPin>,
701+
ch1: Peri<'d, impl GpioPin>,
702+
config: &SimpleConfig,
703+
) -> Self {
704+
Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None, config)
655705
}
656706

657707
/// Create a new 3-channel PWM
658-
#[allow(unused_unsafe)]
659708
pub fn new_3ch<T: Instance>(
660709
pwm: Peri<'d, T>,
661710
ch0: Peri<'d, impl GpioPin>,
662711
ch1: Peri<'d, impl GpioPin>,
663712
ch2: Peri<'d, impl GpioPin>,
713+
config: &SimpleConfig,
664714
) -> Self {
665-
unsafe { Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None) }
715+
Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None, config)
666716
}
667717

668718
/// Create a new 4-channel PWM
669-
#[allow(unused_unsafe)]
670719
pub fn new_4ch<T: Instance>(
671720
pwm: Peri<'d, T>,
672721
ch0: Peri<'d, impl GpioPin>,
673722
ch1: Peri<'d, impl GpioPin>,
674723
ch2: Peri<'d, impl GpioPin>,
675724
ch3: Peri<'d, impl GpioPin>,
725+
config: &SimpleConfig,
676726
) -> Self {
677-
unsafe {
678-
Self::new_inner(
679-
pwm,
680-
Some(ch0.into()),
681-
Some(ch1.into()),
682-
Some(ch2.into()),
683-
Some(ch3.into()),
684-
)
685-
}
727+
Self::new_inner(
728+
pwm,
729+
Some(ch0.into()),
730+
Some(ch1.into()),
731+
Some(ch2.into()),
732+
Some(ch3.into()),
733+
config,
734+
)
686735
}
687736

688737
fn new_inner<T: Instance>(
@@ -691,24 +740,33 @@ impl<'d> SimplePwm<'d> {
691740
ch1: Option<Peri<'d, AnyPin>>,
692741
ch2: Option<Peri<'d, AnyPin>>,
693742
ch3: Option<Peri<'d, AnyPin>>,
743+
config: &SimpleConfig,
694744
) -> Self {
695745
let r = T::regs();
696746

697-
for (i, ch) in [&ch0, &ch1, &ch2, &ch3].into_iter().enumerate() {
698-
if let Some(pin) = ch {
699-
pin.set_low();
700-
747+
let channels = [
748+
(&ch0, config.ch0_drive, config.ch0_idle_level),
749+
(&ch1, config.ch1_drive, config.ch1_idle_level),
750+
(&ch2, config.ch2_drive, config.ch2_idle_level),
751+
(&ch3, config.ch3_drive, config.ch3_idle_level),
752+
];
753+
for (i, (pin, drive, idle_level)) in channels.into_iter().enumerate() {
754+
if let Some(pin) = pin {
755+
match idle_level {
756+
Level::Low => pin.set_low(),
757+
Level::High => pin.set_high(),
758+
}
701759
pin.conf().write(|w| {
702760
w.set_dir(gpiovals::Dir::OUTPUT);
703761
w.set_input(gpiovals::Input::DISCONNECT);
704-
w.set_drive(gpiovals::Drive::S0S1);
762+
convert_drive(w, drive);
705763
});
706764
}
707-
r.psel().out(i).write_value(ch.psel_bits());
765+
r.psel().out(i).write_value(pin.psel_bits());
708766
}
709767

710768
let pwm = Self {
711-
r: T::regs(),
769+
r,
712770
ch0,
713771
ch1,
714772
ch2,
@@ -732,9 +790,13 @@ impl<'d> SimplePwm<'d> {
732790
w.set_load(vals::Load::INDIVIDUAL);
733791
w.set_mode(vals::Mode::REFRESH_COUNT);
734792
});
735-
r.mode().write(|w| w.set_updown(vals::Updown::UP));
736-
r.prescaler().write(|w| w.set_prescaler(vals::Prescaler::DIV_16));
737-
r.countertop().write(|w| w.set_countertop(1000));
793+
r.mode().write(|w| match config.counter_mode {
794+
CounterMode::UpAndDown => w.set_updown(vals::Updown::UP_AND_DOWN),
795+
CounterMode::Up => w.set_updown(vals::Updown::UP),
796+
});
797+
r.prescaler()
798+
.write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8)));
799+
r.countertop().write(|w| w.set_countertop(config.max_duty));
738800
r.loop_().write(|w| w.set_cnt(vals::LoopCnt::DISABLED));
739801

740802
pwm

0 commit comments

Comments
 (0)