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