1use atsamd_hal_macros::hal_cfg;
2
3use core::convert::Infallible;
4use crate::ehal_02::digital::v2::InputPin as InputPin_02;
5use crate::ehal::digital::{ErrorType, InputPin};
6use crate::eic::*;
7use crate::gpio::{
8 self, pin::*, AnyPin, FloatingInterrupt, PinMode, PullDownInterrupt, PullUpInterrupt,
9};
10
11#[allow(unused_macros)]
15macro_rules! ei {
16 (
17 $PadType:ident [ $num:expr ] {
18 $(
19 $(#[$attr:meta])*
20 $PinType:ident,
21 )+
22 }
23 ) => {
24
25 crate::paste::item! {
26 $(
27 $(#[$attr])*
28 impl<M: PinMode> EicPin for Pin<gpio::$PinType, M> {
29 type Floating = ExtInt<Pin<gpio::$PinType, FloatingInterrupt>, Self::ChId>;
30 type PullUp = ExtInt<Pin<gpio::$PinType, PullUpInterrupt>, Self::ChId>;
31 type PullDown = ExtInt<Pin<gpio::$PinType, PullDownInterrupt>, Self::ChId>;
32
33 type ChId = [<Ch $num>];
34
35 #[cfg(feature = "async")]
36 type InterruptSource = crate::async_hal::interrupts::[<EIC_EXTINT_ $num>];
37
38 fn into_floating_ei(self, channel: Channel<Self::ChId>) -> Self::Floating {
39 ExtInt::new(self.into_floating_interrupt(), channel)
40 }
41
42 fn into_pull_up_ei(self,channel: Channel<Self::ChId>) -> Self::PullUp {
43 ExtInt::new(self.into_pull_up_interrupt(), channel)
44 }
45
46 fn into_pull_down_ei(self, channel: Channel<Self::ChId>) -> Self::PullDown {
47 ExtInt::new(self.into_pull_down_interrupt(), channel)
48 }
49 }
50 )+
51
52 }
53 };
54}
55
56impl<P, Id, F> ExtInt<P, Id, F>
57where
58 P: EicPin,
59 Id: ChId,
60{
61 pub fn enable_event(&mut self) {
62 self.chan
63 .eic
64 .evctrl()
65 .modify(|_, w| unsafe { w.bits(1 << P::ChId::ID) });
66 }
67
68 pub fn enable_interrupt(&mut self) {
69 self.chan
70 .eic
71 .intenset()
72 .write(|w| unsafe { w.bits(1 << P::ChId::ID) })
73 }
74
75 pub fn disable_interrupt(&mut self) {
76 self.chan
77 .eic
78 .intenclr()
79 .write(|w| unsafe { w.bits(1 << P::ChId::ID) })
80 }
81
82 pub fn is_interrupt(&mut self) -> bool {
83 let intflag = self.chan.eic.intflag().read().bits();
84 intflag & (1 << P::ChId::ID) != 0
85 }
86
87 pub fn state(&mut self) -> bool {
88 let state = self.chan.eic.pinstate().read().bits();
89 state & (1 << P::ChId::ID) != 0
90 }
91
92 pub fn clear_interrupt(&mut self) {
93 unsafe {
94 self.chan.eic.intflag().write(|w| w.bits(1 << P::ChId::ID));
95 }
96 }
97
98 pub fn sense(&mut self, sense: Sense) {
99 self.chan.with_disable(|e| {
100 let offset = (P::ChId::ID >> 3) & 0b0001;
102 let config = &e.config(offset);
103
104 config.modify(|_, w| unsafe {
105 match P::ChId::ID & 0b111 {
107 0b000 => w.sense0().bits(sense as u8),
108 0b001 => w.sense1().bits(sense as u8),
109 0b010 => w.sense2().bits(sense as u8),
110 0b011 => w.sense3().bits(sense as u8),
111 0b100 => w.sense4().bits(sense as u8),
112 0b101 => w.sense5().bits(sense as u8),
113 0b110 => w.sense6().bits(sense as u8),
114 0b111 => w.sense7().bits(sense as u8),
115 _ => unreachable!(),
116 }
117 });
118 });
119 }
120
121 pub fn filter(&mut self, filter: bool) {
122 self.chan.with_disable(|e| {
123 let offset = (P::ChId::ID >> 3) & 0b0001;
125 let config = &e.config(offset);
126
127 config.modify(|_, w| {
128 match P::ChId::ID & 0b111 {
130 0b000 => w.filten0().bit(filter),
131 0b001 => w.filten1().bit(filter),
132 0b010 => w.filten2().bit(filter),
133 0b011 => w.filten3().bit(filter),
134 0b100 => w.filten4().bit(filter),
135 0b101 => w.filten5().bit(filter),
136 0b110 => w.filten6().bit(filter),
137 0b111 => w.filten7().bit(filter),
138 _ => unreachable!(),
139 }
140 });
141 });
142 }
143
144 pub fn debounce(&mut self) {
146 self.chan.with_disable(|e| {
147 e.dprescaler().modify(|_, w| {
148 w.tickon().set_bit() .states0().set_bit() .states1().set_bit() .prescaler0().div16()
152 .prescaler1().div16()
153 });
154
155 e.debouncen()
156 .modify(|_, w| unsafe { w.bits(P::ChId::ID as u32) });
157 });
158 }
159}
160
161impl<P, C, Id, F> InputPin_02 for ExtInt<P, Id, F>
162where
163 P: EicPin + AnyPin<Mode = Interrupt<C>>,
164 C: InterruptConfig,
165 Id: ChId,
166{
167 type Error = Infallible;
168 #[inline]
169 fn is_high(&self) -> Result<bool, Self::Error> {
170 self.pin.is_high()
171 }
172 #[inline]
173 fn is_low(&self) -> Result<bool, Self::Error> {
174 self.pin.is_low()
175 }
176}
177
178impl<P, Id, F> InputPin for ExtInt<P, Id, F>
179where Self: ErrorType,
180 P: EicPin,
181 Id: ChId,
182{
183 #[inline]
184 fn is_high(&mut self) -> Result<bool, Self::Error> {
185 Ok(self.pin._is_high())
186 }
187
188 #[inline]
189 fn is_low(&mut self) -> Result<bool, Self::Error> {
190 Ok(self.pin._is_low())
191 }
192}
193
194impl<P, Id, F> ErrorType for ExtInt<P, Id, F>
195where
196 P: EicPin,
197 Id: ChId,
198{
199 type Error = Infallible;
200}
201
202#[cfg(feature = "async")]
203mod async_impls {
204 use embedded_hal_async::digital::Wait;
205
206 use crate::{
207 async_hal::interrupts::{Binding, Handler, InterruptSource},
208 eic::EicFuture,
209 typelevel::NoneT,
210 };
211
212 use super::{
213 super::async_api::{InterruptHandler, WAKERS},
214 *,
215 };
216
217 impl<P, Id> ExtInt<P, Id, NoneT>
218 where
219 P: EicPin,
220 Id: ChId,
221 {
222 pub fn into_future<I>(self, _irq: I) -> ExtInt<P, Id, EicFuture>
225 where
226 I: Binding<P::InterruptSource, InterruptHandler>,
227 InterruptHandler: Handler<P::InterruptSource>,
228 {
229 P::InterruptSource::unpend();
230 unsafe { P::InterruptSource::enable() };
231
232 ExtInt {
233 pin: self.pin,
234 chan: self.chan.change_mode(),
235 }
236 }
237 }
238
239 impl<P, Id> ExtInt<P, Id, EicFuture>
240 where
241 P: EicPin,
242 Self: InputPin<Error = Infallible>,
243 Id: ChId,
244 {
245 pub async fn wait(&mut self, sense: Sense) {
246 use core::{future::poll_fn, task::Poll};
247 self.disable_interrupt();
248
249 self.sense(sense);
250 poll_fn(|cx| {
251 if self.is_interrupt() {
252 self.clear_interrupt();
253 self.disable_interrupt();
254 self.sense(Sense::None);
255 return Poll::Ready(());
256 }
257
258 WAKERS[P::ChId::ID].register(cx.waker());
259 self.enable_interrupt();
260
261 if self.is_interrupt() {
262 self.clear_interrupt();
263 self.disable_interrupt();
264 self.sense(Sense::None);
265 return Poll::Ready(());
266 }
267
268 Poll::Pending
269 })
270 .await;
271 }
272 }
273
274 impl<P, Id> Wait for ExtInt<P, Id, EicFuture>
275 where
276 P: EicPin,
277 Self: InputPin<Error = Infallible>,
278 Id: ChId,
279 {
280 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
281 self.wait(Sense::High).await;
282 Ok(())
283 }
284
285 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
286 self.wait(Sense::Low).await;
287 Ok(())
288 }
289
290 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
291 self.wait(Sense::Rise).await;
292 Ok(())
293 }
294
295 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
296 self.wait(Sense::Fall).await;
297 Ok(())
298 }
299
300 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
301 self.wait(Sense::Both).await;
302 Ok(())
303 }
304 }
305}
306
307ei!(ExtInt[0] {
308 #[hal_cfg("pa00")]
309 PA00,
310 #[hal_cfg("pa16")]
311 PA16,
312 #[hal_cfg("pb00")]
313 PB00,
314 #[hal_cfg("pb16")]
315 PB16,
316 #[hal_cfg("pc00")]
317 PC00,
318 #[hal_cfg("pc16")]
319 PC16,
320 #[hal_cfg("pd00")]
321 PD00,
322});
323
324ei!(ExtInt[1] {
325 #[hal_cfg("pa01")]
326 PA01,
327 #[hal_cfg("pa17")]
328 PA17,
329 #[hal_cfg("pb01")]
330 PB01,
331 #[hal_cfg("pb17")]
332 PB17,
333 #[hal_cfg("pc01")]
334 PC01,
335 #[hal_cfg("pc17")]
336 PC17,
337 #[hal_cfg("pd01")]
338 PD01,
339});
340
341ei!(ExtInt[2] {
342 #[hal_cfg("pa02")]
343 PA02,
344 #[hal_cfg("pa18")]
345 PA18,
346 #[hal_cfg("pb02")]
347 PB02,
348 #[hal_cfg("pb18")]
349 PB18,
350 #[hal_cfg("pc02")]
351 PC02,
352 #[hal_cfg("pc18")]
353 PC18,
354});
355
356ei!(ExtInt[3] {
357 #[hal_cfg("pa03")]
358 PA03,
359 #[hal_cfg("pa19")]
360 PA19,
361 #[hal_cfg("pb03")]
362 PB03,
363 #[hal_cfg("pb19")]
364 PB19,
365 #[hal_cfg("pc03")]
366 PC03,
367 #[hal_cfg("pc19")]
368 PC19,
369 #[hal_cfg("pd08")]
370 PD08,
371});
372
373ei!(ExtInt[4] {
374 #[hal_cfg("pa04")]
375 PA04,
376 #[hal_cfg("pa20")]
377 PA20,
378 #[hal_cfg("pb04")]
379 PB04,
380 #[hal_cfg("pb20")]
381 PB20,
382 #[hal_cfg("pc04")]
383 PC04,
384 #[hal_cfg("pc20")]
385 PC20,
386 #[hal_cfg("pd09")]
387 PD09,
388});
389
390ei!(ExtInt[5] {
391 #[hal_cfg("pa05")]
392 PA05,
393 #[hal_cfg("pa21")]
394 PA21,
395 #[hal_cfg("pb05")]
396 PB05,
397 #[hal_cfg("pb21")]
398 PB21,
399 #[hal_cfg("pc05")]
400 PC05,
401 #[hal_cfg("pc21")]
402 PC21,
403 #[hal_cfg("pd10")]
404 PD10,
405});
406
407ei!(ExtInt[6] {
408 #[hal_cfg("pa06")]
409 PA06,
410 #[hal_cfg("pa22")]
411 PA22,
412 #[hal_cfg("pb06")]
413 PB06,
414 #[hal_cfg("pb22")]
415 PB22,
416 #[hal_cfg("pc06")]
417 PC06,
418 #[hal_cfg("pc22")]
419 PC22,
420 #[hal_cfg("pd11")]
421 PD11,
422});
423
424ei!(ExtInt[7] {
425 #[hal_cfg("pa07")]
426 PA07,
427 #[hal_cfg("pa23")]
428 PA23,
429 #[hal_cfg("pb07")]
430 PB07,
431 #[hal_cfg("pb23")]
432 PB23,
433 #[hal_cfg("pc23")]
434 PC23,
435 #[hal_cfg("pd12")]
436 PD12,
437});
438
439ei!(ExtInt[8] {
440 #[hal_cfg("pa24")]
441 PA24,
442 #[hal_cfg("pb08")]
443 PB08,
444 #[hal_cfg("pb24")]
445 PB24,
446 #[hal_cfg("pc24")]
447 PC24,
448});
449
450ei!(ExtInt[9] {
451 #[hal_cfg("pa09")]
452 PA09,
453 #[hal_cfg("pa25")]
454 PA25,
455 #[hal_cfg("pb09")]
456 PB09,
457 #[hal_cfg("pb25")]
458 PB25,
459 #[hal_cfg("pc07")]
460 PC07,
461 #[hal_cfg("pc25")]
462 PC25,
463});
464
465ei!(ExtInt[10] {
466 #[hal_cfg("pa10")]
467 PA10,
468 #[hal_cfg("pb10")]
469 PB10,
470 #[hal_cfg("pc10")]
471 PC10,
472 #[hal_cfg("pc26")]
473 PC26,
474 #[hal_cfg("pd20")]
475 PD20,
476});
477
478ei!(ExtInt[11] {
479 #[hal_cfg("pa11")]
480 PA11,
481 #[hal_cfg("pa27")]
482 PA27,
483 #[hal_cfg("pb11")]
484 PB11,
485 #[hal_cfg("pc11")]
486 PC11,
487 #[hal_cfg("pc27")]
488 PC27,
489 #[hal_cfg("pd21")]
490 PD21,
491});
492
493ei!(ExtInt[12] {
494 #[hal_cfg("pa12")]
495 PA12,
496 #[hal_cfg("pb12")]
497 PB12,
498 #[hal_cfg("pb26")]
499 PB26,
500 #[hal_cfg("pc12")]
501 PC12,
502 #[hal_cfg("pc28")]
503 PC28,
504});
505
506ei!(ExtInt[13] {
507 #[hal_cfg("pa13")]
508 PA13,
509 #[hal_cfg("pb13")]
510 PB13,
511 #[hal_cfg("pb27")]
512 PB27,
513 #[hal_cfg("pc13")]
514 PC13,
515});
516
517ei!(ExtInt[14] {
518 #[hal_cfg("pa14")]
519 PA14,
520 #[hal_cfg("pa30")]
521 PA30,
522 #[hal_cfg("pb14")]
523 PB14,
524 #[hal_cfg("pb28")]
525 PB28,
526 #[hal_cfg("pb30")]
527 PB30,
528 #[hal_cfg("pc14")]
529 PC14,
530 #[hal_cfg("pc30")]
531 PC30,
532});
533
534ei!(ExtInt[15] {
535 #[hal_cfg("pa15")]
536 PA15,
537 #[hal_cfg("pa31")]
538 PA31,
539 #[hal_cfg("pb15")]
540 PB15,
541 #[hal_cfg("pb29")]
542 PB29,
543 #[hal_cfg("pb31")]
544 PB31,
545 #[hal_cfg("pc15")]
546 PC15,
547 #[hal_cfg("pc31")]
548 PC31,
549});