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