atsamd_hal/peripherals/pwm/
d5x.rs

1#![allow(non_snake_case)]
2
3use atsamd_hal_macros::hal_cfg;
4
5use crate::clock;
6use crate::gpio::*;
7use crate::gpio::{AlternateE, AnyPin, Pin};
8use crate::pac::Mclk;
9use crate::time::Hertz;
10use crate::timer_params::TimerParams;
11
12// Timer/Counter (TCx)
13
14/// This is a major syntax hack.
15///
16/// The previous Pinout types were enums that took specific v1::Pin types. As a
17/// result, there was no way to make that implementation simultaneously
18/// compatible with both v1::Pin and Pin.
19///
20/// BUT, the enum variant syntax is the same as the namespaced function syntax.
21/// I converted the enums to structs, and I created constructor methods with the
22/// same names as the previous enum variants. By constructing Pinout types with
23/// functions rather than enum variants, you can make it generic over v1::Pin
24/// and Pin types.
25///
26/// This is (mostly) backwards compatible with the current syntax, and all the
27/// existing calls compile. The only incompatible change is the requirement of
28/// type parameters on the Pwm types. Most of the type, the type parameters can
29/// be inferred, so this is mostly backwards compatible as well. But there were
30/// one or two instances where I had to add explicit type parameters to existing
31/// BSP code.
32macro_rules! impl_tc_pinout {
33    (
34        $Type:ident: [ $(
35            $( #[$attr:meta] )?
36            ($func: ident, $Id: ident)
37        ),+ ]
38    ) => {
39        pub struct $Type<I: PinId> {
40            _pin: Pin<I, AlternateE>,
41        }
42
43        $(
44            $( #[$attr] )?
45            impl $Type<$Id> {
46                #[inline]
47                pub fn $func(pin: impl AnyPin<Id = $Id>) -> Self {
48                    let _pin = pin.into().into_alternate();
49                    Self { _pin }
50                }
51            }
52        )+
53    };
54}
55
56#[hal_cfg("tc0")]
57impl_tc_pinout!(TC0Pinout: [
58    #[hal_cfg("pa05")]
59    (Pa5, PA05),
60    #[hal_cfg("pa09")]
61    (Pa9, PA09),
62    #[hal_cfg("pb31")]
63    (Pb31, PB31)
64]);
65
66#[hal_cfg("tc1")]
67impl_tc_pinout!(TC1Pinout: [
68    #[hal_cfg("pa07")]
69    (Pa7, PA07),
70    #[hal_cfg("pa11")]
71    (Pa11, PA11)
72]);
73
74#[hal_cfg("tc2")]
75impl_tc_pinout!(TC2Pinout: [
76    #[hal_cfg("pa01")]
77    (Pa1, PA01),
78    #[hal_cfg("pa13")]
79    (Pa13, PA13),
80    #[hal_cfg("pa17")]
81    (Pa17, PA17)
82]);
83
84#[hal_cfg("tc3")]
85impl_tc_pinout!(TC3Pinout: [
86    #[hal_cfg("pa15")]
87    (Pa15, PA15),
88    #[hal_cfg("pa19")]
89    (Pa19, PA19)
90]);
91
92#[hal_cfg("tc4")]
93impl_tc_pinout!(TC4Pinout: [
94    #[hal_cfg("pa23")]
95    (Pa23, PA23),
96    #[hal_cfg("pb09")]
97    (Pb9, PB09),
98    #[hal_cfg("pb13")]
99    (Pb13, PB13)
100]);
101
102#[hal_cfg("tc5")]
103impl_tc_pinout!(TC5Pinout: [
104    #[hal_cfg("pa25")]
105    (Pa25, PA25),
106    #[hal_cfg("pb11")]
107    (Pb11, PB11),
108    #[hal_cfg("pb15")]
109    (Pb15, PB15)
110]);
111
112#[hal_cfg("tc6")]
113impl_tc_pinout!(TC6Pinout: [
114    #[hal_cfg("pb03")]
115    (Pb3, PB03),
116    #[hal_cfg("pb17")]
117    (Pb17, PB17),
118    #[hal_cfg("pa31")]
119    (Pa31, PA31)
120]);
121
122#[hal_cfg("tc7")]
123impl_tc_pinout!(TC7Pinout: [
124    #[hal_cfg("pa21")]
125    (Pa21, PA21),
126    #[hal_cfg("pb23")]
127    (Pb23, PB23),
128    #[hal_cfg("pb01")]
129    (Pb1, PB01)
130]);
131
132macro_rules! pwm {
133    ($($TYPE:ident: ($TC:ident, $pinout:ident, $clock:ident, $apmask:ident, $apbits:ident, $wrapper:ident)),+) => {
134        $(
135
136pub struct $TYPE<I: PinId> {
137    /// The frequency of the attached clock, not the period of the pwm.
138    /// Used to calculate the period of the pwm.
139    clock_freq: Hertz,
140    tc: crate::pac::$TC,
141    #[allow(dead_code)]
142    pinout: $pinout<I>,
143}
144
145impl<I: PinId> $TYPE<I> {
146    pub fn new(
147        clock: &clock::$clock,
148        freq: Hertz,
149        tc: crate::pac::$TC,
150        pinout: $pinout<I>,
151        mclk: &mut Mclk,
152    ) -> Self {
153        let count = tc.count16();
154        let params = TimerParams::new(freq.convert(), clock.freq());
155        mclk.$apmask().modify(|_, w| w.$apbits().set_bit());
156        count.ctrla().write(|w| w.swrst().set_bit());
157        while count.ctrla().read().bits() & 1 != 0 {}
158        count.ctrla().modify(|_, w| w.enable().clear_bit());
159        while count.syncbusy().read().enable().bit_is_set() {}
160        count.ctrla().modify(|_, w| {
161            match params.divider {
162                1 => w.prescaler().div1(),
163                2 => w.prescaler().div2(),
164                4 => w.prescaler().div4(),
165                8 => w.prescaler().div8(),
166                16 => w.prescaler().div16(),
167                64 => w.prescaler().div64(),
168                256 => w.prescaler().div256(),
169                1024 => w.prescaler().div1024(),
170                _ => unreachable!(),
171            }
172        });
173        count.wave().write(|w| w.wavegen().mpwm());
174        count.cc(0).write(|w| unsafe { w.cc().bits(params.cycles as u16) });
175        while count.syncbusy().read().cc0().bit_is_set() {}
176        count.cc(1).write(|w| unsafe { w.cc().bits(0) });
177        while count.syncbusy().read().cc1().bit_is_set() {}
178        count.ctrla().modify(|_, w| w.enable().set_bit());
179        while count.syncbusy().read().enable().bit_is_set() {}
180
181        Self {
182            clock_freq: clock.freq(),
183            tc,
184            pinout,
185        }
186    }
187
188    pub fn get_period(&self) -> Hertz {
189        let count = self.tc.count16();
190        let divisor = count.ctrla().read().prescaler().bits();
191        let top = count.cc(0).read().cc().bits();
192        self.clock_freq / divisor as u32 / (top + 1) as u32
193    }
194
195    pub fn set_period(&mut self, period: Hertz)
196    {
197        let period = period.into();
198        let params = TimerParams::new(period, self.clock_freq);
199        let count = self.tc.count16();
200        count.ctrla().modify(|_, w| w.enable().clear_bit());
201        while count.syncbusy().read().enable().bit_is_set() {}
202        count.ctrla().modify(|_, w| {
203                match params.divider {
204                    1 => w.prescaler().div1(),
205                    2 => w.prescaler().div2(),
206                    4 => w.prescaler().div4(),
207                    8 => w.prescaler().div8(),
208                    16 => w.prescaler().div16(),
209                    64 => w.prescaler().div64(),
210                    256 => w.prescaler().div256(),
211                    1024 => w.prescaler().div1024(),
212                    _ => unreachable!(),
213                }
214            });
215        count.ctrla().modify(|_, w| w.enable().set_bit());
216        while count.syncbusy().read().enable().bit_is_set() {}
217        count.cc(0).write(|w| unsafe { w.cc().bits(params.cycles as u16) });
218        while count.syncbusy().read().cc0().bit_is_set() {}
219    }
220}
221
222impl<I: PinId> $crate::ehal::pwm::ErrorType for$TYPE<I> {
223    type Error = ::core::convert::Infallible;
224}
225
226impl<I: PinId> $crate::ehal::pwm::SetDutyCycle for $TYPE<I> {
227    fn max_duty_cycle(&self) -> u16 {
228        let count = self.tc.count16();
229        let top = count.cc(0).read().cc().bits();
230        top
231    }
232
233    fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
234        let count = self.tc.count16();
235        unsafe { count.ccbuf(1).write(|w| w.ccbuf().bits(duty)); }
236        Ok(())
237    }
238}
239
240impl<I: PinId> $crate::ehal_02::PwmPin for $TYPE<I> {
241    type Duty = u16;
242
243    fn disable(&mut self) {
244        let count = self.tc.count16();
245        count.ctrla().modify(|_, w| w.enable().clear_bit());
246        while count.syncbusy().read().enable().bit_is_set() {}
247    }
248
249    fn enable(&mut self) {
250        let count = self.tc.count16();
251        count.ctrla().modify(|_, w| w.enable().set_bit());
252        while count.syncbusy().read().enable().bit_is_set() {}
253    }
254
255
256    fn get_duty(&self) -> Self::Duty {
257        let count = self.tc.count16();
258        let duty: u16 = count.ccbuf(1).read().ccbuf().bits();
259        duty
260    }
261
262    fn get_max_duty(&self) -> Self::Duty {
263        use $crate::ehal::pwm::SetDutyCycle;
264        self.max_duty_cycle()
265    }
266
267    fn set_duty(&mut self, duty: Self::Duty) {
268        use $crate::ehal::pwm::SetDutyCycle;
269        let _ignore_infaillible = self.set_duty_cycle(duty);
270    }
271}
272
273
274
275)+}}
276
277#[hal_cfg("tc0")]
278pwm! { Pwm0: (Tc0, TC0Pinout, Tc0Tc1Clock, apbamask, tc0_, Pwm0Wrapper) }
279#[hal_cfg("tc1")]
280pwm! { Pwm1: (Tc1, TC1Pinout, Tc0Tc1Clock, apbamask, tc1_, Pwm1Wrapper) }
281#[hal_cfg("tc2")]
282pwm! { Pwm2: (Tc2, TC2Pinout, Tc2Tc3Clock, apbbmask, tc2_, Pwm2Wrapper) }
283#[hal_cfg("tc3")]
284pwm! { Pwm3: (Tc3, TC3Pinout, Tc2Tc3Clock, apbbmask, tc3_, Pwm3Wrapper) }
285#[hal_cfg("tc4")]
286pwm! { Pwm4: (Tc4, TC4Pinout, Tc4Tc5Clock, apbcmask, tc4_, Pwm4Wrapper) }
287#[hal_cfg("tc5")]
288pwm! { Pwm5: (Tc5, TC5Pinout, Tc4Tc5Clock, apbcmask, tc5_, Pwm5Wrapper) }
289#[hal_cfg("tc6")]
290pwm! { Pwm6: (Tc6, TC6Pinout, Tc6Tc7Clock, apbdmask, tc6_, Pwm6Wrapper) }
291#[hal_cfg("tc7")]
292pwm! { Pwm7: (Tc7, TC7Pinout, Tc6Tc7Clock, apbdmask, tc7_, Pwm7Wrapper) }
293
294// Timer/Counter for Control Applications (TCCx)
295
296#[derive(Copy, Clone)]
297pub enum Channel {
298    _0,
299    _1,
300    _2,
301    _3,
302    _4,
303    _5,
304    _6,
305    _7,
306}
307
308/// This is a major syntax hack.
309///
310/// The previous Pinout types were enums that took specific v1::Pin types. As a
311/// result, there was no way to make that implementation simultaneously
312/// compatible with both v1::Pin and Pin.
313///
314/// BUT, the enum variant syntax is the same as the namespaced function syntax.
315/// I converted the enums to structs, and I created constructor methods with the
316/// same names as the previous enum variants. By constructing Pinout types with
317/// functions rather than enum variants, you can make it generic over v1::Pin
318/// and Pin types.
319///
320/// This is (mostly) backwards compatible with the current syntax, and all the
321/// existing calls compile. The only incompatible change is the requirement of
322/// type parameters on the Pwm types. Most of the type, the type parameters can
323/// be inferred, so this is mostly backwards compatible as well. But there were
324/// one or two instances where I had to add explicit type parameters to existing
325/// BSP code.
326macro_rules! impl_tcc_pinout {
327    (
328        $Type:ident: [ $(
329            $( #[$attr:meta] )?
330            ($func: ident, $Id: ident, $Mode:ident)
331        ),+ ]
332    ) => {
333        pub struct $Type<I: PinId, M: PinMode> {
334            _pin: Pin<I, M>,
335        }
336
337        $(
338            $( #[$attr] )?
339            impl $Type<$Id, $Mode> {
340                #[inline]
341                pub fn $func(pin: impl AnyPin<Id = $Id>) -> Self {
342                    let _pin = pin.into().into_alternate();
343                    Self { _pin }
344                }
345            }
346        )+
347    };
348}
349
350#[hal_cfg("tcc0")]
351impl_tcc_pinout!(TCC0Pinout: [
352    #[hal_cfg("pa08")]
353    (Pa8, PA08, AlternateF),
354    #[hal_cfg("pa09")]
355    (Pa9, PA09, AlternateF),
356    #[hal_cfg("pa10")]
357    (Pa10, PA10, AlternateF),
358    #[hal_cfg("pa11")]
359    (Pa11, PA11, AlternateF),
360    #[hal_cfg("pa12")]
361    (Pa12, PA12, AlternateF),
362    #[hal_cfg("pa13")]
363    (Pa13, PA13, AlternateF),
364    #[hal_cfg("pa16")]
365    (Pa16, PA16, AlternateG),
366    #[hal_cfg("pa17")]
367    (Pa17, PA17, AlternateG),
368    #[hal_cfg("pa18")]
369    (Pa18, PA18, AlternateG),
370    #[hal_cfg("pa19")]
371    (Pa19, PA19, AlternateG),
372    #[hal_cfg("pa20")]
373    (Pa20, PA20, AlternateG),
374    #[hal_cfg("pa21")]
375    (Pa21, PA21, AlternateG),
376    #[hal_cfg("pa22")]
377    (Pa22, PA22, AlternateG),
378    #[hal_cfg("pa23")]
379    (Pa23, PA23, AlternateG),
380    #[hal_cfg("pb10")]
381    (Pb10, PB10, AlternateF),
382    #[hal_cfg("pb11")]
383    (Pb11, PB11, AlternateF),
384    #[hal_cfg("pb12")]
385    (Pb12, PB12, AlternateG),
386    #[hal_cfg("pb13")]
387    (Pb13, PB13, AlternateG),
388    #[hal_cfg("pb14")]
389    (Pb14, PB14, AlternateG),
390    #[hal_cfg("pb15")]
391    (Pb15, PB15, AlternateG),
392    #[hal_cfg("pb16")]
393    (Pb16, PB16, AlternateG),
394    #[hal_cfg("pb17")]
395    (Pb17, PB17, AlternateG),
396    #[hal_cfg("pb30")]
397    (Pb30, PB30, AlternateG),
398    #[hal_cfg("pb31")]
399    (Pb31, PB31, AlternateG),
400    #[hal_cfg("pc10")]
401    (Pc10, PC10, AlternateF),
402    #[hal_cfg("pc11")]
403    (Pc11, PC11, AlternateF),
404    #[hal_cfg("pc12")]
405    (Pc12, PC12, AlternateF),
406    #[hal_cfg("pc13")]
407    (Pc13, PC13, AlternateF),
408    #[hal_cfg("pc14")]
409    (Pc14, PC14, AlternateF),
410    #[hal_cfg("pc15")]
411    (Pc15, PC15, AlternateF),
412    #[hal_cfg("pc16")]
413    (Pc16, PC16, AlternateF),
414    #[hal_cfg("pc17")]
415    (Pc17, PC17, AlternateF),
416    #[hal_cfg("pc18")]
417    (Pc18, PC18, AlternateF),
418    #[hal_cfg("pc19")]
419    (Pc19, PC19, AlternateF),
420    #[hal_cfg("pc20")]
421    (Pc20, PC20, AlternateF),
422    #[hal_cfg("pc21")]
423    (Pc21, PC21, AlternateF),
424    #[hal_cfg("pc04")]
425    (Pc4, PC04, AlternateF),
426    #[hal_cfg("pc22")]
427    (Pc22, PC22, AlternateF),
428    #[hal_cfg("pc23")]
429    (Pc23, PC23, AlternateF),
430    #[hal_cfg("pd08")]
431    (Pd8, PD08, AlternateF),
432    #[hal_cfg("pd09")]
433    (Pd9, PD09, AlternateF),
434    #[hal_cfg("pd10")]
435    (Pd10, PD10, AlternateF),
436    #[hal_cfg("pd11")]
437    (Pd11, PD11, AlternateF),
438    #[hal_cfg("pd12")]
439    (Pd12, PD12, AlternateF)
440]);
441
442#[hal_cfg("tcc1")]
443impl_tcc_pinout!(TCC1Pinout: [
444    #[hal_cfg("pa08")]
445    (Pa8, PA08, AlternateG),
446    #[hal_cfg("pa09")]
447    (Pa9, PA09, AlternateG),
448    #[hal_cfg("pa10")]
449    (Pa10, PA10, AlternateG),
450    #[hal_cfg("pa11")]
451    (Pa11, PA11, AlternateG),
452    #[hal_cfg("pa12")]
453    (Pa12, PA12, AlternateG),
454    #[hal_cfg("pa13")]
455    (Pa13, PA13, AlternateG),
456    #[hal_cfg("pa14")]
457    (Pa14, PA14, AlternateG),
458    #[hal_cfg("pa15")]
459    (Pa15, PA15, AlternateG),
460    #[hal_cfg("pa16")]
461    (Pa16, PA16, AlternateF),
462    #[hal_cfg("pa17")]
463    (Pa17, PA17, AlternateF),
464    #[hal_cfg("pa18")]
465    (Pa18, PA18, AlternateF),
466    #[hal_cfg("pa19")]
467    (Pa19, PA19, AlternateF),
468    #[hal_cfg("pa20")]
469    (Pa20, PA20, AlternateF),
470    #[hal_cfg("pa21")]
471    (Pa21, PA21, AlternateF),
472    #[hal_cfg("pa22")]
473    (Pa22, PA22, AlternateF),
474    #[hal_cfg("pa23")]
475    (Pa23, PA23, AlternateF),
476    #[hal_cfg("pb10")]
477    (Pb10, PB10, AlternateG),
478    #[hal_cfg("pb11")]
479    (Pb11, PB11, AlternateG),
480    #[hal_cfg("pb18")]
481    (Pb18, PB18, AlternateF),
482    #[hal_cfg("pb19")]
483    (Pb19, PB19, AlternateF),
484    #[hal_cfg("pb20")]
485    (Pb20, PB20, AlternateF),
486    #[hal_cfg("pb21")]
487    (Pb21, PB21, AlternateF),
488    #[hal_cfg("pc10")]
489    (Pc10, PC10, AlternateG),
490    #[hal_cfg("pc11")]
491    (Pc11, PC11, AlternateG),
492    #[hal_cfg("pc12")]
493    (Pc12, PC12, AlternateG),
494    #[hal_cfg("pc13")]
495    (Pc13, PC13, AlternateG),
496    #[hal_cfg("pc14")]
497    (Pc14, PC14, AlternateG),
498    #[hal_cfg("pc15")]
499    (Pc15, PC15, AlternateG),
500    #[hal_cfg("pb26")]
501    (Pb26, PB26, AlternateF),
502    #[hal_cfg("pb27")]
503    (Pb27, PB27, AlternateF),
504    #[hal_cfg("pb28")]
505    (Pb28, PB28, AlternateF),
506    #[hal_cfg("pb29")]
507    (Pb29, PB29, AlternateF),
508    #[hal_cfg("pd20")]
509    (Pd20, PD20, AlternateF),
510    #[hal_cfg("pd21")]
511    (Pd21, PD21, AlternateF)
512]);
513
514#[hal_cfg("tcc2")]
515impl_tcc_pinout!(TCC2Pinout: [
516    #[hal_cfg("pa14")]
517    (Pa14, PA14, AlternateF),
518    #[hal_cfg("pa15")]
519    (Pa15, PA15, AlternateF),
520    #[hal_cfg("pa24")]
521    (Pa24, PA24, AlternateF),
522    #[hal_cfg("pa30")]
523    (Pa30, PA30, AlternateF),
524    #[hal_cfg("pa31")]
525    (Pa31, PA31, AlternateF),
526    #[hal_cfg("pb02")]
527    (Pb2,  PB02, AlternateF)
528]);
529
530#[hal_cfg("tcc3")]
531impl_tcc_pinout!(TCC3Pinout: [
532    #[hal_cfg("pb12")]
533    (Pb12, PB12, AlternateF),
534    #[hal_cfg("pb13")]
535    (Pb13, PB13, AlternateF),
536    #[hal_cfg("pb16")]
537    (Pb16, PB16, AlternateF),
538    #[hal_cfg("pb17")]
539    (Pb17, PB17, AlternateF)
540]);
541
542#[hal_cfg("tcc4")]
543impl_tcc_pinout!(TCC4Pinout: [
544    #[hal_cfg("pb14")]
545    (Pb14, PB14, AlternateF),
546    #[hal_cfg("pb15")]
547    (Pb15, PB15, AlternateF),
548    #[hal_cfg("pb30")]
549    (Pb30, PB30, AlternateF),
550    #[hal_cfg("pb31")]
551    (Pb31, PB31, AlternateF)
552]);
553
554macro_rules! pwm_tcc {
555    ($($TYPE:ident: ($TCC:ident, $pinout:ident, $clock:ident, $apmask:ident, $apbits:ident, $wrapper:ident)),+) => {
556        $(
557
558pub struct $TYPE<I: PinId, M: PinMode> {
559    /// The frequency of the attached clock, not the period of the pwm.
560    /// Used to calculate the period of the pwm.
561    clock_freq: Hertz,
562    tcc: crate::pac::$TCC,
563    #[allow(dead_code)]
564    pinout: $pinout<I, M>,
565}
566
567impl<I: PinId, M: PinMode> $TYPE<I, M> {
568    pub fn new(
569        clock: &clock::$clock,
570        freq: Hertz,
571        tcc: crate::pac::$TCC,
572        pinout: $pinout<I, M>,
573        mclk: &mut Mclk,
574    ) -> Self {
575        let params = TimerParams::new(freq.convert(), clock.freq());
576        mclk.$apmask().modify(|_, w| w.$apbits().set_bit());
577        tcc.ctrla().write(|w| w.swrst().set_bit());
578        while tcc.syncbusy().read().swrst().bit_is_set() {}
579        tcc.ctrlbclr().write(|w| w.dir().set_bit() );
580        while tcc.syncbusy().read().ctrlb().bit_is_set() {}
581        tcc.ctrla().modify(|_, w| w.enable().clear_bit());
582        while tcc.syncbusy().read().enable().bit_is_set() {}
583        tcc.ctrla().modify(|_, w| {
584            match params.divider {
585                1 => w.prescaler().div1(),
586                2 => w.prescaler().div2(),
587                4 => w.prescaler().div4(),
588                8 => w.prescaler().div8(),
589                16 => w.prescaler().div16(),
590                64 => w.prescaler().div64(),
591                256 => w.prescaler().div256(),
592                1024 => w.prescaler().div1024(),
593                _ => unreachable!(),
594            }
595        });
596        tcc.wave().write(|w| w.wavegen().npwm());
597        while tcc.syncbusy().read().wave().bit_is_set() {}
598        tcc.per().write(|w| unsafe { w.bits(params.cycles as u32) });
599        while tcc.syncbusy().read().per().bit_is_set() {}
600        tcc.ctrla().modify(|_, w| w.enable().set_bit());
601        while tcc.syncbusy().read().enable().bit_is_set() {}
602
603        Self {
604            clock_freq: clock.freq(),
605            tcc,
606            pinout,
607        }
608    }
609}
610
611impl<I: PinId, M: PinMode> $crate::ehal_02::Pwm for $TYPE<I, M> {
612    type Channel = Channel;
613    type Time = Hertz;
614    type Duty = u32;
615
616    fn disable(&mut self, _channel: Self::Channel) {
617        self.tcc.ctrla().modify(|_, w| w.enable().clear_bit());
618        while self.tcc.syncbusy().read().enable().bit_is_set() {}
619    }
620
621    fn enable(&mut self, _channel: Self::Channel) {
622        self.tcc.ctrla().modify(|_, w| w.enable().set_bit());
623        while self.tcc.syncbusy().read().enable().bit_is_set() {}
624    }
625
626    fn get_period(&self) -> Self::Time {
627        let divisor = self.tcc.ctrla().read().prescaler().bits();
628        let top = self.tcc.per().read().bits();
629        self.clock_freq / divisor as u32 / (top + 1) as u32
630    }
631
632    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
633        let cc = self.tcc.cc(channel as usize);
634        let duty = cc.read().cc().bits();
635        duty
636    }
637
638    fn get_max_duty(&self) -> Self::Duty {
639        let top = self.tcc.per().read().bits();
640        top
641    }
642
643    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
644        let cc = self.tcc.cc(channel as usize);
645        cc.write(|w| unsafe { w.cc().bits(duty) });
646    }
647
648    fn set_period<P>(&mut self, period: P)
649    where
650        P: Into<Self::Time>,
651    {
652        let params = TimerParams::new(period.into().convert(), self.clock_freq);
653        self.tcc.ctrla().modify(|_, w| w.enable().clear_bit());
654        while self.tcc.syncbusy().read().enable().bit_is_set() {}
655        self.tcc.ctrla().modify(|_, w| {
656            match params.divider {
657                1 => w.prescaler().div1(),
658                2 => w.prescaler().div2(),
659                4 => w.prescaler().div4(),
660                8 => w.prescaler().div8(),
661                16 => w.prescaler().div16(),
662                64 => w.prescaler().div64(),
663                256 => w.prescaler().div256(),
664                1024 => w.prescaler().div1024(),
665                _ => unreachable!(),
666            }
667        });
668        self.tcc.ctrla().modify(|_, w| w.enable().set_bit());
669        while self.tcc.syncbusy().read().enable().bit_is_set() {}
670        self.tcc.per().write(|w| unsafe { w.bits(params.cycles as u32) });
671        while self.tcc.syncbusy().read().per().bit() {}
672    }
673}
674
675        )+
676    };
677}
678
679#[hal_cfg("tcc0")]
680pwm_tcc! { Tcc0Pwm: (Tcc0, TCC0Pinout, Tcc0Tcc1Clock, apbbmask, tcc0_, TccPwm0Wrapper) }
681#[hal_cfg("tcc1")]
682pwm_tcc! { Tcc1Pwm: (Tcc1, TCC1Pinout, Tcc0Tcc1Clock, apbbmask, tcc1_, TccPwm1Wrapper) }
683#[hal_cfg("tcc2")]
684pwm_tcc! { Tcc2Pwm: (Tcc2, TCC2Pinout, Tcc2Tcc3Clock, apbcmask, tcc2_, TccPwm2Wrapper) }
685#[hal_cfg("tcc3")]
686pwm_tcc! { Tcc3Pwm: (Tcc3, TCC3Pinout, Tcc2Tcc3Clock, apbcmask, tcc3_, TccPwm3Wrapper) }
687#[hal_cfg("tcc4")]
688pwm_tcc! { Tcc4Pwm: (Tcc4, TCC4Pinout, Tcc4Clock,     apbdmask, tcc4_, TccPwm4Wrapper) }