1#![cfg_attr(not(target_os = "none"), allow(dead_code))]
161
162pub mod ir_generated;
163mod kepler;
164mod mapping;
165
166pub use device_envoy_core::ir::{Ir, IrEvent, IrKepler, IrMapping};
167#[doc(hidden)]
169pub use device_envoy_core::ir::IrStatic as __IrStatic;
170#[doc(hidden)]
172pub use device_envoy_core::ir::kepler::KEPLER_MAPPING as __KEPLER_MAPPING;
173pub use kepler::KeplerKeys;
175pub use mapping::__build_button_map;
176#[doc(hidden)]
177pub use paste;
178
179#[cfg(target_os = "none")]
180use device_envoy_core::ir::decode_nec_frame;
181
182#[doc(hidden)]
184#[cfg(target_os = "none")]
185pub async fn __ir_receiver_task_loop(
186 mut channel: esp_hal::rmt::Channel<'static, esp_hal::Async, esp_hal::rmt::Rx>,
187 ir_static: &'static __IrStatic,
188) -> ! {
189 let mut pulse_codes = [esp_hal::rmt::PulseCode::default(); 96];
190
191 loop {
192 for pulse_code in &mut pulse_codes {
193 pulse_code.reset();
194 }
195
196 if let Ok(symbol_count) = channel.receive(&mut pulse_codes).await {
197 if let Some((addr, cmd)) = decode_nec_from_pulses(&pulse_codes[..symbol_count]) {
198 ir_static.send(IrEvent::Press { addr, cmd }).await;
199 }
200 }
201 }
202}
203
204#[cfg(target_os = "none")]
205fn decode_nec_from_pulses(pulse_codes: &[esp_hal::rmt::PulseCode]) -> Option<(u16, u8)> {
206 use esp_hal::gpio::Level;
207
208 let mut runs = [(Level::Low, 0u16); 256];
209 let mut run_count = 0usize;
210
211 for pulse_code in pulse_codes {
212 let length1 = pulse_code.length1();
213 if length1 > 0 && run_count < runs.len() {
214 runs[run_count] = (pulse_code.level1(), length1);
215 run_count += 1;
216 }
217
218 let length2 = pulse_code.length2();
219 if length2 == 0 {
220 break;
221 }
222 if run_count < runs.len() {
223 runs[run_count] = (pulse_code.level2(), length2);
224 run_count += 1;
225 }
226 }
227
228 if run_count < 2 {
229 return None;
230 }
231
232 if is_nec_repeat_runs(&runs[..run_count]) {
233 return None;
234 }
235
236 let mut leader_index = None;
237 for run_index in 0..(run_count - 1) {
238 let (level0, duration0) = runs[run_index];
239 let (level1, duration1) = runs[run_index + 1];
240 if level0 == Level::Low
241 && level1 == Level::High
242 && within(duration0, 9000, 2200)
243 && within(duration1, 4500, 1600)
244 {
245 leader_index = Some(run_index + 2);
246 break;
247 }
248 }
249 let mut run_index = leader_index?;
250
251 let mut frame = 0u32;
252 for bit_index in 0..32u32 {
253 if run_index + 1 >= run_count {
254 return None;
255 }
256 let (mark_level, mark_duration) = runs[run_index];
257 let (space_level, space_duration) = runs[run_index + 1];
258 run_index += 2;
259
260 if mark_level != Level::Low || space_level != Level::High {
261 return None;
262 }
263 if !(250..=900).contains(&mark_duration) {
264 return None;
265 }
266
267 let bit_value = if (250..=900).contains(&space_duration) {
268 0u32
269 } else if (1200..=2200).contains(&space_duration) {
270 1u32
271 } else {
272 return None;
273 };
274
275 frame |= bit_value << bit_index;
276 }
277
278 decode_nec_frame(frame)
280}
281
282#[inline]
283#[cfg(target_os = "none")]
284fn within(value: u16, target: u16, tolerance: u16) -> bool {
285 let min = target.saturating_sub(tolerance);
286 let max = target.saturating_add(tolerance);
287 (min..=max).contains(&value)
288}
289
290#[cfg(target_os = "none")]
291fn is_nec_repeat_runs(runs: &[(esp_hal::gpio::Level, u16)]) -> bool {
292 use esp_hal::gpio::Level;
293
294 if runs.len() < 2 {
295 return false;
296 }
297
298 let (level0, duration0) = runs[0];
299 let (level1, duration1) = runs[1];
300
301 level0 == Level::Low
302 && level1 == Level::High
303 && within(duration0, 9000, 2200)
304 && within(duration1, 2250, 1000)
305}
306
307#[doc(hidden)]
308#[macro_export]
309macro_rules! irs {
310 (
311 $group_name:ident {
312 $first_name:ident : { pin: $first_pin:ident $(,)? }
313 $(, $rest_name:ident : { pin: $rest_pin:ident $(,)? })* $(,)?
314 }
315 ) => {
316 $crate::__irs_impl! {
317 $group_name,
318 [($first_name, $first_pin) $(, ($rest_name, $rest_pin))*]
319 }
320 };
321}
322
323#[doc(hidden)]
325#[macro_export]
326macro_rules! __irs_impl {
327 (
328 $group_name:ident,
329 [($name0:ident, $pin0:ident)]
330 ) => {
331 $crate::ir::paste::paste! {
332 static [<$name0:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
333 static [<$name0:upper _IR>]: $name0 = $name0 { ir_static: &[<$name0:upper _IR_STATIC>] };
334
335 #[embassy_executor::task]
336 async fn [<__ $name0:lower _ir_receiver_task>](
337 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
338 ir_static: &'static $crate::ir::__IrStatic,
339 ) -> ! {
340 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
341 }
342
343 pub struct $name0 {
344 ir_static: &'static $crate::ir::__IrStatic,
345 }
346
347 impl $name0 {
348 pub fn new(
349 pin: $crate::esp_hal::peripherals::$pin0<'static>,
350 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
351 spawner: embassy_executor::Spawner,
352 ) -> $crate::Result<&'static Self> {
353 let channel = channel_creator
354 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
355 .map_err($crate::Error::Rmt)?;
356 spawner
357 .spawn([<__ $name0:lower _ir_receiver_task>](channel, &[<$name0:upper _IR_STATIC>]))
358 .map_err($crate::Error::TaskSpawn)?;
359 Ok(&[<$name0:upper _IR>])
360 }
361 }
362
363 impl $crate::ir::Ir for $name0 {
364 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
365 self.ir_static.receive().await
366 }
367 }
368
369 pub struct $group_name;
370 impl $group_name {
371 pub fn new(
372 pin0: $crate::esp_hal::peripherals::$pin0<'static>,
373 channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
374 spawner: embassy_executor::Spawner,
375 ) -> $crate::Result<(&'static $name0,)> {
376 let name0 = $name0::new(pin0, channel_creator0, spawner)?;
377 Ok((name0,))
378 }
379 }
380 }
381 };
382 (
383 $group_name:ident,
384 [($name0:ident, $pin0:ident), ($name1:ident, $pin1:ident)]
385 ) => {
386 $crate::ir::paste::paste! {
387 static [<$name0:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
388 static [<$name1:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
389
390 static [<$name0:upper _IR>]: $name0 = $name0 { ir_static: &[<$name0:upper _IR_STATIC>] };
391 static [<$name1:upper _IR>]: $name1 = $name1 { ir_static: &[<$name1:upper _IR_STATIC>] };
392
393 #[embassy_executor::task]
394 async fn [<__ $name0:lower _ir_receiver_task>](
395 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
396 ir_static: &'static $crate::ir::__IrStatic,
397 ) -> ! {
398 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
399 }
400
401 #[embassy_executor::task]
402 async fn [<__ $name1:lower _ir_receiver_task>](
403 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
404 ir_static: &'static $crate::ir::__IrStatic,
405 ) -> ! {
406 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
407 }
408
409 pub struct $name0 {
410 ir_static: &'static $crate::ir::__IrStatic,
411 }
412
413 pub struct $name1 {
414 ir_static: &'static $crate::ir::__IrStatic,
415 }
416
417 impl $name0 {
418 pub fn new(
419 pin: $crate::esp_hal::peripherals::$pin0<'static>,
420 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
421 spawner: embassy_executor::Spawner,
422 ) -> $crate::Result<&'static Self> {
423 let channel = channel_creator
424 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
425 .map_err($crate::Error::Rmt)?;
426 spawner
427 .spawn([<__ $name0:lower _ir_receiver_task>](channel, &[<$name0:upper _IR_STATIC>]))
428 .map_err($crate::Error::TaskSpawn)?;
429 Ok(&[<$name0:upper _IR>])
430 }
431 }
432
433 impl $name1 {
434 pub fn new(
435 pin: $crate::esp_hal::peripherals::$pin1<'static>,
436 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
437 spawner: embassy_executor::Spawner,
438 ) -> $crate::Result<&'static Self> {
439 let channel = channel_creator
440 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
441 .map_err($crate::Error::Rmt)?;
442 spawner
443 .spawn([<__ $name1:lower _ir_receiver_task>](channel, &[<$name1:upper _IR_STATIC>]))
444 .map_err($crate::Error::TaskSpawn)?;
445 Ok(&[<$name1:upper _IR>])
446 }
447 }
448
449 impl $crate::ir::Ir for $name0 {
450 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
451 self.ir_static.receive().await
452 }
453 }
454
455 impl $crate::ir::Ir for $name1 {
456 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
457 self.ir_static.receive().await
458 }
459 }
460
461 pub struct $group_name;
462 impl $group_name {
463 pub fn new(
464 pin0: $crate::esp_hal::peripherals::$pin0<'static>,
465 channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
466 pin1: $crate::esp_hal::peripherals::$pin1<'static>,
467 channel_creator1: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
468 spawner: embassy_executor::Spawner,
469 ) -> $crate::Result<(&'static $name0, &'static $name1)> {
470 let name0 = $name0::new(pin0, channel_creator0, spawner)?;
471 let name1 = $name1::new(pin1, channel_creator1, spawner)?;
472 Ok((name0, name1))
473 }
474 }
475 }
476 };
477 (
478 $group_name:ident,
479 [($name0:ident, $pin0:ident), ($name1:ident, $pin1:ident), ($name2:ident, $pin2:ident)]
480 ) => {
481 $crate::ir::paste::paste! {
482 static [<$name0:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
483 static [<$name1:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
484 static [<$name2:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
485
486 static [<$name0:upper _IR>]: $name0 = $name0 { ir_static: &[<$name0:upper _IR_STATIC>] };
487 static [<$name1:upper _IR>]: $name1 = $name1 { ir_static: &[<$name1:upper _IR_STATIC>] };
488 static [<$name2:upper _IR>]: $name2 = $name2 { ir_static: &[<$name2:upper _IR_STATIC>] };
489
490 #[embassy_executor::task]
491 async fn [<__ $name0:lower _ir_receiver_task>](
492 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
493 ir_static: &'static $crate::ir::__IrStatic,
494 ) -> ! {
495 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
496 }
497
498 #[embassy_executor::task]
499 async fn [<__ $name1:lower _ir_receiver_task>](
500 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
501 ir_static: &'static $crate::ir::__IrStatic,
502 ) -> ! {
503 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
504 }
505
506 #[embassy_executor::task]
507 async fn [<__ $name2:lower _ir_receiver_task>](
508 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
509 ir_static: &'static $crate::ir::__IrStatic,
510 ) -> ! {
511 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
512 }
513
514 pub struct $name0 {
515 ir_static: &'static $crate::ir::__IrStatic,
516 }
517
518 pub struct $name1 {
519 ir_static: &'static $crate::ir::__IrStatic,
520 }
521
522 pub struct $name2 {
523 ir_static: &'static $crate::ir::__IrStatic,
524 }
525
526 impl $name0 {
527 pub fn new(
528 pin: $crate::esp_hal::peripherals::$pin0<'static>,
529 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
530 spawner: embassy_executor::Spawner,
531 ) -> $crate::Result<&'static Self> {
532 let channel = channel_creator
533 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
534 .map_err($crate::Error::Rmt)?;
535 spawner
536 .spawn([<__ $name0:lower _ir_receiver_task>](channel, &[<$name0:upper _IR_STATIC>]))
537 .map_err($crate::Error::TaskSpawn)?;
538 Ok(&[<$name0:upper _IR>])
539 }
540 }
541
542 impl $name1 {
543 pub fn new(
544 pin: $crate::esp_hal::peripherals::$pin1<'static>,
545 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
546 spawner: embassy_executor::Spawner,
547 ) -> $crate::Result<&'static Self> {
548 let channel = channel_creator
549 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
550 .map_err($crate::Error::Rmt)?;
551 spawner
552 .spawn([<__ $name1:lower _ir_receiver_task>](channel, &[<$name1:upper _IR_STATIC>]))
553 .map_err($crate::Error::TaskSpawn)?;
554 Ok(&[<$name1:upper _IR>])
555 }
556 }
557
558 impl $name2 {
559 pub fn new(
560 pin: $crate::esp_hal::peripherals::$pin2<'static>,
561 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
562 spawner: embassy_executor::Spawner,
563 ) -> $crate::Result<&'static Self> {
564 let channel = channel_creator
565 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
566 .map_err($crate::Error::Rmt)?;
567 spawner
568 .spawn([<__ $name2:lower _ir_receiver_task>](channel, &[<$name2:upper _IR_STATIC>]))
569 .map_err($crate::Error::TaskSpawn)?;
570 Ok(&[<$name2:upper _IR>])
571 }
572 }
573
574 impl $crate::ir::Ir for $name0 {
575 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
576 self.ir_static.receive().await
577 }
578 }
579
580 impl $crate::ir::Ir for $name1 {
581 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
582 self.ir_static.receive().await
583 }
584 }
585
586 impl $crate::ir::Ir for $name2 {
587 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
588 self.ir_static.receive().await
589 }
590 }
591
592 pub struct $group_name;
593 impl $group_name {
594 pub fn new(
595 pin0: $crate::esp_hal::peripherals::$pin0<'static>,
596 channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
597 pin1: $crate::esp_hal::peripherals::$pin1<'static>,
598 channel_creator1: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
599 pin2: $crate::esp_hal::peripherals::$pin2<'static>,
600 channel_creator2: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
601 spawner: embassy_executor::Spawner,
602 ) -> $crate::Result<(&'static $name0, &'static $name1, &'static $name2)> {
603 let name0 = $name0::new(pin0, channel_creator0, spawner)?;
604 let name1 = $name1::new(pin1, channel_creator1, spawner)?;
605 let name2 = $name2::new(pin2, channel_creator2, spawner)?;
606 Ok((name0, name1, name2))
607 }
608 }
609 }
610 };
611 (
612 $group_name:ident,
613 [($name0:ident, $pin0:ident), ($name1:ident, $pin1:ident), ($name2:ident, $pin2:ident), ($name3:ident, $pin3:ident)]
614 ) => {
615 $crate::ir::paste::paste! {
616 static [<$name0:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
617 static [<$name1:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
618 static [<$name2:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
619 static [<$name3:upper _IR_STATIC>]: $crate::ir::__IrStatic = $crate::ir::__IrStatic::new();
620
621 static [<$name0:upper _IR>]: $name0 = $name0 { ir_static: &[<$name0:upper _IR_STATIC>] };
622 static [<$name1:upper _IR>]: $name1 = $name1 { ir_static: &[<$name1:upper _IR_STATIC>] };
623 static [<$name2:upper _IR>]: $name2 = $name2 { ir_static: &[<$name2:upper _IR_STATIC>] };
624 static [<$name3:upper _IR>]: $name3 = $name3 { ir_static: &[<$name3:upper _IR_STATIC>] };
625
626 #[embassy_executor::task]
627 async fn [<__ $name0:lower _ir_receiver_task>](
628 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
629 ir_static: &'static $crate::ir::__IrStatic,
630 ) -> ! {
631 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
632 }
633
634 #[embassy_executor::task]
635 async fn [<__ $name1:lower _ir_receiver_task>](
636 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
637 ir_static: &'static $crate::ir::__IrStatic,
638 ) -> ! {
639 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
640 }
641
642 #[embassy_executor::task]
643 async fn [<__ $name2:lower _ir_receiver_task>](
644 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
645 ir_static: &'static $crate::ir::__IrStatic,
646 ) -> ! {
647 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
648 }
649
650 #[embassy_executor::task]
651 async fn [<__ $name3:lower _ir_receiver_task>](
652 channel: $crate::esp_hal::rmt::Channel<'static, $crate::esp_hal::Async, $crate::esp_hal::rmt::Rx>,
653 ir_static: &'static $crate::ir::__IrStatic,
654 ) -> ! {
655 $crate::ir::__ir_receiver_task_loop(channel, ir_static).await
656 }
657
658 pub struct $name0 {
659 ir_static: &'static $crate::ir::__IrStatic,
660 }
661
662 pub struct $name1 {
663 ir_static: &'static $crate::ir::__IrStatic,
664 }
665
666 pub struct $name2 {
667 ir_static: &'static $crate::ir::__IrStatic,
668 }
669
670 pub struct $name3 {
671 ir_static: &'static $crate::ir::__IrStatic,
672 }
673
674 impl $name0 {
675 pub fn new(
676 pin: $crate::esp_hal::peripherals::$pin0<'static>,
677 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
678 spawner: embassy_executor::Spawner,
679 ) -> $crate::Result<&'static Self> {
680 let channel = channel_creator
681 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
682 .map_err($crate::Error::Rmt)?;
683 spawner
684 .spawn([<__ $name0:lower _ir_receiver_task>](channel, &[<$name0:upper _IR_STATIC>]))
685 .map_err($crate::Error::TaskSpawn)?;
686 Ok(&[<$name0:upper _IR>])
687 }
688 }
689
690 impl $name1 {
691 pub fn new(
692 pin: $crate::esp_hal::peripherals::$pin1<'static>,
693 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
694 spawner: embassy_executor::Spawner,
695 ) -> $crate::Result<&'static Self> {
696 let channel = channel_creator
697 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
698 .map_err($crate::Error::Rmt)?;
699 spawner
700 .spawn([<__ $name1:lower _ir_receiver_task>](channel, &[<$name1:upper _IR_STATIC>]))
701 .map_err($crate::Error::TaskSpawn)?;
702 Ok(&[<$name1:upper _IR>])
703 }
704 }
705
706 impl $name2 {
707 pub fn new(
708 pin: $crate::esp_hal::peripherals::$pin2<'static>,
709 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
710 spawner: embassy_executor::Spawner,
711 ) -> $crate::Result<&'static Self> {
712 let channel = channel_creator
713 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
714 .map_err($crate::Error::Rmt)?;
715 spawner
716 .spawn([<__ $name2:lower _ir_receiver_task>](channel, &[<$name2:upper _IR_STATIC>]))
717 .map_err($crate::Error::TaskSpawn)?;
718 Ok(&[<$name2:upper _IR>])
719 }
720 }
721
722 impl $name3 {
723 pub fn new(
724 pin: $crate::esp_hal::peripherals::$pin3<'static>,
725 channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
726 spawner: embassy_executor::Spawner,
727 ) -> $crate::Result<&'static Self> {
728 let channel = channel_creator
729 .configure_rx(pin, $crate::init_and_start::rmt::nec_rx_config())
730 .map_err($crate::Error::Rmt)?;
731 spawner
732 .spawn([<__ $name3:lower _ir_receiver_task>](channel, &[<$name3:upper _IR_STATIC>]))
733 .map_err($crate::Error::TaskSpawn)?;
734 Ok(&[<$name3:upper _IR>])
735 }
736 }
737
738 impl $crate::ir::Ir for $name0 {
739 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
740 self.ir_static.receive().await
741 }
742 }
743
744 impl $crate::ir::Ir for $name1 {
745 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
746 self.ir_static.receive().await
747 }
748 }
749
750 impl $crate::ir::Ir for $name2 {
751 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
752 self.ir_static.receive().await
753 }
754 }
755
756 impl $crate::ir::Ir for $name3 {
757 async fn wait_for_press(&self) -> $crate::ir::IrEvent {
758 self.ir_static.receive().await
759 }
760 }
761
762 pub struct $group_name;
763 impl $group_name {
764 pub fn new(
765 pin0: $crate::esp_hal::peripherals::$pin0<'static>,
766 channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
767 pin1: $crate::esp_hal::peripherals::$pin1<'static>,
768 channel_creator1: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
769 pin2: $crate::esp_hal::peripherals::$pin2<'static>,
770 channel_creator2: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
771 pin3: $crate::esp_hal::peripherals::$pin3<'static>,
772 channel_creator3: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
773 spawner: embassy_executor::Spawner,
774 ) -> $crate::Result<(&'static $name0, &'static $name1, &'static $name2, &'static $name3)> {
775 let name0 = $name0::new(pin0, channel_creator0, spawner)?;
776 let name1 = $name1::new(pin1, channel_creator1, spawner)?;
777 let name2 = $name2::new(pin2, channel_creator2, spawner)?;
778 let name3 = $name3::new(pin3, channel_creator3, spawner)?;
779 Ok((name0, name1, name2, name3))
780 }
781 }
782 }
783 };
784 (
785 $group_name:ident,
786 [($name0:ident, $pin0:ident), ($name1:ident, $pin1:ident), ($name2:ident, $pin2:ident), ($name3:ident, $pin3:ident), ($($tail:tt)+)]
787 ) => {
788 compile_error!("irs! currently supports up to 4 receivers in one group.");
789 };
790}
791
792#[doc(hidden)]
793#[macro_export]
794macro_rules! ir {
795 (
796 $(#[$attrs:meta])*
797 $vis:vis $name:ident : { $($deprecated_fields:tt)* }
798 ) => {
799 compile_error!(
800 "ir! no longer supports `Name: { ... }`. Use `Name { ... }` instead."
801 );
802 };
803 (
804 $(#[$attrs:meta])*
805 $vis:vis $name:ident { pin: $pin:ident $(,)? }
806 ) => {
807 $crate::ir::paste::paste! {
808 $crate::irs! {
809 [<__ $name:camel Group>] {
810 [<__ $name:camel Ir>]: { pin: $pin }
811 }
812 }
813
814 $(#[$attrs])*
815 $vis type $name = [<__ $name:camel Ir>];
816 }
817 };
818}
819
820#[allow(unused_imports)]
844#[doc(inline)]
845pub use crate::ir_kepler;
846#[allow(unused_imports)]
874#[doc(inline)]
875pub use crate::ir_keplers;
876#[allow(unused_imports)]
904#[doc(inline)]
905pub use crate::ir_mapping;
906#[allow(unused_imports)]
938#[doc(inline)]
939pub use crate::ir_mappings;
940#[allow(unused_imports)]
964#[doc(inline)]
965pub use ir;
966#[allow(unused_imports)]
994#[doc(inline)]
995pub use irs;