atsamd_hal/peripherals/pwm/
d11.rs1use atsamd_hal_macros::hal_cfg;
2
3use crate::clock;
4use crate::pac::Pm;
5use crate::time::Hertz;
6use crate::timer_params::TimerParams;
7
8macro_rules! pwm {
11 ($($TYPE:ident: ($TC:ident, $clock:ident, $apmask:ident, $apbits:ident, $wrapper:ident)),+) => {
12 $(
13
14pub struct $TYPE {
15 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 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#[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 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) }