Skip to main content

atsamd_hal/peripherals/pwm/
d11.rs

1use atsamd_hal_macros::hal_cfg;
2
3use crate::clock;
4use crate::pac::Pm;
5use crate::time::Hertz;
6use crate::timer_params::TimerParams;
7
8// Timer/Counter (TCx)
9
10macro_rules! pwm {
11    ($($TYPE:ident: ($TC:ident, $clock:ident, $apmask:ident, $apbits:ident, $wrapper:ident)),+) => {
12        $(
13
14pub struct $TYPE {
15    /// The frequency of the attached clock, not the period of the pwm.
16    /// Used to calculate the period of the pwm.
17    clock_freq: Hertz,
18    tc: crate::pac::$TC,
19}
20
21impl $TYPE {
22    pub fn new(
23        clock: &clock::$clock,
24        freq: Hertz,
25        tc: crate::pac::$TC,
26        pm: &mut Pm,
27    ) -> Self {
28        let count = tc.count16();
29        let params = TimerParams::new(freq.convert(), clock.freq());
30        pm.$apmask().modify(|_, w| w.$apbits().set_bit());
31        count.ctrla().write(|w| w.swrst().set_bit());
32        while count.ctrla().read().bits() & 1 != 0 {}
33        count.ctrla().modify(|_, w| w.enable().clear_bit());
34        while count.status().read().syncbusy().bit_is_set() {}
35        count.ctrla().modify(|_, w| {
36            match params.divider {
37                1 => w.prescaler().div1(),
38                2 => w.prescaler().div2(),
39                4 => w.prescaler().div4(),
40                8 => w.prescaler().div8(),
41                16 => w.prescaler().div16(),
42                64 => w.prescaler().div64(),
43                256 => w.prescaler().div256(),
44                1024 => w.prescaler().div1024(),
45                _ => unreachable!(),
46            }
47        });
48        count.ctrla().write(|w| w.wavegen().mpwm());
49        count.cc(0).write(|w| unsafe { w.cc().bits(params.cycles as u16 - 1) });
50        count.cc(1).write(|w| unsafe { w.cc().bits(0) });
51        count.ctrla().modify(|_, w| w.enable().set_bit());
52        while count.status().read().syncbusy().bit_is_set() {}
53
54        Self {
55            clock_freq: clock.freq(),
56            tc,
57        }
58    }
59
60    #[inline]
61    // Disables the TC, then releases it
62    pub fn free(self) -> crate::pac::$TC {
63        let count = self.tc.count16();
64        count.ctrla().write(|w| w.swrst().set_bit());
65        while count.ctrla().read().bits() & 1 != 0 {}
66        self.tc
67    }
68
69    pub fn set_period(&mut self, period: Hertz)
70    {
71        let params = TimerParams::new(period, self.clock_freq);
72        let count = self.tc.count16();
73        count.ctrla().modify(|_, w| w.enable().clear_bit());
74        while count.status().read().syncbusy().bit_is_set() {}
75        count.ctrla().modify(|_, w| {
76            match params.divider {
77                1 => w.prescaler().div1(),
78                2 => w.prescaler().div2(),
79                4 => w.prescaler().div4(),
80                8 => w.prescaler().div8(),
81                16 => w.prescaler().div16(),
82                64 => w.prescaler().div64(),
83                256 => w.prescaler().div256(),
84                1024 => w.prescaler().div1024(),
85                _ => unreachable!(),
86            }
87        });
88        count.ctrla().modify(|_, w| w.enable().set_bit());
89        while count.status().read().syncbusy().bit_is_set() {}
90        count.cc(0).write(|w| unsafe { w.cc().bits(params.cycles as u16 - 1) });
91    }
92
93    pub fn get_period(&self) -> Hertz {
94        let count = self.tc.count16();
95        let divisor = count.ctrla().read().prescaler().bits();
96        let top = count.cc(0).read().cc().bits();
97        self.clock_freq / divisor as u32 / (top + 1) as u32
98    }
99}
100
101impl $crate::ehal::pwm::ErrorType for$TYPE {
102    type Error = ::core::convert::Infallible;
103}
104
105impl $crate::ehal::pwm::SetDutyCycle for $TYPE {
106    fn max_duty_cycle(&self) -> u16 {
107        let count = self.tc.count16();
108        let top = count.cc(0).read().cc().bits();
109        top.saturating_add(1)
110    }
111
112    fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
113        let count = self.tc.count16();
114        unsafe { count.cc(1).write(|w| w.cc().bits(duty)); }
115        Ok(())
116    }
117}
118
119impl $crate::ehal_02::PwmPin for $TYPE {
120    type Duty = u16;
121
122    fn disable(&mut self) {
123        let count = self.tc.count16();
124        count.ctrla().modify(|_, w| w.enable().clear_bit());
125        while count.status().read().syncbusy().bit_is_set() {}
126    }
127
128    fn enable(&mut self) {
129        let count = self.tc.count16();
130        count.ctrla().modify(|_, w| w.enable().set_bit());
131        while count.status().read().syncbusy().bit_is_set() {}
132    }
133
134    fn get_duty(&self) -> Self::Duty {
135        let count = self.tc.count16();
136        let duty: u16 = count.cc(1).read().cc().bits();
137        duty
138    }
139
140    fn get_max_duty(&self) -> Self::Duty {
141        use $crate::ehal::pwm::SetDutyCycle;
142        self.max_duty_cycle()
143    }
144
145    fn set_duty(&mut self, duty: Self::Duty) {
146        use $crate::ehal::pwm::SetDutyCycle;
147        let _ignore_infaillible = self.set_duty_cycle(duty);
148    }
149}
150
151)+}}
152
153#[hal_cfg("tc1")]
154pwm! { Pwm1: (Tc1, Tc1Tc2Clock, apbcmask, tc1_, Pwm1Wrapper) }
155#[hal_cfg("tc2")]
156pwm! { Pwm2: (Tc2, Tc1Tc2Clock, apbcmask, tc2_, Pwm2Wrapper) }
157#[hal_cfg("tc3")]
158pwm! { Pwm3: (Tc3, Tcc2Tc3Clock, apbcmask, tc3_, Pwm3Wrapper) }
159#[hal_cfg("tc4")]
160pwm! { Pwm4: (Tc4, Tc4Tc5Clock, apbcmask, tc4_, Pwm4Wrapper) }
161#[hal_cfg("tc5")]
162pwm! { Pwm5: (Tc5, Tc4Tc5Clock, apbcmask, tc5_, Pwm5Wrapper) }
163
164#[hal_cfg("tc6")]
165pwm! { Pwm6: (Tc6, Tc6Tc7Clock, apbcmask, tc6_, Pwm6Wrapper) }
166#[hal_cfg("tc7")]
167pwm! { Pwm7: (Tc7, Tc6Tc7Clock, apbcmask, tc7_, Pwm7Wrapper) }
168
169// Timer/Counter for Control Applications (TCCx)
170
171#[derive(Copy, Clone)]
172pub enum Channel {
173    _0,
174    _1,
175    _2,
176    _3,
177}
178
179macro_rules! pwm_tcc {
180    ($($TYPE:ident: ($TCC:ident, $clock:ident, $apmask:ident, $apbits:ident, $wrapper:ident)),+) => {
181        $(
182
183pub struct $TYPE {
184    /// The frequency of the attached clock, not the period of the pwm.
185    /// Used to calculate the period of the pwm.
186    clock_freq: Hertz,
187    tcc: crate::pac::$TCC,
188}
189
190impl $TYPE {
191    pub fn new<F: Into<Hertz>> (
192        clock: &clock::$clock,
193        freq: F,
194        tcc: crate::pac::$TCC,
195        pm: &mut Pm,
196    ) -> Self {
197        let freq = freq.into();
198        {
199            let params = TimerParams::new(freq, clock.freq());
200            pm.$apmask().modify(|_, w| w.$apbits().set_bit());
201            tcc.ctrla().write(|w| w.swrst().set_bit());
202            while tcc.syncbusy().read().swrst().bit_is_set() {}
203            tcc.ctrlbclr().write(|w| w.dir().set_bit() );
204            while tcc.syncbusy().read().ctrlb().bit_is_set() {}
205            tcc.ctrla().modify(|_, w| w.enable().clear_bit());
206            while tcc.syncbusy().read().enable().bit_is_set() {}
207            tcc.ctrla().modify(|_, w| {
208                match params.divider {
209                    1 => w.prescaler().div1(),
210                    2 => w.prescaler().div2(),
211                    4 => w.prescaler().div4(),
212                    8 => w.prescaler().div8(),
213                    16 => w.prescaler().div16(),
214                    64 => w.prescaler().div64(),
215                    256 => w.prescaler().div256(),
216                    1024 => w.prescaler().div1024(),
217                    _ => unreachable!(),
218                }
219            });
220            tcc.wave().write(|w| w.wavegen().npwm());
221            while tcc.syncbusy().read().wave().bit_is_set() {}
222            tcc.per().write(|w| unsafe { w.bits(params.cycles as u32 - 1) });
223            while tcc.syncbusy().read().per().bit_is_set() {}
224            tcc.ctrla().modify(|_, w| w.enable().set_bit());
225            while tcc.syncbusy().read().enable().bit_is_set() {}
226        }
227
228        Self {
229            clock_freq: clock.freq(),
230            tcc,
231        }
232    }
233}
234
235impl $crate::ehal_02::Pwm for $TYPE {
236    type Channel = Channel;
237    type Time = Hertz;
238    type Duty = u32;
239
240    fn disable(&mut self, _channel: Self::Channel) {
241        self.tcc.ctrla().modify(|_, w| w.enable().clear_bit());
242        while self.tcc.syncbusy().read().enable().bit_is_set() {}
243    }
244
245    fn enable(&mut self, _channel: Self::Channel) {
246        self.tcc.ctrla().modify(|_, w| w.enable().set_bit());
247        while self.tcc.syncbusy().read().enable().bit_is_set() {}
248    }
249
250    fn get_period(&self) -> Self::Time {
251        let divisor = self.tcc.ctrla().read().prescaler().bits();
252        let top = self.tcc.per().read().bits();
253        self.clock_freq / divisor as u32 / (top + 1) as u32
254    }
255
256    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
257        let cc = self.tcc.cc(channel as usize);
258        let duty: u32 = cc.read().cc().bits();
259        duty
260    }
261
262    fn get_max_duty(&self) -> Self::Duty {
263        let top = self.tcc.per().read().bits();
264        top + 1
265    }
266
267    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
268        let cc = self.tcc.cc(channel as usize);
269        cc.write(|w| unsafe { w.cc().bits(duty) });
270    }
271
272    fn set_period<P>(&mut self, period: P)
273    where
274        P: Into<Self::Time>,
275    {
276        let period = period.into();
277        let params = TimerParams::new(period, self.clock_freq);
278        self.tcc.ctrla().modify(|_, w| w.enable().clear_bit());
279        while self.tcc.syncbusy().read().enable().bit_is_set() {}
280        self.tcc.ctrla().modify(|_, w| {
281            match params.divider {
282                1 => w.prescaler().div1(),
283                2 => w.prescaler().div2(),
284                4 => w.prescaler().div4(),
285                8 => w.prescaler().div8(),
286                16 => w.prescaler().div16(),
287                64 => w.prescaler().div64(),
288                256 => w.prescaler().div256(),
289                1024 => w.prescaler().div1024(),
290                _ => unreachable!(),
291            }
292        });
293        self.tcc.ctrla().modify(|_, w| w.enable().set_bit());
294        while self.tcc.syncbusy().read().enable().bit_is_set() {}
295        self.tcc.per().write(|w| unsafe { w.bits(params.cycles as u32 - 1) });
296        while self.tcc.syncbusy().read().per().bit() {}
297    }
298}
299
300)+}}
301
302#[hal_cfg("tcc0-d11")]
303pwm_tcc! { Pwm0: (Tcc0, Tcc0Clock, apbcmask, tcc0_, Pwm0Wrapper) }
304#[hal_cfg("tcc0-d21")]
305pwm_tcc! { Pwm0: (Tcc0, Tcc0Tcc1Clock, apbcmask, tcc0_, Pwm0Wrapper) }
306#[hal_cfg("tcc1")]
307pwm_tcc! { Pwm1: (Tcc1, Tcc0Tcc1Clock, apbcmask, tcc1_, Pwm1Wrapper) }
308#[hal_cfg("tcc1")]
309pwm_tcc! { Pwm2: (Tcc2, Tcc2Tc3Clock, apbcmask, tcc2_, Pwm2Wrapper) }