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
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) });
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#[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 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) }