diff options
| author | Maarten de Vries <[email protected]> | 2025-10-15 12:01:18 +0200 |
|---|---|---|
| committer | Maarten de Vries <[email protected]> | 2025-10-15 14:42:08 +0200 |
| commit | 9c66ec1589ae2e55817e03d9e2bb8666050d054c (patch) | |
| tree | 37c8ea7eb56e1a0853c71df4defcd7c6fd008d28 /embassy-nrf/src | |
| parent | b2dce7a67e0dc18c568da5758190e23778d025ef (diff) | |
embassy_nrf::pwm: add channel idle level to config
Diffstat (limited to 'embassy-nrf/src')
| -rw-r--r-- | embassy-nrf/src/pwm.rs | 85 |
1 files 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}; | |||
| 6 | 6 | ||
| 7 | use embassy_hal_internal::{Peri, PeripheralType}; | 7 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 8 | 8 | ||
| 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}; |
| 10 | use crate::pac::gpio::vals as gpiovals; | 10 | use crate::pac::gpio::vals as gpiovals; |
| 11 | use crate::pac::pwm::vals; | 11 | use crate::pac::pwm::vals; |
| 12 | use crate::ppi::{Event, Task}; | 12 | use crate::ppi::{Event, Task}; |
| @@ -53,13 +53,11 @@ pub const PWM_CLK_HZ: u32 = 16_000_000; | |||
| 53 | 53 | ||
| 54 | impl<'d> SequencePwm<'d> { | 54 | impl<'d> SequencePwm<'d> { |
| 55 | /// Create a new 1-channel PWM | 55 | /// Create a new 1-channel PWM |
| 56 | #[allow(unused_unsafe)] | ||
| 57 | pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result<Self, Error> { | 56 | pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result<Self, Error> { |
| 58 | Self::new_inner(pwm, Some(ch0.into()), None, None, None, config) | 57 | Self::new_inner(pwm, Some(ch0.into()), None, None, None, config) |
| 59 | } | 58 | } |
| 60 | 59 | ||
| 61 | /// Create a new 2-channel PWM | 60 | /// Create a new 2-channel PWM |
| 62 | #[allow(unused_unsafe)] | ||
| 63 | pub fn new_2ch<T: Instance>( | 61 | pub fn new_2ch<T: Instance>( |
| 64 | pwm: Peri<'d, T>, | 62 | pwm: Peri<'d, T>, |
| 65 | ch0: Peri<'d, impl GpioPin>, | 63 | ch0: Peri<'d, impl GpioPin>, |
| @@ -70,7 +68,6 @@ impl<'d> SequencePwm<'d> { | |||
| 70 | } | 68 | } |
| 71 | 69 | ||
| 72 | /// Create a new 3-channel PWM | 70 | /// Create a new 3-channel PWM |
| 73 | #[allow(unused_unsafe)] | ||
| 74 | pub fn new_3ch<T: Instance>( | 71 | pub fn new_3ch<T: Instance>( |
| 75 | pwm: Peri<'d, T>, | 72 | pwm: Peri<'d, T>, |
| 76 | ch0: Peri<'d, impl GpioPin>, | 73 | ch0: Peri<'d, impl GpioPin>, |
| @@ -82,7 +79,6 @@ impl<'d> SequencePwm<'d> { | |||
| 82 | } | 79 | } |
| 83 | 80 | ||
| 84 | /// Create a new 4-channel PWM | 81 | /// Create a new 4-channel PWM |
| 85 | #[allow(unused_unsafe)] | ||
| 86 | pub fn new_4ch<T: Instance>( | 82 | pub fn new_4ch<T: Instance>( |
| 87 | pwm: Peri<'d, T>, | 83 | pwm: Peri<'d, T>, |
| 88 | ch0: Peri<'d, impl GpioPin>, | 84 | ch0: Peri<'d, impl GpioPin>, |
| @@ -111,44 +107,27 @@ impl<'d> SequencePwm<'d> { | |||
| 111 | ) -> Result<Self, Error> { | 107 | ) -> Result<Self, Error> { |
| 112 | let r = T::regs(); | 108 | let r = T::regs(); |
| 113 | 109 | ||
| 114 | if let Some(pin) = &ch0 { | 110 | let channels = [ |
| 115 | pin.set_low(); | 111 | (&ch0, config.ch0_drive, config.ch0_idle_level), |
| 116 | pin.conf().write(|w| { | 112 | (&ch1, config.ch1_drive, config.ch1_idle_level), |
| 117 | w.set_dir(gpiovals::Dir::OUTPUT); | 113 | (&ch2, config.ch2_drive, config.ch2_idle_level), |
| 118 | w.set_input(gpiovals::Input::DISCONNECT); | 114 | (&ch3, config.ch3_drive, config.ch3_idle_level), |
| 119 | convert_drive(w, config.ch0_drive); | 115 | ]; |
| 120 | }); | 116 | for (i, (pin, drive, idle_level)) in channels.into_iter().enumerate() { |
| 121 | } | 117 | if let Some(pin) = pin { |
| 122 | if let Some(pin) = &ch1 { | 118 | match idle_level { |
| 123 | pin.set_low(); | 119 | Level::Low => pin.set_low(), |
| 124 | pin.conf().write(|w| { | 120 | Level::High => pin.set_high(), |
| 125 | w.set_dir(gpiovals::Dir::OUTPUT); | 121 | } |
| 126 | w.set_input(gpiovals::Input::DISCONNECT); | 122 | pin.conf().write(|w| { |
| 127 | convert_drive(w, config.ch1_drive); | 123 | w.set_dir(gpiovals::Dir::OUTPUT); |
| 128 | }); | 124 | w.set_input(gpiovals::Input::DISCONNECT); |
| 129 | } | 125 | convert_drive(w, drive); |
| 130 | if let Some(pin) = &ch2 { | 126 | }); |
| 131 | pin.set_low(); | 127 | } |
| 132 | pin.conf().write(|w| { | 128 | r.psel().out(i).write_value(pin.psel_bits()); |
| 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 | }); | ||
| 145 | } | 129 | } |
| 146 | 130 | ||
| 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 | |||
| 152 | // Disable all interrupts | 131 | // Disable all interrupts |
| 153 | r.intenclr().write(|w| w.0 = 0xFFFF_FFFF); | 132 | r.intenclr().write(|w| w.0 = 0xFFFF_FFFF); |
| 154 | r.shorts().write(|_| ()); | 133 | r.shorts().write(|_| ()); |
| @@ -173,13 +152,7 @@ impl<'d> SequencePwm<'d> { | |||
| 173 | .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8))); | 152 | .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8))); |
| 174 | r.countertop().write(|w| w.set_countertop(config.max_duty)); | 153 | r.countertop().write(|w| w.set_countertop(config.max_duty)); |
| 175 | 154 | ||
| 176 | Ok(Self { | 155 | Ok(Self { r, ch0, ch1, ch2, ch3 }) |
| 177 | r: T::regs(), | ||
| 178 | ch0, | ||
| 179 | ch1, | ||
| 180 | ch2, | ||
| 181 | ch3, | ||
| 182 | }) | ||
| 183 | } | 156 | } |
| 184 | 157 | ||
| 185 | /// Returns reference to `Stopped` event endpoint for PPI. | 158 | /// Returns reference to `Stopped` event endpoint for PPI. |
| @@ -309,11 +282,19 @@ pub struct Config { | |||
| 309 | pub ch2_drive: OutputDrive, | 282 | pub ch2_drive: OutputDrive, |
| 310 | /// Drive strength for the channel 3 line. | 283 | /// Drive strength for the channel 3 line. |
| 311 | pub ch3_drive: OutputDrive, | 284 | 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, | ||
| 312 | } | 293 | } |
| 313 | 294 | ||
| 314 | impl Default for Config { | 295 | impl Default for Config { |
| 315 | fn default() -> Config { | 296 | fn default() -> Self { |
| 316 | Config { | 297 | Self { |
| 317 | counter_mode: CounterMode::Up, | 298 | counter_mode: CounterMode::Up, |
| 318 | max_duty: 1000, | 299 | max_duty: 1000, |
| 319 | prescaler: Prescaler::Div16, | 300 | prescaler: Prescaler::Div16, |
| @@ -322,6 +303,10 @@ impl Default for Config { | |||
| 322 | ch1_drive: OutputDrive::Standard, | 303 | ch1_drive: OutputDrive::Standard, |
| 323 | ch2_drive: OutputDrive::Standard, | 304 | ch2_drive: OutputDrive::Standard, |
| 324 | ch3_drive: OutputDrive::Standard, | 305 | 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, | ||
| 325 | } | 310 | } |
| 326 | } | 311 | } |
| 327 | } | 312 | } |
