Skip to content

Commit 25699b9

Browse files
committed
embassy_nrf::pwm: add channel idle level to config
1 parent ae382e7 commit 25699b9

File tree

1 file changed

+35
-50
lines changed

1 file changed

+35
-50
lines changed

embassy-nrf/src/pwm.rs

Lines changed: 35 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
66

77
use embassy_hal_internal::{Peri, PeripheralType};
88

9-
use crate::gpio::{AnyPin, DISCONNECTED, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive};
9+
use crate::gpio::{AnyPin, DISCONNECTED, Level, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive};
1010
use crate::pac::gpio::vals as gpiovals;
1111
use crate::pac::pwm::vals;
1212
use crate::ppi::{Event, Task};
@@ -53,13 +53,11 @@ pub const PWM_CLK_HZ: u32 = 16_000_000;
5353

5454
impl<'d> SequencePwm<'d> {
5555
/// Create a new 1-channel PWM
56-
#[allow(unused_unsafe)]
5756
pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result<Self, Error> {
5857
Self::new_inner(pwm, Some(ch0.into()), None, None, None, config)
5958
}
6059

6160
/// Create a new 2-channel PWM
62-
#[allow(unused_unsafe)]
6361
pub fn new_2ch<T: Instance>(
6462
pwm: Peri<'d, T>,
6563
ch0: Peri<'d, impl GpioPin>,
@@ -70,7 +68,6 @@ impl<'d> SequencePwm<'d> {
7068
}
7169

7270
/// Create a new 3-channel PWM
73-
#[allow(unused_unsafe)]
7471
pub fn new_3ch<T: Instance>(
7572
pwm: Peri<'d, T>,
7673
ch0: Peri<'d, impl GpioPin>,
@@ -82,7 +79,6 @@ impl<'d> SequencePwm<'d> {
8279
}
8380

8481
/// Create a new 4-channel PWM
85-
#[allow(unused_unsafe)]
8682
pub fn new_4ch<T: Instance>(
8783
pwm: Peri<'d, T>,
8884
ch0: Peri<'d, impl GpioPin>,
@@ -111,44 +107,27 @@ impl<'d> SequencePwm<'d> {
111107
) -> Result<Self, Error> {
112108
let r = T::regs();
113109

114-
if let Some(pin) = &ch0 {
115-
pin.set_low();
116-
pin.conf().write(|w| {
117-
w.set_dir(gpiovals::Dir::OUTPUT);
118-
w.set_input(gpiovals::Input::DISCONNECT);
119-
convert_drive(w, config.ch0_drive);
120-
});
121-
}
122-
if let Some(pin) = &ch1 {
123-
pin.set_low();
124-
pin.conf().write(|w| {
125-
w.set_dir(gpiovals::Dir::OUTPUT);
126-
w.set_input(gpiovals::Input::DISCONNECT);
127-
convert_drive(w, config.ch1_drive);
128-
});
129-
}
130-
if let Some(pin) = &ch2 {
131-
pin.set_low();
132-
pin.conf().write(|w| {
133-
w.set_dir(gpiovals::Dir::OUTPUT);
134-
w.set_input(gpiovals::Input::DISCONNECT);
135-
convert_drive(w, config.ch2_drive);
136-
});
137-
}
138-
if let Some(pin) = &ch3 {
139-
pin.set_low();
140-
pin.conf().write(|w| {
141-
w.set_dir(gpiovals::Dir::OUTPUT);
142-
w.set_input(gpiovals::Input::DISCONNECT);
143-
convert_drive(w, config.ch3_drive);
144-
});
110+
let channels = [
111+
(&ch0, config.ch0_drive, config.ch0_idle_level),
112+
(&ch1, config.ch1_drive, config.ch1_idle_level),
113+
(&ch2, config.ch2_drive, config.ch2_idle_level),
114+
(&ch3, config.ch3_drive, config.ch3_idle_level),
115+
];
116+
for (i, (pin, drive, idle_level)) in channels.into_iter().enumerate() {
117+
if let Some(pin) = pin {
118+
match idle_level {
119+
Level::Low => pin.set_low(),
120+
Level::High => pin.set_high(),
121+
}
122+
pin.conf().write(|w| {
123+
w.set_dir(gpiovals::Dir::OUTPUT);
124+
w.set_input(gpiovals::Input::DISCONNECT);
125+
convert_drive(w, drive);
126+
});
127+
}
128+
r.psel().out(i).write_value(pin.psel_bits());
145129
}
146130

147-
r.psel().out(0).write_value(ch0.psel_bits());
148-
r.psel().out(1).write_value(ch1.psel_bits());
149-
r.psel().out(2).write_value(ch2.psel_bits());
150-
r.psel().out(3).write_value(ch3.psel_bits());
151-
152131
// Disable all interrupts
153132
r.intenclr().write(|w| w.0 = 0xFFFF_FFFF);
154133
r.shorts().write(|_| ());
@@ -173,13 +152,7 @@ impl<'d> SequencePwm<'d> {
173152
.write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8)));
174153
r.countertop().write(|w| w.set_countertop(config.max_duty));
175154

176-
Ok(Self {
177-
r: T::regs(),
178-
ch0,
179-
ch1,
180-
ch2,
181-
ch3,
182-
})
155+
Ok(Self { r, ch0, ch1, ch2, ch3 })
183156
}
184157

185158
/// Returns reference to `Stopped` event endpoint for PPI.
@@ -309,11 +282,19 @@ pub struct Config {
309282
pub ch2_drive: OutputDrive,
310283
/// Drive strength for the channel 3 line.
311284
pub ch3_drive: OutputDrive,
285+
/// Output level for the channel 0 line when PWM if disabled.
286+
pub ch0_idle_level: Level,
287+
/// Output level for the channel 1 line when PWM if disabled.
288+
pub ch1_idle_level: Level,
289+
/// Output level for the channel 2 line when PWM if disabled.
290+
pub ch2_idle_level: Level,
291+
/// Output level for the channel 3 line when PWM if disabled.
292+
pub ch3_idle_level: Level,
312293
}
313294

314295
impl Default for Config {
315-
fn default() -> Config {
316-
Config {
296+
fn default() -> Self {
297+
Self {
317298
counter_mode: CounterMode::Up,
318299
max_duty: 1000,
319300
prescaler: Prescaler::Div16,
@@ -322,6 +303,10 @@ impl Default for Config {
322303
ch1_drive: OutputDrive::Standard,
323304
ch2_drive: OutputDrive::Standard,
324305
ch3_drive: OutputDrive::Standard,
306+
ch0_idle_level: Level::Low,
307+
ch1_idle_level: Level::Low,
308+
ch2_idle_level: Level::Low,
309+
ch3_idle_level: Level::Low,
325310
}
326311
}
327312
}

0 commit comments

Comments
 (0)