aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer/complementary_pwm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/timer/complementary_pwm.rs')
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs33
1 files changed, 27 insertions, 6 deletions
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 6654366cd..71d7110b5 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -1,3 +1,5 @@
1//! PWM driver with complementary output support.
2
1use core::marker::PhantomData; 3use core::marker::PhantomData;
2 4
3use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
@@ -11,15 +13,19 @@ use crate::gpio::{AnyPin, OutputType};
11use crate::time::Hertz; 13use crate::time::Hertz;
12use crate::Peripheral; 14use crate::Peripheral;
13 15
14pub struct ComplementaryPwmPin<'d, Perip, Channel> { 16/// Complementary PWM pin wrapper.
17///
18/// This wraps a pin to make it usable with PWM.
19pub struct ComplementaryPwmPin<'d, T, C> {
15 _pin: PeripheralRef<'d, AnyPin>, 20 _pin: PeripheralRef<'d, AnyPin>,
16 phantom: PhantomData<(Perip, Channel)>, 21 phantom: PhantomData<(T, C)>,
17} 22}
18 23
19macro_rules! complementary_channel_impl { 24macro_rules! complementary_channel_impl {
20 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 25 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
21 impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { 26 impl<'d, T: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> {
22 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self { 27 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
28 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
23 into_ref!(pin); 29 into_ref!(pin);
24 critical_section::with(|_| { 30 critical_section::with(|_| {
25 pin.set_low(); 31 pin.set_low();
@@ -41,11 +47,13 @@ complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
41complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin); 47complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
42complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); 48complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
43 49
50/// PWM driver with support for standard and complementary outputs.
44pub struct ComplementaryPwm<'d, T> { 51pub struct ComplementaryPwm<'d, T> {
45 inner: PeripheralRef<'d, T>, 52 inner: PeripheralRef<'d, T>,
46} 53}
47 54
48impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { 55impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
56 /// Create a new complementary PWM driver.
49 pub fn new( 57 pub fn new(
50 tim: impl Peripheral<P = T> + 'd, 58 tim: impl Peripheral<P = T> + 'd,
51 _ch1: Option<PwmPin<'d, T, Ch1>>, 59 _ch1: Option<PwmPin<'d, T, Ch1>>,
@@ -70,7 +78,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
70 let mut this = Self { inner: tim }; 78 let mut this = Self { inner: tim };
71 79
72 this.inner.set_counting_mode(counting_mode); 80 this.inner.set_counting_mode(counting_mode);
73 this.set_freq(freq); 81 this.set_frequency(freq);
74 this.inner.start(); 82 this.inner.start();
75 83
76 this.inner.enable_outputs(); 84 this.inner.enable_outputs();
@@ -86,17 +94,23 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
86 this 94 this
87 } 95 }
88 96
97 /// Enable the given channel.
89 pub fn enable(&mut self, channel: Channel) { 98 pub fn enable(&mut self, channel: Channel) {
90 self.inner.enable_channel(channel, true); 99 self.inner.enable_channel(channel, true);
91 self.inner.enable_complementary_channel(channel, true); 100 self.inner.enable_complementary_channel(channel, true);
92 } 101 }
93 102
103 /// Disable the given channel.
94 pub fn disable(&mut self, channel: Channel) { 104 pub fn disable(&mut self, channel: Channel) {
95 self.inner.enable_complementary_channel(channel, false); 105 self.inner.enable_complementary_channel(channel, false);
96 self.inner.enable_channel(channel, false); 106 self.inner.enable_channel(channel, false);
97 } 107 }
98 108
99 pub fn set_freq(&mut self, freq: Hertz) { 109 /// Set PWM frequency.
110 ///
111 /// Note: when you call this, the max duty value changes, so you will have to
112 /// call `set_duty` on all channels with the duty calculated based on the new max duty.
113 pub fn set_frequency(&mut self, freq: Hertz) {
100 let multiplier = if self.inner.get_counting_mode().is_center_aligned() { 114 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
101 2u8 115 2u8
102 } else { 116 } else {
@@ -105,15 +119,22 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
105 self.inner.set_frequency(freq * multiplier); 119 self.inner.set_frequency(freq * multiplier);
106 } 120 }
107 121
122 /// Get max duty value.
123 ///
124 /// This value depends on the configured frequency and the timer's clock rate from RCC.
108 pub fn get_max_duty(&self) -> u16 { 125 pub fn get_max_duty(&self) -> u16 {
109 self.inner.get_max_compare_value() + 1 126 self.inner.get_max_compare_value() + 1
110 } 127 }
111 128
129 /// Set the duty for a given channel.
130 ///
131 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
112 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 132 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
113 assert!(duty <= self.get_max_duty()); 133 assert!(duty <= self.get_max_duty());
114 self.inner.set_compare_value(channel, duty) 134 self.inner.set_compare_value(channel, duty)
115 } 135 }
116 136
137 /// Set the output polarity for a given channel.
117 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 138 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
118 self.inner.set_output_polarity(channel, polarity); 139 self.inner.set_output_polarity(channel, polarity);
119 self.inner.set_complementary_output_polarity(channel, polarity); 140 self.inner.set_complementary_output_polarity(channel, polarity);