1use crate::pac::{OCMP1, OCMP2, OCMP3, OCMP4, OCMP5};
5use crate::pac::{TMR2, TMR3};
6use core::convert::Infallible;
7use embedded_hal::pwm::{ErrorType, SetDutyCycle};
8use embedded_hal_0_2::PwmPin;
9
10use core::marker::PhantomData;
11
12pub struct TimebaseUninit;
14
15pub struct Timebase16even;
17
18pub struct Timebase16odd;
20
21pub struct Timebase32;
23
24pub enum OcConfig {
26 Off,
28 RisingSlope(u32),
30
31 FallingSlope(u32),
33
34 Toggle(u32),
36
37 SinglePulse(u32, u32),
39
40 ContinuousPulses(u32, u32),
42}
43
44impl OcConfig {
45 const fn ocm_bits(&self) -> u8 {
46 match self {
47 Self::Off => 0b000,
48 Self::RisingSlope(_) => 0b001,
49 Self::FallingSlope(_) => 0b010,
50 Self::Toggle(_) => 0b011,
51 Self::SinglePulse(_, _) => 0b100,
52 Self::ContinuousPulses(_, _) => 0b101,
53 }
54 }
55}
56
57pub struct Oc<OCMP, TIMEBASE> {
59 ocmp: OCMP,
60 _timebase: PhantomData<TIMEBASE>,
61}
62
63macro_rules! oc_impl {
64 ($constructor: ident, $ocmp: ty) => {
65 impl Oc<$ocmp, TimebaseUninit> {
66 pub fn $constructor(ocmp: $ocmp, stop_in_idle_mode: bool) -> Self {
67 ocmp.cont
68 .write(|w| w.on().clear_bit().sidl().bit(stop_in_idle_mode));
69 Self {
70 ocmp,
71 _timebase: PhantomData,
72 }
73 }
74 }
75
76 impl<TIMEBASE> Oc<$ocmp, TIMEBASE> {
77 pub fn timebase16even(self) -> Oc<$ocmp, Timebase16even> {
79 self.ocmp
80 .cont
81 .modify(|_, w| w.octsel().bit(false).oc32().bit(false));
82 Oc {
83 ocmp: self.ocmp,
84 _timebase: PhantomData,
85 }
86 }
87
88 pub fn timebase16odd(self) -> Oc<$ocmp, Timebase16odd> {
90 self.ocmp
91 .cont
92 .modify(|_, w| w.octsel().bit(true).oc32().bit(false));
93 self.ocmp.contset.write(|w| w.on().set_bit());
94 Oc {
95 ocmp: self.ocmp,
96 _timebase: PhantomData,
97 }
98 }
99
100 pub fn timebase32(self) -> Oc<$ocmp, Timebase32> {
102 self.ocmp
103 .cont
104 .modify(|_, w| w.octsel().bit(false).oc32().bit(true));
105 self.ocmp.contset.write(|w| w.on().set_bit());
106 Oc {
107 ocmp: self.ocmp,
108 _timebase: PhantomData,
109 }
110 }
111
112 pub fn free(self) -> $ocmp {
114 self.ocmp.cont.write(|w| w.on().clear_bit());
115 self.ocmp
116 }
117
118 #[inline(never)] pub fn turn_off(&mut self) {
121 self.ocmp.contclr.write(|w| w.on().set_bit());
122 }
123 }
124
125 impl Oc<$ocmp, Timebase16even> {
126 pub fn turn_on(&mut self, config: OcConfig) {
127 self.ocmp
128 .cont
129 .modify(|_, w| unsafe { w.ocm().bits(config.ocm_bits()) });
130 let (r, rs) = match config {
131 OcConfig::RisingSlope(r) | OcConfig::FallingSlope(r) | OcConfig::Toggle(r) => {
132 (r, 0)
133 }
134 OcConfig::SinglePulse(r, rs) | OcConfig::ContinuousPulses(r, rs) => (r, rs),
135 OcConfig::Off => (0, 0),
136 };
137 self.ocmp.r.write(|w| unsafe { w.r().bits(r) });
138 self.ocmp.rs.write(|w| unsafe { w.rs().bits(rs) });
139 self.ocmp.contset.write(|w| w.on().set_bit());
140 }
141 }
142
143 impl Oc<$ocmp, Timebase16odd> {
144 pub fn turn_on(&mut self, config: OcConfig) {
145 self.ocmp
146 .cont
147 .modify(|_, w| unsafe { w.ocm().bits(config.ocm_bits()) });
148 let (r, rs) = match config {
149 OcConfig::RisingSlope(r) | OcConfig::FallingSlope(r) | OcConfig::Toggle(r) => {
150 (r, 0)
151 }
152 OcConfig::SinglePulse(r, rs) | OcConfig::ContinuousPulses(r, rs) => (r, rs),
153 OcConfig::Off => (0, 0),
154 };
155 self.ocmp.r.write(|w| unsafe { w.r().bits(r) });
156 self.ocmp.rs.write(|w| unsafe { w.rs().bits(rs) });
157 self.ocmp.contset.write(|w| w.on().set_bit());
158 }
159 }
160 impl Oc<$ocmp, Timebase32> {
161 pub fn turn_on(&mut self, config: OcConfig) {
162 self.ocmp
163 .cont
164 .modify(|_, w| unsafe { w.ocm().bits(config.ocm_bits()) });
165 let (r, rs) = match config {
166 OcConfig::RisingSlope(r) | OcConfig::FallingSlope(r) | OcConfig::Toggle(r) => {
167 (r, 0)
168 }
169 OcConfig::SinglePulse(r, rs) | OcConfig::ContinuousPulses(r, rs) => (r, rs),
170 OcConfig::Off => (0, 0),
171 };
172 self.ocmp.r.write(|w| unsafe { w.r().bits(r) });
173 self.ocmp.rs.write(|w| unsafe { w.rs().bits(rs) });
174 self.ocmp.contset.write(|w| w.on().set_bit());
175 }
176 }
177 };
178}
179
180oc_impl!(oc1, OCMP1);
181oc_impl!(oc2, OCMP2);
182oc_impl!(oc3, OCMP3);
183oc_impl!(oc4, OCMP4);
184oc_impl!(oc5, OCMP5);
185
186pub struct Pwm<OCMP, TIMEBASE> {
188 ocmp: OCMP,
189 _timebase: PhantomData<TIMEBASE>,
190}
191
192macro_rules! pwm_impl {
193 ($constructor: ident, $ocmp: ty, $timer_even: ty, $timer_odd: ty) => {
194 impl Pwm<$ocmp, TimebaseUninit> {
195 pub fn $constructor(
201 ocmp: $ocmp,
202 enable_fault_pin: bool,
203 stop_in_idle_mode: bool,
204 ) -> Self {
205 let ocm = match enable_fault_pin {
206 false => 0b110,
207 true => 0b111,
208 };
209 ocmp.cont
210 .write(|w| unsafe { w.sidl().bit(stop_in_idle_mode).ocm().bits(ocm) });
211 Pwm {
212 ocmp,
213 _timebase: PhantomData,
214 }
215 }
216 }
217
218 impl<TIMEBASE> Pwm<$ocmp, TIMEBASE> {
219 pub fn timebase16even(self) -> Pwm<$ocmp, Timebase16even> {
221 self.ocmp
222 .cont
223 .modify(|_, w| w.octsel().bit(false).oc32().bit(false).on().bit(true));
224 Pwm {
225 ocmp: self.ocmp,
226 _timebase: PhantomData,
227 }
228 }
229
230 pub fn timebase16odd(self) -> Pwm<$ocmp, Timebase16odd> {
232 self.ocmp
233 .cont
234 .modify(|_, w| w.octsel().bit(true).oc32().bit(false).on().bit(true));
235 self.ocmp.contset.write(|w| w.on().set_bit());
236 Pwm {
237 ocmp: self.ocmp,
238 _timebase: PhantomData,
239 }
240 }
241
242 pub fn timebase32(self) -> Pwm<$ocmp, Timebase32> {
244 self.ocmp
245 .cont
246 .modify(|_, w| w.octsel().bit(false).oc32().bit(true).on().bit(true));
247 self.ocmp.contset.write(|w| w.on().set_bit());
248 Pwm {
249 ocmp: self.ocmp,
250 _timebase: PhantomData,
251 }
252 }
253
254 pub fn fault(&self) -> bool {
258 self.ocmp.cont.read().ocflt().bit()
259 }
260
261 pub fn on(&mut self) {
265 self.ocmp.contset.write(|w| w.on().set_bit());
266 }
267
268 pub fn off(&mut self) {
270 self.ocmp.contclr.write(|w| w.on().set_bit());
271 }
272
273 pub fn free(self) -> $ocmp {
275 self.ocmp.cont.write(|w| w.on().clear_bit());
276 self.ocmp
277 }
278 }
279
280 impl PwmPin for Pwm<$ocmp, Timebase16even> {
281 type Duty = u32;
282
283 fn enable(&mut self) {
284 self.ocmp.contset.write(|w| w.on().set_bit());
285 }
286
287 fn disable(&mut self) {
288 self.ocmp.contclr.write(|w| w.on().set_bit());
289 }
290
291 fn get_duty(&self) -> Self::Duty {
292 self.ocmp.rs.read().rs().bits() as Self::Duty
293 }
294
295 fn set_duty(&mut self, duty: Self::Duty) {
296 self.ocmp.rs.write(|w| unsafe { w.rs().bits(duty) });
297 }
298
299 fn get_max_duty(&self) -> Self::Duty {
300 unsafe { (*<$timer_even>::ptr()).pr.read().pr().bits() + 1 }
301 }
302 }
303
304 impl PwmPin for Pwm<$ocmp, Timebase16odd> {
305 type Duty = u32;
306
307 fn enable(&mut self) {
308 self.ocmp.contset.write(|w| w.on().set_bit());
309 }
310
311 fn disable(&mut self) {
312 self.ocmp.contclr.write(|w| w.on().set_bit());
313 }
314
315 fn get_duty(&self) -> Self::Duty {
316 self.ocmp.rs.read().rs().bits() as Self::Duty
317 }
318
319 fn set_duty(&mut self, duty: Self::Duty) {
320 self.ocmp.rs.write(|w| unsafe { w.rs().bits(duty) });
321 }
322
323 fn get_max_duty(&self) -> Self::Duty {
324 unsafe { (*<$timer_odd>::ptr()).pr.read().pr().bits() + 1 }
325 }
326 }
327
328 impl PwmPin for Pwm<$ocmp, Timebase32> {
329 type Duty = u32;
330
331 fn enable(&mut self) {
332 self.ocmp.contset.write(|w| w.on().set_bit());
333 }
334
335 fn disable(&mut self) {
336 self.ocmp.contclr.write(|w| w.on().set_bit());
337 }
338
339 fn get_duty(&self) -> Self::Duty {
340 self.ocmp.rs.read().rs().bits() as Self::Duty
341 }
342
343 fn set_duty(&mut self, duty: Self::Duty) {
344 self.ocmp.rs.write(|w| unsafe { w.rs().bits(duty) });
345 }
346
347 fn get_max_duty(&self) -> Self::Duty {
348 let pr = unsafe { (*<$timer_even>::ptr()).pr.read().pr().bits() };
349 pr.saturating_add(1)
350 }
351 }
352
353 impl<TIMEBASE> ErrorType for Pwm<$ocmp, TIMEBASE> {
354 type Error = Infallible;
355 }
356
357 impl SetDutyCycle for Pwm<$ocmp, Timebase16even> {
358 fn max_duty_cycle(&self) -> u16 {
359 unsafe { (*<$timer_even>::ptr()).pr.read().pr().bits() as u16 + 1 }
360 }
361
362 fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
363 self.ocmp.rs.write(|w| unsafe { w.rs().bits(duty as u32) });
364 Ok(())
365 }
366 }
367
368 impl SetDutyCycle for Pwm<$ocmp, Timebase16odd> {
369 fn max_duty_cycle(&self) -> u16 {
370 unsafe { (*<$timer_odd>::ptr()).pr.read().pr().bits() as u16 + 1 }
371 }
372
373 fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
374 self.ocmp.rs.write(|w| unsafe { w.rs().bits(duty as u32) });
375 Ok(())
376 }
377 }
378 };
379}
380
381pwm_impl!(oc1, OCMP1, TMR2, TMR3);
382pwm_impl!(oc2, OCMP2, TMR2, TMR3);
383pwm_impl!(oc3, OCMP3, TMR2, TMR3);
384pwm_impl!(oc4, OCMP4, TMR2, TMR3);
385pwm_impl!(oc5, OCMP5, TMR2, TMR3);