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