Skip to content

Commit 9d2dfdd

Browse files
committed
Add custom timer
1 parent 052a182 commit 9d2dfdd

File tree

2 files changed

+269
-0
lines changed

2 files changed

+269
-0
lines changed
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
use core::u16;
2+
3+
use embassy_hal_internal::Peri;
4+
use stm32_metapac::timer::vals::FilterValue;
5+
6+
use crate::{
7+
dac::Ch2,
8+
timer::{
9+
Ch1, Ch3, Ch4, CoreInstance, GeneralInstance1Channel, GeneralInstance2Channel, GeneralInstance4Channel,
10+
TimerPin,
11+
low_level::{CountingMode, OutputCompareMode, Timer},
12+
simple_pwm::PwmPin,
13+
},
14+
};
15+
16+
mod ch_mode {
17+
use crate::timer::{Channel, low_level::InputTISelection};
18+
19+
use super::*;
20+
21+
pub trait Mode<T: CoreInstance> {
22+
fn init(self, channel: Channel, tim: &mut Timer<'_, T>);
23+
}
24+
25+
pub struct Unused;
26+
pub struct Input(pub(crate) FilterValue);
27+
pub struct Output(pub(crate) OutputCompareMode);
28+
29+
impl<T: CoreInstance> Mode<T> for Unused {
30+
fn init(self, _channel: Channel, _tim: &mut Timer<'_, T>) {}
31+
}
32+
33+
impl<T: GeneralInstance4Channel> Mode<T> for Input {
34+
fn init(self, channel: Channel, tim: &mut Timer<'_, T>) {
35+
tim.set_input_ti_selection(channel, InputTISelection::Normal);
36+
tim.set_input_capture_filter(channel, self.0);
37+
}
38+
}
39+
40+
impl<T: GeneralInstance1Channel> Mode<T> for Output {
41+
fn init(self, channel: Channel, tim: &mut Timer<'_, T>) {
42+
tim.set_output_compare_mode(channel, self.0);
43+
}
44+
}
45+
}
46+
47+
/// Used to construct a [CustomPwm]
48+
pub struct CustomPwmBuilder<
49+
'd,
50+
T: CoreInstance,
51+
CH1: ch_mode::Mode<T>,
52+
CH2: ch_mode::Mode<T>,
53+
CH3: ch_mode::Mode<T>,
54+
CH4: ch_mode::Mode<T>,
55+
> {
56+
tim: Peri<'d, T>,
57+
ch1: CH1,
58+
ch2: CH2,
59+
ch3: CH3,
60+
ch4: CH4,
61+
62+
counting_mode: CountingMode,
63+
arr: u32,
64+
psc: u16,
65+
}
66+
67+
impl<'d, T: CoreInstance> CustomPwmBuilder<'d, T, ch_mode::Unused, ch_mode::Unused, ch_mode::Unused, ch_mode::Unused> {
68+
/// Construct a [CustomPwmBuilder] which can be used to construct a [CustomPwm]
69+
pub fn new(tim: Peri<'d, T>) -> Self {
70+
Self {
71+
tim,
72+
ch1: ch_mode::Unused,
73+
ch2: ch_mode::Unused,
74+
ch3: ch_mode::Unused,
75+
ch4: ch_mode::Unused,
76+
77+
counting_mode: CountingMode::EdgeAlignedUp,
78+
arr: u32::MAX,
79+
psc: 0,
80+
}
81+
}
82+
83+
// TODO allow u32 too?
84+
pub fn period(mut self, arr: u16) -> Self {
85+
self.arr = arr as u32;
86+
self
87+
}
88+
89+
pub fn prescaler(mut self, psc: u16) -> Self {
90+
self.psc = psc;
91+
self
92+
}
93+
}
94+
95+
impl<'d, T: GeneralInstance1Channel, CH2: ch_mode::Mode<T>, CH3: ch_mode::Mode<T>, CH4: ch_mode::Mode<T>>
96+
CustomPwmBuilder<'d, T, ch_mode::Unused, CH2, CH3, CH4>
97+
{
98+
pub fn ch1<#[cfg(afio)] A>(
99+
self,
100+
_pin: if_afio!(PwmPin<'d, T, Ch1, A>),
101+
mode: OutputCompareMode,
102+
) -> CustomPwmBuilder<'d, T, ch_mode::Output, CH2, CH3, CH4> {
103+
let CustomPwmBuilder {
104+
tim,
105+
ch1: _,
106+
ch2,
107+
ch3,
108+
ch4,
109+
counting_mode,
110+
arr,
111+
psc,
112+
} = self;
113+
CustomPwmBuilder {
114+
tim,
115+
ch1: ch_mode::Output(mode),
116+
ch2,
117+
ch3,
118+
ch4,
119+
counting_mode,
120+
arr,
121+
psc,
122+
}
123+
}
124+
}
125+
126+
impl<'d, T: GeneralInstance2Channel, CH1: ch_mode::Mode<T>, CH3: ch_mode::Mode<T>, CH4: ch_mode::Mode<T>>
127+
CustomPwmBuilder<'d, T, CH1, ch_mode::Unused, CH3, CH4>
128+
{
129+
pub fn ch2<#[cfg(afio)] A>(
130+
self,
131+
_pin: if_afio!(PwmPin<'d, T, Ch2, A>),
132+
mode: OutputCompareMode,
133+
) -> CustomPwmBuilder<'d, T, CH1, ch_mode::Output, CH3, CH4> {
134+
let CustomPwmBuilder {
135+
tim,
136+
ch1,
137+
ch2: _,
138+
ch3,
139+
ch4,
140+
counting_mode,
141+
arr,
142+
psc,
143+
} = self;
144+
CustomPwmBuilder {
145+
tim,
146+
ch1,
147+
ch2: ch_mode::Output(mode),
148+
ch3,
149+
ch4,
150+
counting_mode,
151+
arr,
152+
psc,
153+
}
154+
}
155+
}
156+
157+
impl<'d, T: GeneralInstance4Channel, CH1: ch_mode::Mode<T>, CH2: ch_mode::Mode<T>, CH4: ch_mode::Mode<T>>
158+
CustomPwmBuilder<'d, T, CH1, CH2, ch_mode::Unused, CH4>
159+
{
160+
pub fn ch3<#[cfg(afio)] A>(
161+
self,
162+
_pin: if_afio!(PwmPin<'d, T, Ch3, A>),
163+
mode: OutputCompareMode,
164+
) -> CustomPwmBuilder<'d, T, CH1, CH2, ch_mode::Output, CH4> {
165+
let CustomPwmBuilder {
166+
tim,
167+
ch1,
168+
ch2,
169+
ch3: _,
170+
ch4,
171+
counting_mode,
172+
arr,
173+
psc,
174+
} = self;
175+
CustomPwmBuilder {
176+
tim,
177+
ch1,
178+
ch2,
179+
ch3: ch_mode::Output(mode),
180+
ch4,
181+
counting_mode,
182+
arr,
183+
psc,
184+
}
185+
}
186+
}
187+
188+
impl<'d, T: GeneralInstance4Channel, CH1: ch_mode::Mode<T>, CH2: ch_mode::Mode<T>, CH3: ch_mode::Mode<T>>
189+
CustomPwmBuilder<'d, T, CH1, CH2, CH3, ch_mode::Unused>
190+
{
191+
pub fn ch4<#[cfg(afio)] A>(
192+
self,
193+
_pin: if_afio!(PwmPin<'d, T, Ch4, A>),
194+
mode: OutputCompareMode,
195+
) -> CustomPwmBuilder<'d, T, CH1, CH2, CH3, ch_mode::Output> {
196+
let CustomPwmBuilder {
197+
tim,
198+
ch1,
199+
ch2,
200+
ch3,
201+
ch4: _,
202+
counting_mode,
203+
arr,
204+
psc,
205+
} = self;
206+
CustomPwmBuilder {
207+
tim,
208+
ch1,
209+
ch2,
210+
ch3,
211+
ch4: ch_mode::Output(mode),
212+
counting_mode,
213+
arr,
214+
psc,
215+
}
216+
}
217+
218+
pub fn ch4_input<C, #[cfg(afio)] A>(
219+
self,
220+
_pin: if_afio!(impl TimerPin<T, Ch4, A>),
221+
filter: FilterValue,
222+
) -> CustomPwmBuilder<'d, T, CH1, CH2, CH3, ch_mode::Input> {
223+
let CustomPwmBuilder {
224+
tim,
225+
ch1,
226+
ch2,
227+
ch3,
228+
ch4: _,
229+
counting_mode,
230+
arr,
231+
psc,
232+
} = self;
233+
CustomPwmBuilder {
234+
tim,
235+
ch1,
236+
ch2,
237+
ch3,
238+
ch4: ch_mode::Input(filter),
239+
counting_mode,
240+
arr,
241+
psc,
242+
}
243+
}
244+
}
245+
246+
impl<'d, T: GeneralInstance1Channel, CH1: ch_mode::Mode<T>, CH2: ch_mode::Mode<T>, CH3: ch_mode::Mode<T>>
247+
CustomPwmBuilder<'d, T, CH1, CH2, CH3, ch_mode::Unused>
248+
{
249+
pub fn finalize(self) -> CustomPwm<'d, T> {
250+
use ch_mode::Mode;
251+
let mut inner = Timer::new(self.tim);
252+
253+
self.ch1.init(super::Channel::Ch1, &mut inner);
254+
self.ch2.init(super::Channel::Ch2, &mut inner);
255+
self.ch3.init(super::Channel::Ch3, &mut inner);
256+
self.ch4.init(super::Channel::Ch4, &mut inner);
257+
258+
//inner.set_counting_mode(self.counting_mode);
259+
inner.set_max_compare_value(self.arr);
260+
inner.set_prescaler(self.psc);
261+
262+
CustomPwm { inner }
263+
}
264+
}
265+
266+
pub struct CustomPwm<'d, T: CoreInstance> {
267+
inner: Timer<'d, T>,
268+
}

embassy-stm32/src/timer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use embassy_sync::waitqueue::AtomicWaker;
77

88
#[cfg(not(stm32l0))]
99
pub mod complementary_pwm;
10+
pub mod custom_timer;
1011
pub mod input_capture;
1112
pub mod low_level;
1213
pub mod one_pulse;

0 commit comments

Comments
 (0)