aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2024-10-23 10:30:13 +0000
committerGitHub <[email protected]>2024-10-23 10:30:13 +0000
commit8803128707b8bd9fc9dcea392a62dfd42aa822d2 (patch)
treef7ce53e194af927e02b015bf8e5dcd837169a70e
parent8eb80c6816a1f6ea7814acd4f48f07e79891f804 (diff)
parentf2646b29a6b0a741fc424f88c5ca3dc25fce9369 (diff)
Merge pull request #3317 from GrantM11235/simplepwmchannel
embassy-stm32: Add SimplePwmChannel
-rw-r--r--embassy-stm32/src/timer/low_level.rs7
-rw-r--r--embassy-stm32/src/timer/mod.rs3
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs270
-rw-r--r--examples/stm32f4/src/bin/pwm.rs19
-rw-r--r--examples/stm32f4/src/bin/ws2812_pwm.rs4
-rw-r--r--examples/stm32g0/src/bin/input_capture.rs8
-rw-r--r--examples/stm32g0/src/bin/pwm_input.rs10
-rw-r--r--examples/stm32g4/src/bin/pwm.rs19
-rw-r--r--examples/stm32h7/src/bin/pwm.rs19
9 files changed, 269 insertions, 90 deletions
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
index e643722aa..3136ea4e9 100644
--- a/embassy-stm32/src/timer/low_level.rs
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -6,6 +6,8 @@
6//! 6//!
7//! The available functionality depends on the timer type. 7//! The available functionality depends on the timer type.
8 8
9use core::mem::ManuallyDrop;
10
9use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 11use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
10// Re-export useful enums 12// Re-export useful enums
11pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource}; 13pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource};
@@ -198,6 +200,11 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
198 Self { tim } 200 Self { tim }
199 } 201 }
200 202
203 pub(crate) unsafe fn clone_unchecked(&self) -> ManuallyDrop<Self> {
204 let tim = unsafe { self.tim.clone_unchecked() };
205 ManuallyDrop::new(Self { tim })
206 }
207
201 /// Get access to the virutal core 16bit timer registers. 208 /// Get access to the virutal core 16bit timer registers.
202 /// 209 ///
203 /// Note: This works even if the timer is more capable, because registers 210 /// Note: This works even if the timer is more capable, because registers
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 25782ee13..aa9dd91d9 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -2,6 +2,7 @@
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
5use embassy_hal_internal::Peripheral;
5use embassy_sync::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
6 7
7#[cfg(not(stm32l0))] 8#[cfg(not(stm32l0))]
@@ -66,7 +67,7 @@ impl State {
66 } 67 }
67} 68}
68 69
69trait SealedInstance: RccPeripheral { 70trait SealedInstance: RccPeripheral + Peripheral<P = Self> {
70 /// Async state for this timer 71 /// Async state for this timer
71 fn state() -> &'static State; 72 fn state() -> &'static State;
72} 73}
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index b7771bd64..9e4a09095 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -1,6 +1,7 @@
1//! Simple PWM driver. 1//! Simple PWM driver.
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::mem::ManuallyDrop;
4 5
5use embassy_hal_internal::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
6 7
@@ -51,6 +52,111 @@ channel_impl!(new_ch2, Ch2, Channel2Pin);
51channel_impl!(new_ch3, Ch3, Channel3Pin); 52channel_impl!(new_ch3, Ch3, Channel3Pin);
52channel_impl!(new_ch4, Ch4, Channel4Pin); 53channel_impl!(new_ch4, Ch4, Channel4Pin);
53 54
55/// A single channel of a pwm, obtained from [`SimplePwm::split`],
56/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc.
57///
58/// It is not possible to change the pwm frequency because
59/// the frequency configuration is shared with all four channels.
60pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> {
61 timer: ManuallyDrop<Timer<'d, T>>,
62 channel: Channel,
63}
64
65// TODO: check for RMW races
66impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> {
67 /// Enable the given channel.
68 pub fn enable(&mut self) {
69 self.timer.enable_channel(self.channel, true);
70 }
71
72 /// Disable the given channel.
73 pub fn disable(&mut self) {
74 self.timer.enable_channel(self.channel, false);
75 }
76
77 /// Check whether given channel is enabled
78 pub fn is_enabled(&self) -> bool {
79 self.timer.get_channel_enable_state(self.channel)
80 }
81
82 /// Get max duty value.
83 ///
84 /// This value depends on the configured frequency and the timer's clock rate from RCC.
85 pub fn max_duty_cycle(&self) -> u16 {
86 let max = self.timer.get_max_compare_value();
87 assert!(max < u16::MAX as u32);
88 max as u16 + 1
89 }
90
91 /// Set the duty for a given channel.
92 ///
93 /// The value ranges from 0 for 0% duty, to [`max_duty_cycle`](Self::max_duty_cycle) for 100% duty, both included.
94 pub fn set_duty_cycle(&mut self, duty: u16) {
95 assert!(duty <= (*self).max_duty_cycle());
96 self.timer.set_compare_value(self.channel, duty.into())
97 }
98
99 /// Set the duty cycle to 0%, or always inactive.
100 pub fn set_duty_cycle_fully_off(&mut self) {
101 self.set_duty_cycle(0);
102 }
103
104 /// Set the duty cycle to 100%, or always active.
105 pub fn set_duty_cycle_fully_on(&mut self) {
106 self.set_duty_cycle((*self).max_duty_cycle());
107 }
108
109 /// Set the duty cycle to `num / denom`.
110 ///
111 /// The caller is responsible for ensuring that `num` is less than or equal to `denom`,
112 /// and that `denom` is not zero.
113 pub fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) {
114 assert!(denom != 0);
115 assert!(num <= denom);
116 let duty = u32::from(num) * u32::from(self.max_duty_cycle()) / u32::from(denom);
117
118 // This is safe because we know that `num <= denom`, so `duty <= self.max_duty_cycle()` (u16)
119 #[allow(clippy::cast_possible_truncation)]
120 self.set_duty_cycle(duty as u16);
121 }
122
123 /// Set the duty cycle to `percent / 100`
124 ///
125 /// The caller is responsible for ensuring that `percent` is less than or equal to 100.
126 pub fn set_duty_cycle_percent(&mut self, percent: u8) {
127 self.set_duty_cycle_fraction(u16::from(percent), 100)
128 }
129
130 /// Get the duty for a given channel.
131 ///
132 /// The value ranges from 0 for 0% duty, to [`max_duty_cycle`](Self::max_duty_cycle) for 100% duty, both included.
133 pub fn current_duty_cycle(&self) -> u16 {
134 unwrap!(self.timer.get_compare_value(self.channel).try_into())
135 }
136
137 /// Set the output polarity for a given channel.
138 pub fn set_polarity(&mut self, polarity: OutputPolarity) {
139 self.timer.set_output_polarity(self.channel, polarity);
140 }
141
142 /// Set the output compare mode for a given channel.
143 pub fn set_output_compare_mode(&mut self, mode: OutputCompareMode) {
144 self.timer.set_output_compare_mode(self.channel, mode);
145 }
146}
147
148/// A group of four [`SimplePwmChannel`]s, obtained from [`SimplePwm::split`].
149pub struct SimplePwmChannels<'d, T: GeneralInstance4Channel> {
150 /// Channel 1
151 pub ch1: SimplePwmChannel<'d, T>,
152 /// Channel 2
153 pub ch2: SimplePwmChannel<'d, T>,
154 /// Channel 3
155 pub ch3: SimplePwmChannel<'d, T>,
156 /// Channel 4
157 pub ch4: SimplePwmChannel<'d, T>,
158}
159
54/// Simple PWM driver. 160/// Simple PWM driver.
55pub struct SimplePwm<'d, T: GeneralInstance4Channel> { 161pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
56 inner: Timer<'d, T>, 162 inner: Timer<'d, T>,
@@ -89,19 +195,76 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
89 this 195 this
90 } 196 }
91 197
92 /// Enable the given channel. 198 /// Get a single channel
93 pub fn enable(&mut self, channel: Channel) { 199 ///
94 self.inner.enable_channel(channel, true); 200 /// If you need to use multiple channels, use [`Self::split`].
201 pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> {
202 SimplePwmChannel {
203 timer: unsafe { self.inner.clone_unchecked() },
204 channel,
205 }
95 } 206 }
96 207
97 /// Disable the given channel. 208 /// Channel 1
98 pub fn disable(&mut self, channel: Channel) { 209 ///
99 self.inner.enable_channel(channel, false); 210 /// This is just a convenience wrapper around [`Self::channel`].
211 ///
212 /// If you need to use multiple channels, use [`Self::split`].
213 pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> {
214 self.channel(Channel::Ch1)
100 } 215 }
101 216
102 /// Check whether given channel is enabled 217 /// Channel 2
103 pub fn is_enabled(&self, channel: Channel) -> bool { 218 ///
104 self.inner.get_channel_enable_state(channel) 219 /// This is just a convenience wrapper around [`Self::channel`].
220 ///
221 /// If you need to use multiple channels, use [`Self::split`].
222 pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> {
223 self.channel(Channel::Ch2)
224 }
225
226 /// Channel 3
227 ///
228 /// This is just a convenience wrapper around [`Self::channel`].
229 ///
230 /// If you need to use multiple channels, use [`Self::split`].
231 pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> {
232 self.channel(Channel::Ch3)
233 }
234
235 /// Channel 4
236 ///
237 /// This is just a convenience wrapper around [`Self::channel`].
238 ///
239 /// If you need to use multiple channels, use [`Self::split`].
240 pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> {
241 self.channel(Channel::Ch4)
242 }
243
244 /// Splits a [`SimplePwm`] into four pwm channels.
245 ///
246 /// This returns all four channels, including channels that
247 /// aren't configured with a [`PwmPin`].
248 // TODO: I hate the name "split"
249 pub fn split(self) -> SimplePwmChannels<'static, T>
250 where
251 // must be static because the timer will never be dropped/disabled
252 'd: 'static,
253 {
254 // without this, the timer would be disabled at the end of this function
255 let timer = ManuallyDrop::new(self.inner);
256
257 let ch = |channel| SimplePwmChannel {
258 timer: unsafe { timer.clone_unchecked() },
259 channel,
260 };
261
262 SimplePwmChannels {
263 ch1: ch(Channel::Ch1),
264 ch2: ch(Channel::Ch2),
265 ch3: ch(Channel::Ch3),
266 ch4: ch(Channel::Ch4),
267 }
105 } 268 }
106 269
107 /// Set PWM frequency. 270 /// Set PWM frequency.
@@ -109,6 +272,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
109 /// Note: when you call this, the max duty value changes, so you will have to 272 /// Note: when you call this, the max duty value changes, so you will have to
110 /// call `set_duty` on all channels with the duty calculated based on the new max duty. 273 /// call `set_duty` on all channels with the duty calculated based on the new max duty.
111 pub fn set_frequency(&mut self, freq: Hertz) { 274 pub fn set_frequency(&mut self, freq: Hertz) {
275 // TODO: prevent ARR = u16::MAX?
112 let multiplier = if self.inner.get_counting_mode().is_center_aligned() { 276 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
113 2u8 277 2u8
114 } else { 278 } else {
@@ -120,33 +284,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
120 /// Get max duty value. 284 /// Get max duty value.
121 /// 285 ///
122 /// This value depends on the configured frequency and the timer's clock rate from RCC. 286 /// This value depends on the configured frequency and the timer's clock rate from RCC.
123 pub fn get_max_duty(&self) -> u32 { 287 pub fn max_duty_cycle(&self) -> u16 {
124 self.inner.get_max_compare_value() + 1 288 let max = self.inner.get_max_compare_value();
125 } 289 assert!(max < u16::MAX as u32);
126 290 max as u16 + 1
127 /// Set the duty for a given channel.
128 ///
129 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
130 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
131 assert!(duty <= self.get_max_duty());
132 self.inner.set_compare_value(channel, duty)
133 }
134
135 /// Get the duty for a given channel.
136 ///
137 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
138 pub fn get_duty(&self, channel: Channel) -> u32 {
139 self.inner.get_compare_value(channel)
140 }
141
142 /// Set the output polarity for a given channel.
143 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
144 self.inner.set_output_polarity(channel, polarity);
145 }
146
147 /// Set the output compare mode for a given channel.
148 pub fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
149 self.inner.set_output_compare_mode(channel, mode);
150 } 291 }
151 292
152 /// Generate a sequence of PWM waveform 293 /// Generate a sequence of PWM waveform
@@ -164,8 +305,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
164 #[allow(clippy::let_unit_value)] // eg. stm32f334 305 #[allow(clippy::let_unit_value)] // eg. stm32f334
165 let req = dma.request(); 306 let req = dma.request();
166 307
167 let original_duty_state = self.get_duty(channel); 308 let original_duty_state = self.channel(channel).current_duty_cycle();
168 let original_enable_state = self.is_enabled(channel); 309 let original_enable_state = self.channel(channel).is_enabled();
169 let original_update_dma_state = self.inner.get_update_dma_state(); 310 let original_update_dma_state = self.inner.get_update_dma_state();
170 311
171 if !original_update_dma_state { 312 if !original_update_dma_state {
@@ -173,7 +314,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
173 } 314 }
174 315
175 if !original_enable_state { 316 if !original_enable_state {
176 self.enable(channel); 317 self.channel(channel).enable();
177 } 318 }
178 319
179 unsafe { 320 unsafe {
@@ -201,10 +342,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
201 342
202 // restore output compare state 343 // restore output compare state
203 if !original_enable_state { 344 if !original_enable_state {
204 self.disable(channel); 345 self.channel(channel).disable();
205 } 346 }
206 347
207 self.set_duty(channel, original_duty_state); 348 self.channel(channel).set_duty_cycle(original_duty_state);
208 349
209 // Since DMA is closed before timer update event trigger DMA is turn off, 350 // Since DMA is closed before timer update event trigger DMA is turn off,
210 // this can almost always trigger a DMA FIFO error. 351 // this can almost always trigger a DMA FIFO error.
@@ -234,8 +375,8 @@ macro_rules! impl_waveform_chx {
234 375
235 let cc_channel = Channel::$cc_ch; 376 let cc_channel = Channel::$cc_ch;
236 377
237 let original_duty_state = self.get_duty(cc_channel); 378 let original_duty_state = self.channel(cc_channel).current_duty_cycle();
238 let original_enable_state = self.is_enabled(cc_channel); 379 let original_enable_state = self.channel(cc_channel).is_enabled();
239 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ONUPDATE; 380 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ONUPDATE;
240 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); 381 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
241 382
@@ -249,7 +390,7 @@ macro_rules! impl_waveform_chx {
249 } 390 }
250 391
251 if !original_enable_state { 392 if !original_enable_state {
252 self.enable(cc_channel); 393 self.channel(cc_channel).enable();
253 } 394 }
254 395
255 unsafe { 396 unsafe {
@@ -277,10 +418,10 @@ macro_rules! impl_waveform_chx {
277 418
278 // restore output compare state 419 // restore output compare state
279 if !original_enable_state { 420 if !original_enable_state {
280 self.disable(cc_channel); 421 self.channel(cc_channel).disable();
281 } 422 }
282 423
283 self.set_duty(cc_channel, original_duty_state); 424 self.channel(cc_channel).set_duty_cycle(original_duty_state);
284 425
285 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, 426 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
286 // this can almost always trigger a DMA FIFO error. 427 // this can almost always trigger a DMA FIFO error.
@@ -304,6 +445,41 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2);
304impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); 445impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
305impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); 446impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
306 447
448impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
449 type Error = core::convert::Infallible;
450}
451
452impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for SimplePwmChannel<'d, T> {
453 fn max_duty_cycle(&self) -> u16 {
454 self.max_duty_cycle()
455 }
456
457 fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
458 self.set_duty_cycle(duty);
459 Ok(())
460 }
461
462 fn set_duty_cycle_fully_off(&mut self) -> Result<(), Self::Error> {
463 self.set_duty_cycle_fully_off();
464 Ok(())
465 }
466
467 fn set_duty_cycle_fully_on(&mut self) -> Result<(), Self::Error> {
468 self.set_duty_cycle_fully_on();
469 Ok(())
470 }
471
472 fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) -> Result<(), Self::Error> {
473 self.set_duty_cycle_fraction(num, denom);
474 Ok(())
475 }
476
477 fn set_duty_cycle_percent(&mut self, percent: u8) -> Result<(), Self::Error> {
478 self.set_duty_cycle_percent(percent);
479 Ok(())
480 }
481}
482
307impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { 483impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
308 type Channel = Channel; 484 type Channel = Channel;
309 type Time = Hertz; 485 type Time = Hertz;
@@ -330,7 +506,7 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
330 } 506 }
331 507
332 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { 508 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
333 assert!(duty <= self.get_max_duty()); 509 assert!(duty <= self.max_duty_cycle() as u32);
334 self.inner.set_compare_value(channel, duty) 510 self.inner.set_compare_value(channel, duty)
335 } 511 }
336 512
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index 8844a9f0e..04811162b 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -6,7 +6,6 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::OutputType; 6use embassy_stm32::gpio::OutputType;
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 8use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
9use embassy_stm32::timer::Channel;
10use embassy_time::Timer; 9use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
@@ -15,22 +14,22 @@ async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
16 info!("Hello World!"); 15 info!("Hello World!");
17 16
18 let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull); 17 let ch1_pin = PwmPin::new_ch1(p.PE9, OutputType::PushPull);
19 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10), Default::default()); 18 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default());
20 let max = pwm.get_max_duty(); 19 let mut ch1 = pwm.ch1();
21 pwm.enable(Channel::Ch1); 20 ch1.enable();
22 21
23 info!("PWM initialized"); 22 info!("PWM initialized");
24 info!("PWM max duty {}", max); 23 info!("PWM max duty {}", ch1.max_duty_cycle());
25 24
26 loop { 25 loop {
27 pwm.set_duty(Channel::Ch1, 0); 26 ch1.set_duty_cycle_fully_off();
28 Timer::after_millis(300).await; 27 Timer::after_millis(300).await;
29 pwm.set_duty(Channel::Ch1, max / 4); 28 ch1.set_duty_cycle_fraction(1, 4);
30 Timer::after_millis(300).await; 29 Timer::after_millis(300).await;
31 pwm.set_duty(Channel::Ch1, max / 2); 30 ch1.set_duty_cycle_fraction(1, 2);
32 Timer::after_millis(300).await; 31 Timer::after_millis(300).await;
33 pwm.set_duty(Channel::Ch1, max - 1); 32 ch1.set_duty_cycle(ch1.max_duty_cycle() - 1);
34 Timer::after_millis(300).await; 33 Timer::after_millis(300).await;
35 } 34 }
36} 35}
diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs
index cbaff75fc..3ab93d6e0 100644
--- a/examples/stm32f4/src/bin/ws2812_pwm.rs
+++ b/examples/stm32f4/src/bin/ws2812_pwm.rs
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 // construct ws2812 non-return-to-zero (NRZ) code bit by bit 61 // construct ws2812 non-return-to-zero (NRZ) code bit by bit
62 // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low 62 // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low
63 63
64 let max_duty = ws2812_pwm.get_max_duty() as u16; 64 let max_duty = ws2812_pwm.max_duty_cycle();
65 let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing 65 let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing
66 let n1 = 2 * n0; // ws2812 Bit 1 high level timing 66 let n1 = 2 * n0; // ws2812 Bit 1 high level timing
67 67
@@ -84,7 +84,7 @@ async fn main(_spawner: Spawner) {
84 let pwm_channel = Channel::Ch1; 84 let pwm_channel = Channel::Ch1;
85 85
86 // make sure PWM output keep low on first start 86 // make sure PWM output keep low on first start
87 ws2812_pwm.set_duty(pwm_channel, 0); 87 ws2812_pwm.channel(pwm_channel).set_duty_cycle(0);
88 88
89 // flip color at 2 Hz 89 // flip color at 2 Hz
90 let mut ticker = Ticker::every(Duration::from_millis(500)); 90 let mut ticker = Ticker::every(Duration::from_millis(500));
diff --git a/examples/stm32g0/src/bin/input_capture.rs b/examples/stm32g0/src/bin/input_capture.rs
index 69fdae96d..bc814cb13 100644
--- a/examples/stm32g0/src/bin/input_capture.rs
+++ b/examples/stm32g0/src/bin/input_capture.rs
@@ -47,10 +47,10 @@ async fn main(spawner: Spawner) {
47 unwrap!(spawner.spawn(blinky(p.PB1))); 47 unwrap!(spawner.spawn(blinky(p.PB1)));
48 48
49 // Connect PB1 and PA8 with a 1k Ohm resistor 49 // Connect PB1 and PA8 with a 1k Ohm resistor
50 let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); 50 let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
51 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(1), Default::default()); 51 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default());
52 pwm.enable(Channel::Ch1); 52 pwm.ch1().enable();
53 pwm.set_duty(Channel::Ch1, 50); 53 pwm.ch1().set_duty_cycle(50);
54 54
55 let ch1 = CapturePin::new_ch1(p.PA0, Pull::None); 55 let ch1 = CapturePin::new_ch1(p.PA0, Pull::None);
56 let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default()); 56 let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default());
diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs
index 152ecda86..db9cf4f8a 100644
--- a/examples/stm32g0/src/bin/pwm_input.rs
+++ b/examples/stm32g0/src/bin/pwm_input.rs
@@ -14,7 +14,6 @@ use embassy_stm32::gpio::{Level, Output, OutputType, Pull, Speed};
14use embassy_stm32::time::khz; 14use embassy_stm32::time::khz;
15use embassy_stm32::timer::pwm_input::PwmInput; 15use embassy_stm32::timer::pwm_input::PwmInput;
16use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 16use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
17use embassy_stm32::timer::Channel;
18use embassy_stm32::{bind_interrupts, peripherals, timer}; 17use embassy_stm32::{bind_interrupts, peripherals, timer};
19use embassy_time::Timer; 18use embassy_time::Timer;
20use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
@@ -43,11 +42,10 @@ async fn main(spawner: Spawner) {
43 42
44 unwrap!(spawner.spawn(blinky(p.PB1))); 43 unwrap!(spawner.spawn(blinky(p.PB1)));
45 // Connect PA8 and PA6 with a 1k Ohm resistor 44 // Connect PA8 and PA6 with a 1k Ohm resistor
46 let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); 45 let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
47 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(1), Default::default()); 46 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default());
48 let max = pwm.get_max_duty(); 47 pwm.ch1().set_duty_cycle_fraction(1, 4);
49 pwm.set_duty(Channel::Ch1, max / 4); 48 pwm.ch1().enable();
50 pwm.enable(Channel::Ch1);
51 49
52 let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(1000)); 50 let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(1000));
53 pwm_input.enable(); 51 pwm_input.enable();
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index d4809a481..6c965012c 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -6,7 +6,6 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::OutputType; 6use embassy_stm32::gpio::OutputType;
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 8use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
9use embassy_stm32::timer::Channel;
10use embassy_time::Timer; 9use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
@@ -15,22 +14,22 @@ async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
16 info!("Hello World!"); 15 info!("Hello World!");
17 16
18 let ch1 = PwmPin::new_ch1(p.PC0, OutputType::PushPull); 17 let ch1_pin = PwmPin::new_ch1(p.PC0, OutputType::PushPull);
19 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10), Default::default()); 18 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default());
20 let max = pwm.get_max_duty(); 19 let mut ch1 = pwm.ch1();
21 pwm.enable(Channel::Ch1); 20 ch1.enable();
22 21
23 info!("PWM initialized"); 22 info!("PWM initialized");
24 info!("PWM max duty {}", max); 23 info!("PWM max duty {}", ch1.max_duty_cycle());
25 24
26 loop { 25 loop {
27 pwm.set_duty(Channel::Ch1, 0); 26 ch1.set_duty_cycle_fully_off();
28 Timer::after_millis(300).await; 27 Timer::after_millis(300).await;
29 pwm.set_duty(Channel::Ch1, max / 4); 28 ch1.set_duty_cycle_fraction(1, 4);
30 Timer::after_millis(300).await; 29 Timer::after_millis(300).await;
31 pwm.set_duty(Channel::Ch1, max / 2); 30 ch1.set_duty_cycle_fraction(1, 2);
32 Timer::after_millis(300).await; 31 Timer::after_millis(300).await;
33 pwm.set_duty(Channel::Ch1, max - 1); 32 ch1.set_duty_cycle(ch1.max_duty_cycle() - 1);
34 Timer::after_millis(300).await; 33 Timer::after_millis(300).await;
35 } 34 }
36} 35}
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index 1e48ba67b..a1c53fc3f 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -6,7 +6,6 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::OutputType; 6use embassy_stm32::gpio::OutputType;
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 8use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
9use embassy_stm32::timer::Channel;
10use embassy_stm32::Config; 9use embassy_stm32::Config;
11use embassy_time::Timer; 10use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
@@ -37,22 +36,22 @@ async fn main(_spawner: Spawner) {
37 let p = embassy_stm32::init(config); 36 let p = embassy_stm32::init(config);
38 info!("Hello World!"); 37 info!("Hello World!");
39 38
40 let ch1 = PwmPin::new_ch1(p.PA6, OutputType::PushPull); 39 let ch1_pin = PwmPin::new_ch1(p.PA6, OutputType::PushPull);
41 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1), None, None, None, khz(10), Default::default()); 40 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default());
42 let max = pwm.get_max_duty(); 41 let mut ch1 = pwm.ch1();
43 pwm.enable(Channel::Ch1); 42 ch1.enable();
44 43
45 info!("PWM initialized"); 44 info!("PWM initialized");
46 info!("PWM max duty {}", max); 45 info!("PWM max duty {}", ch1.max_duty_cycle());
47 46
48 loop { 47 loop {
49 pwm.set_duty(Channel::Ch1, 0); 48 ch1.set_duty_cycle_fully_off();
50 Timer::after_millis(300).await; 49 Timer::after_millis(300).await;
51 pwm.set_duty(Channel::Ch1, max / 4); 50 ch1.set_duty_cycle_fraction(1, 4);
52 Timer::after_millis(300).await; 51 Timer::after_millis(300).await;
53 pwm.set_duty(Channel::Ch1, max / 2); 52 ch1.set_duty_cycle_fraction(1, 2);
54 Timer::after_millis(300).await; 53 Timer::after_millis(300).await;
55 pwm.set_duty(Channel::Ch1, max - 1); 54 ch1.set_duty_cycle(ch1.max_duty_cycle() - 1);
56 Timer::after_millis(300).await; 55 Timer::after_millis(300).await;
57 } 56 }
58} 57}