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, pin::*, AnyPin, FloatingInterrupt, PinMode, PullDownInterrupt, PullUpInterrupt,
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 => {
217 if self.is_high().unwrap() {
218 return;
219 }
220 }
221 Sense::Low => {
222 if self.is_low().unwrap() {
223 return;
224 }
225 }
226 _ => (),
227 }
228
229 self.enable_interrupt_wake();
230 self.sense(sense);
231 poll_fn(|cx| {
232 if self.is_interrupt() {
233 self.clear_interrupt();
234 self.disable_interrupt();
235 self.sense(Sense::None);
236 return Poll::Ready(());
237 }
238
239 WAKERS[P::ChId::ID].register(cx.waker());
240 self.enable_interrupt();
241
242 if self.is_interrupt() {
243 self.clear_interrupt();
244 self.disable_interrupt();
245 self.sense(Sense::None);
246 return Poll::Ready(());
247 }
248
249 Poll::Pending
250 })
251 .await;
252 }
253 }
254
255 impl<P, Id> Wait for ExtInt<P, Id, EicFuture>
256 where
257 P: EicPin,
258 Id: ChId,
259 Self: InputPin<Error = Infallible>,
260 {
261 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
262 self.wait(Sense::High).await;
263 Ok(())
264 }
265
266 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
267 self.wait(Sense::Low).await;
268 Ok(())
269 }
270
271 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
272 self.wait(Sense::Rise).await;
273 Ok(())
274 }
275
276 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
277 self.wait(Sense::Fall).await;
278 Ok(())
279 }
280
281 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
282 self.wait(Sense::Both).await;
283 Ok(())
284 }
285 }
286}
287
288#[hal_cfg("eic-d11")]
294mod impls {
295 use super::*;
296
297 ei!(ExtInt[1] {
298 #[hal_cfg("pa15")]
299 PA15,
300 });
301
302 ei!(ExtInt[2] {
303 #[hal_cfg("pa02")]
304 PA02,
305 });
306
307 ei!(ExtInt[3] {
308 #[hal_cfg("pa31")]
309 PA31,
310 });
311
312 ei!(ExtInt[4] {
313 #[hal_cfg("pa04")]
314 PA04,
315 #[hal_cfg("pa24")]
316 PA24,
317 });
318
319 ei!(ExtInt[5] {
320 #[hal_cfg("pa05")]
321 PA05,
322 #[hal_cfg("pa25")]
323 PA25,
324 });
325
326 ei!(ExtInt[6] {
327 #[hal_cfg("pa08")]
328 PA08,
329 });
330
331 ei!(ExtInt[7] {
332 #[hal_cfg("pa09")]
333 PA09,
334 });
335}
336
337#[hal_cfg("eic-d21")]
339mod impls {
340 use super::*;
341
342 ei!(ExtInt[0] {
343 #[hal_cfg("pa00")]
344 PA00,
345 #[hal_cfg("pa16")]
346 PA16,
347 #[hal_cfg("pb00")]
348 PB00,
349 #[hal_cfg("pb16")]
350 PB16,
351 });
352
353 ei!(ExtInt[1] {
354 #[hal_cfg("pa01")]
355 PA01,
356 #[hal_cfg("pa17")]
357 PA17,
358 #[hal_cfg("pb01")]
359 PB01,
360 #[hal_cfg("pb17")]
361 PB17,
362 });
363
364 ei!(ExtInt[2] {
365 #[hal_cfg("pa02")]
366 PA02,
367 #[hal_cfg("pa18")]
368 PA18,
369 #[hal_cfg("pb02")]
370 PB02,
371 });
372
373 ei!(ExtInt[3] {
374 #[hal_cfg("pa03")]
375 PA03,
376 #[hal_cfg("pa19")]
377 PA19,
378 #[hal_cfg("pb03")]
379 PB03,
380 });
381
382 ei!(ExtInt[4] {
383 #[hal_cfg("pa04")]
384 PA04,
385 #[hal_cfg("pa20")]
386 PA20,
387 #[hal_cfg("pb04")]
388 PB04,
389 });
390
391 ei!(ExtInt[5] {
392 #[hal_cfg("pa05")]
393 PA05,
394 #[hal_cfg("pa21")]
395 PA21,
396 #[hal_cfg("pb05")]
397 PB05,
398 });
399
400 ei!(ExtInt[6] {
401 #[hal_cfg("pa06")]
402 PA06,
403 #[hal_cfg("pa22")]
404 PA22,
405 #[hal_cfg("pb06")]
406 PB06,
407 #[hal_cfg("pb22")]
408 PB22,
409 });
410
411 ei!(ExtInt[7] {
412 #[hal_cfg("pa07")]
413 PA07,
414 #[hal_cfg("pa23")]
415 PA23,
416 #[hal_cfg("pb07")]
417 PB07,
418 #[hal_cfg("pb23")]
419 PB23,
420 });
421
422 ei!(ExtInt[8] {
423 #[hal_cfg("pa28")]
424 PA28,
425 #[hal_cfg("pb08")]
426 PB08,
427 });
428
429 ei!(ExtInt[9] {
430 #[hal_cfg("pa09")]
431 PA09,
432 #[hal_cfg("pb09")]
433 PB09,
434 });
435
436 ei!(ExtInt[10] {
437 #[hal_cfg("pa10")]
438 PA10,
439 #[hal_cfg("pa30")]
440 PA30,
441 #[hal_cfg("pb10")]
442 PB10,
443 });
444
445 ei!(ExtInt[11] {
446 #[hal_cfg("pa11")]
447 PA11,
448 #[hal_cfg("pa31")]
449 PA31,
450 #[hal_cfg("pb11")]
451 PB11,
452 });
453
454 ei!(ExtInt[12] {
455 #[hal_cfg("pa12")]
456 PA12,
457 #[hal_cfg("pa24")]
458 PA24,
459 #[hal_cfg("pb12")]
460 PB12,
461 });
462
463 ei!(ExtInt[13] {
464 #[hal_cfg("pa13")]
465 PA13,
466 #[hal_cfg("pa25")]
467 PA25,
468 #[hal_cfg("pb13")]
469 PB13,
470 });
471
472 ei!(ExtInt[14] {
473 #[hal_cfg("pa14")]
474 PA14,
475 #[hal_cfg("pb14")]
476 PB14,
477 #[hal_cfg("pb30")]
478 PB30,
479 });
480
481 ei!(ExtInt[15] {
482 #[hal_cfg("pa15")]
483 PA15,
484 #[hal_cfg("pa27")]
485 PA27,
486 #[hal_cfg("pb15")]
487 PB15,
488 #[hal_cfg("pb31")]
489 PB31,
490 });
491}