aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer
diff options
context:
space:
mode:
authorGrant Miller <[email protected]>2024-09-06 09:07:29 -0500
committerGrant Miller <[email protected]>2024-09-06 09:09:09 -0500
commit8ac758bdee793496f842f4c267bda2b6f935a0bb (patch)
treebe541273a16858367c34f047e5c79637df4b6aeb /embassy-stm32/src/timer
parent1cf778904d597a5bc01a4b7862f965681636faf1 (diff)
embassy-stm32: Add SimplePwmChannel
Diffstat (limited to 'embassy-stm32/src/timer')
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs112
1 files changed, 112 insertions, 0 deletions
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index b7771bd64..f94ed1be5 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -51,6 +51,96 @@ channel_impl!(new_ch2, Ch2, Channel2Pin);
51channel_impl!(new_ch3, Ch3, Channel3Pin); 51channel_impl!(new_ch3, Ch3, Channel3Pin);
52channel_impl!(new_ch4, Ch4, Channel4Pin); 52channel_impl!(new_ch4, Ch4, Channel4Pin);
53 53
54/// A single channel of a pwm, obtained from [`SimplePwm::split`].
55///
56/// It is not possible to change the pwm frequency because
57/// the frequency configuration is shared with all four channels.
58pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> {
59 timer: &'d Timer<'d, T>,
60 channel: Channel,
61}
62
63// TODO: check for RMW races
64impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> {
65 /// Enable the given channel.
66 pub fn enable(&mut self) {
67 self.timer.enable_channel(self.channel, true);
68 }
69
70 /// Disable the given channel.
71 pub fn disable(&mut self) {
72 self.timer.enable_channel(self.channel, false);
73 }
74
75 /// Check whether given channel is enabled
76 pub fn is_enabled(&self) -> bool {
77 self.timer.get_channel_enable_state(self.channel)
78 }
79
80 /// Get max duty value.
81 ///
82 /// This value depends on the configured frequency and the timer's clock rate from RCC.
83 pub fn get_max_duty(&self) -> u32 {
84 self.timer.get_max_compare_value() + 1
85 }
86
87 /// Set the duty for a given channel.
88 ///
89 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
90 pub fn set_duty(&mut self, duty: u32) {
91 assert!(duty <= self.get_max_duty());
92 self.timer.set_compare_value(self.channel, duty)
93 }
94
95 /// Get the duty for a given channel.
96 ///
97 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
98 pub fn get_duty(&self) -> u32 {
99 self.timer.get_compare_value(self.channel)
100 }
101
102 /// Set the output polarity for a given channel.
103 pub fn set_polarity(&mut self, polarity: OutputPolarity) {
104 self.timer.set_output_polarity(self.channel, polarity);
105 }
106
107 /// Set the output compare mode for a given channel.
108 pub fn set_output_compare_mode(&mut self, mode: OutputCompareMode) {
109 self.timer.set_output_compare_mode(self.channel, mode);
110 }
111}
112
113/// A group of four [`SimplePwmChannel`]s, obtained from [`SimplePwm::split`].
114pub struct SimplePwmChannels<'d, T: GeneralInstance4Channel> {
115 /// Channel 1
116 pub ch1: SimplePwmChannel<'d, T>,
117 /// Channel 2
118 pub ch2: SimplePwmChannel<'d, T>,
119 /// Channel 3
120 pub ch3: SimplePwmChannel<'d, T>,
121 /// Channel 4
122 pub ch4: SimplePwmChannel<'d, T>,
123}
124
125impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
126 type Error = core::convert::Infallible;
127}
128
129impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for SimplePwmChannel<'d, T> {
130 fn max_duty_cycle(&self) -> u16 {
131 // TODO: panics if CCR is 0xFFFF
132 // TODO: rename get_max_duty to max_duty_cycle
133 unwrap!(self.get_max_duty().try_into())
134 }
135
136 fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
137 self.set_duty(duty.into());
138 Ok(())
139 }
140
141 // TODO: default methods?
142}
143
54/// Simple PWM driver. 144/// Simple PWM driver.
55pub struct SimplePwm<'d, T: GeneralInstance4Channel> { 145pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
56 inner: Timer<'d, T>, 146 inner: Timer<'d, T>,
@@ -89,6 +179,28 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
89 this 179 this
90 } 180 }
91 181
182 fn channel(&self, channel: Channel) -> SimplePwmChannel<'_, T> {
183 SimplePwmChannel {
184 timer: &self.inner,
185 channel,
186 }
187 }
188
189 /// Splits a [`SimplePwm`] into four pwm channels.
190 ///
191 /// This returns all four channels, including channels that
192 /// aren't configured with a [`PwmPin`].
193 // TODO: I hate the name "split"
194 pub fn split(&mut self) -> SimplePwmChannels<'_, T> {
195 // TODO: pre-enable channels?
196 SimplePwmChannels {
197 ch1: self.channel(Channel::Ch1),
198 ch2: self.channel(Channel::Ch2),
199 ch3: self.channel(Channel::Ch3),
200 ch4: self.channel(Channel::Ch4),
201 }
202 }
203
92 /// Enable the given channel. 204 /// Enable the given channel.
93 pub fn enable(&mut self, channel: Channel) { 205 pub fn enable(&mut self, channel: Channel) {
94 self.inner.enable_channel(channel, true); 206 self.inner.enable_channel(channel, true);