atsamd_hal/peripherals/eic/d11/
pin.rs1use atsamd_hal_macros::hal_cfg;
2
3use crate::ehal::digital::{ErrorType, InputPin};
4use crate::ehal_02::digital::v2::InputPin as InputPin_02;
5use crate::eic::*;
6use crate::gpio::{
7 self, AnyPin, FloatingInterrupt, PinMode, PullDownInterrupt, PullUpInterrupt, pin::*,
8};
9use core::convert::Infallible;
10
11macro_rules! ei {
15 (
16 $PadType:ident [ $num:expr ] {
17 $(
18 $(#[$attr:meta])*
19 $PinType:ident,
20 )+
21 }
22 ) => {
23 crate::paste::item! {
24 $(
25 $(#[$attr])*
26 impl<M: PinMode> EicPin for Pin<gpio::$PinType, M> {
27 type Floating = ExtInt<Pin<gpio::$PinType, FloatingInterrupt>, Self::ChId>;
28 type PullUp = ExtInt<Pin<gpio::$PinType, PullUpInterrupt>, Self::ChId>;
29 type PullDown = ExtInt<Pin<gpio::$PinType, PullDownInterrupt>, Self::ChId>;
30
31 type ChId = [<Ch $num>];
32
33 fn into_floating_ei(self, chan: Channel<Self::ChId>) -> Self::Floating {
34 Self::Floating::new(self.into_floating_interrupt(), chan)
35 }
36
37 fn into_pull_up_ei(self, chan: Channel<Self::ChId>) -> Self::PullUp {
38 Self::PullUp::new(self.into_pull_up_interrupt(), chan)
39 }
40
41 fn into_pull_down_ei(self, chan: Channel<Self::ChId>) -> Self::PullDown {
42 Self::PullDown::new(self.into_pull_down_interrupt(), chan)
43 }
44 }
45 )+
46 }
47 };
48}
49
50impl<P, Id, F> ExtInt<P, Id, F>
51where
52 P: EicPin,
53 Id: ChId,
54{
55 pub fn enable_event(&mut self) {
60 self.chan.with_disable(|e| {
61 e.evctrl()
62 .modify(|r, w| unsafe { w.bits(r.bits() | 1 << P::ChId::ID) });
63 });
64 }
65
66 pub fn disable_event(&mut self) {
71 self.chan.with_disable(|e| {
72 e.evctrl()
73 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << P::ChId::ID)) });
74 });
75 }
76
77 pub fn enable_interrupt(&mut self) {
78 self.chan
79 .eic
80 .intenset()
81 .write(|w| unsafe { w.bits(1 << P::ChId::ID) });
82 }
83
84 pub fn enable_interrupt_wake(&mut self) {
85 self.chan
86 .eic
87 .wakeup()
88 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << P::ChId::ID)) })
89 }
90
91 pub fn disable_interrupt(&mut self) {
92 self.chan
93 .eic
94 .intenclr()
95 .write(|w| unsafe { w.bits(1 << P::ChId::ID) });
96 }
97
98 pub fn is_interrupt(&mut self) -> bool {
99 self.chan.eic.intflag().read().bits() & (1 << P::ChId::ID) != 0
100 }
101
102 pub fn clear_interrupt(&mut self) {
103 self.chan
104 .eic
105 .intflag()
106 .write(|w| unsafe { w.bits(1 << P::ChId::ID) });
107 }
108
109 pub fn sense(&mut self, sense: Sense) {
110 self.chan.with_disable(|e| {
111 let offset = (P::ChId::ID >> 3) & 0b0001;
113 let config = &e.config(offset);
114
115 config.modify(|_, w| unsafe {
116 match P::ChId::ID & 0b111 {
118 0b000 => w.sense0().bits(sense as u8),
119 0b001 => w.sense1().bits(sense as u8),
120 0b010 => w.sense2().bits(sense as u8),
121 0b011 => w.sense3().bits(sense as u8),
122 0b100 => w.sense4().bits(sense as u8),
123 0b101 => w.sense5().bits(sense as u8),
124 0b110 => w.sense6().bits(sense as u8),
125 0b111 => w.sense7().bits(sense as u8),
126 _ => unreachable!(),
127 }
128 });
129 });
130 }
131
132 pub fn filter(&mut self, filter: bool) {
133 self.chan.with_disable(|e| {
134 let offset = (P::ChId::ID >> 3) & 0b0001;
136 let config = &e.config(offset);
137
138 config.modify(|_, w| {
139 match P::ChId::ID & 0b111 {
141 0b000 => w.filten0().bit(filter),
142 0b001 => w.filten1().bit(filter),
143 0b010 => w.filten2().bit(filter),
144 0b011 => w.filten3().bit(filter),
145 0b100 => w.filten4().bit(filter),
146 0b101 => w.filten5().bit(filter),
147 0b110 => w.filten6().bit(filter),
148 0b111 => w.filten7().bit(filter),
149 _ => unreachable!(),
150 }
151 });
152 });
153 }
154}
155
156impl<P, C, Id, F> InputPin_02 for ExtInt<P, Id, F>
157where
158 P: EicPin + AnyPin<Mode = Interrupt<C>>,
159 Id: ChId,
160 C: InterruptConfig,
161{
162 type Error = Infallible;
163 #[inline]
164 fn is_high(&self) -> Result<bool, Self::Error> {
165 self.pin.is_high()
166 }
167 #[inline]
168 fn is_low(&self) -> Result<bool, Self::Error> {
169 self.pin.is_low()
170 }
171}
172
173impl<P, Id, F> InputPin for ExtInt<P, Id, F>
174where
175 Self: ErrorType,
176 P: EicPin,
177 Id: ChId,
178{
179 #[inline]
180 fn is_high(&mut self) -> Result<bool, Self::Error> {
181 Ok(self.pin._is_high())
182 }
183
184 #[inline]
185 fn is_low(&mut self) -> Result<bool, Self::Error> {
186 Ok(self.pin._is_low())
187 }
188}
189
190impl<P, Id, F> ErrorType for ExtInt<P, Id, F>
191where
192 P: EicPin,
193 Id: ChId,
194{
195 type Error = Infallible;
196}
197
198#[cfg(feature = "async")]
199mod async_impls {
200 use embedded_hal_async::digital::Wait;
201
202 use super::super::async_api::WAKERS;
203 use super::*;
204
205 impl<P, Id> ExtInt<P, Id, EicFuture>
206 where
207 P: EicPin,
208 Id: ChId,
209 Self: InputPin<Error = Infallible>,
210 {
211 pub async fn wait(&mut self, sense: Sense) {
212 use core::{future::poll_fn, task::Poll};
213 self.disable_interrupt();
214
215 match sense {
216 Sense::High if self.is_high().unwrap() => return,
217
218 Sense::Low if self.is_low().unwrap() => return,
219 _ => (),
220 }
221
222 self.enable_interrupt_wake();
223 self.sense(sense);
224 poll_fn(|cx| {
225 if self.is_interrupt() {
226 self.clear_interrupt();
227 self.disable_interrupt();
228 self.sense(Sense::None);
229 return Poll::Ready(());
230 }
231
232 WAKERS[P::ChId::ID].register(cx.waker());
233 self.enable_interrupt();
234
235 if self.is_interrupt() {
236 self.clear_interrupt();
237 self.disable_interrupt();
238 self.sense(Sense::None);
239 return Poll::Ready(());
240 }
241
242 Poll::Pending
243 })
244 .await;
245 }
246 }
247
248 impl<P, Id> Wait for ExtInt<P, Id, EicFuture>
249 where
250 P: EicPin,
251 Id: ChId,
252 Self: InputPin<Error = Infallible>,
253 {
254 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
255 self.wait(Sense::High).await;
256 Ok(())
257 }
258
259 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
260 self.wait(Sense::Low).await;
261 Ok(())
262 }
263
264 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
265 self.wait(Sense::Rise).await;
266 Ok(())
267 }
268
269 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
270 self.wait(Sense::Fall).await;
271 Ok(())
272 }
273
274 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
275 self.wait(Sense::Both).await;
276 Ok(())
277 }
278 }
279}
280
281#[hal_cfg("eic-d11")]
287mod impls {
288 use super::*;
289
290 ei!(ExtInt[1] {
291 #[hal_cfg("pa15")]
292 PA15,
293 });
294
295 ei!(ExtInt[2] {
296 #[hal_cfg("pa02")]
297 PA02,
298 });
299
300 ei!(ExtInt[3] {
301 #[hal_cfg("pa31")]
302 PA31,
303 });
304
305 ei!(ExtInt[4] {
306 #[hal_cfg("pa04")]
307 PA04,
308 #[hal_cfg("pa24")]
309 PA24,
310 });
311
312 ei!(ExtInt[5] {
313 #[hal_cfg("pa05")]
314 PA05,
315 #[hal_cfg("pa25")]
316 PA25,
317 });
318
319 ei!(ExtInt[6] {
320 #[hal_cfg("pa08")]
321 PA08,
322 });
323
324 ei!(ExtInt[7] {
325 #[hal_cfg("pa09")]
326 PA09,
327 });
328}
329
330#[hal_cfg("eic-d21")]
332mod impls {
333 use super::*;
334
335 ei!(ExtInt[0] {
336 #[hal_cfg("pa00")]
337 PA00,
338 #[hal_cfg("pa16")]
339 PA16,
340 #[hal_cfg("pb00")]
341 PB00,
342 #[hal_cfg("pb16")]
343 PB16,
344 });
345
346 ei!(ExtInt[1] {
347 #[hal_cfg("pa01")]
348 PA01,
349 #[hal_cfg("pa17")]
350 PA17,
351 #[hal_cfg("pb01")]
352 PB01,
353 #[hal_cfg("pb17")]
354 PB17,
355 });
356
357 ei!(ExtInt[2] {
358 #[hal_cfg("pa02")]
359 PA02,
360 #[hal_cfg("pa18")]
361 PA18,
362 #[hal_cfg("pb02")]
363 PB02,
364 });
365
366 ei!(ExtInt[3] {
367 #[hal_cfg("pa03")]
368 PA03,
369 #[hal_cfg("pa19")]
370 PA19,
371 #[hal_cfg("pb03")]
372 PB03,
373 });
374
375 ei!(ExtInt[4] {
376 #[hal_cfg("pa04")]
377 PA04,
378 #[hal_cfg("pa20")]
379 PA20,
380 #[hal_cfg("pb04")]
381 PB04,
382 });
383
384 ei!(ExtInt[5] {
385 #[hal_cfg("pa05")]
386 PA05,
387 #[hal_cfg("pa21")]
388 PA21,
389 #[hal_cfg("pb05")]
390 PB05,
391 });
392
393 ei!(ExtInt[6] {
394 #[hal_cfg("pa06")]
395 PA06,
396 #[hal_cfg("pa22")]
397 PA22,
398 #[hal_cfg("pb06")]
399 PB06,
400 #[hal_cfg("pb22")]
401 PB22,
402 });
403
404 ei!(ExtInt[7] {
405 #[hal_cfg("pa07")]
406 PA07,
407 #[hal_cfg("pa23")]
408 PA23,
409 #[hal_cfg("pb07")]
410 PB07,
411 #[hal_cfg("pb23")]
412 PB23,
413 });
414
415 ei!(ExtInt[8] {
416 #[hal_cfg("pa28")]
417 PA28,
418 #[hal_cfg("pb08")]
419 PB08,
420 });
421
422 ei!(ExtInt[9] {
423 #[hal_cfg("pa09")]
424 PA09,
425 #[hal_cfg("pb09")]
426 PB09,
427 });
428
429 ei!(ExtInt[10] {
430 #[hal_cfg("pa10")]
431 PA10,
432 #[hal_cfg("pa30")]
433 PA30,
434 #[hal_cfg("pb10")]
435 PB10,
436 });
437
438 ei!(ExtInt[11] {
439 #[hal_cfg("pa11")]
440 PA11,
441 #[hal_cfg("pa31")]
442 PA31,
443 #[hal_cfg("pb11")]
444 PB11,
445 });
446
447 ei!(ExtInt[12] {
448 #[hal_cfg("pa12")]
449 PA12,
450 #[hal_cfg("pa24")]
451 PA24,
452 #[hal_cfg("pb12")]
453 PB12,
454 });
455
456 ei!(ExtInt[13] {
457 #[hal_cfg("pa13")]
458 PA13,
459 #[hal_cfg("pa25")]
460 PA25,
461 #[hal_cfg("pb13")]
462 PB13,
463 });
464
465 ei!(ExtInt[14] {
466 #[hal_cfg("pa14")]
467 PA14,
468 #[hal_cfg("pb14")]
469 PB14,
470 #[hal_cfg("pb30")]
471 PB30,
472 });
473
474 ei!(ExtInt[15] {
475 #[hal_cfg("pa15")]
476 PA15,
477 #[hal_cfg("pa27")]
478 PA27,
479 #[hal_cfg("pb15")]
480 PB15,
481 #[hal_cfg("pb31")]
482 PB31,
483 });
484}