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