use heapless::LinearMap;
#[doc(hidden)]
pub fn __build_button_map<B: Copy, const N: usize>(
button_map: &[(u16, u8, B)],
) -> LinearMap<(u16, u8), B, N> {
let mut linear_map = LinearMap::new();
for &(addr, cmd, button) in button_map {
let previous_button = match linear_map.insert((addr, cmd), button) {
Ok(previous_button) => previous_button,
Err(_) => panic!("button_map entries exceed IrMapping capacity"),
};
assert!(
previous_button.is_none(),
"button_map contains duplicate (addr, cmd) entries"
);
}
linear_map
}
#[doc(hidden)]
#[macro_export]
macro_rules! ir_mappings {
($($tt:tt)*) => { $crate::__ir_mappings_impl! { $($tt)* } };
}
#[doc(hidden)]
#[macro_export]
macro_rules! __ir_mappings_impl {
(
button: $button_ty:ty,
capacity: $capacity:expr,
$group_name:ident {
$name0:ident : { pin: $pin0:ident $(,)? }
}
$(,)?
) => {
$crate::ir::paste::paste! {
$crate::irs! {
[<__ $group_name:camel Irs>] {
[<__ $name0:camel Ir>]: { pin: $pin0 }
}
}
static [<$name0:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name0> =
::static_cell::StaticCell::new();
pub struct $name0 {
ir: &'static [<__ $name0:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
impl $name0 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name0:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name0:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $crate::ir::IrMapping<$button_ty> for $name0 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name0:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
pub struct $group_name;
impl $group_name {
pub fn new(
pin0: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map0: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<(&'static $name0,)> {
let name0 = $name0::new(pin0, channel_creator0, button_map0, spawner)?;
Ok((name0,))
}
}
}
};
(
button: $button_ty:ty,
capacity: $capacity:expr,
$group_name:ident {
$name0:ident : { pin: $pin0:ident $(,)? },
$name1:ident : { pin: $pin1:ident $(,)? }
}
$(,)?
) => {
$crate::ir::paste::paste! {
$crate::irs! {
[<__ $group_name:camel Irs>] {
[<__ $name0:camel Ir>]: { pin: $pin0 },
[<__ $name1:camel Ir>]: { pin: $pin1 }
}
}
static [<$name0:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name0> =
::static_cell::StaticCell::new();
static [<$name1:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name1> =
::static_cell::StaticCell::new();
pub struct $name0 {
ir: &'static [<__ $name0:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
pub struct $name1 {
ir: &'static [<__ $name1:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
impl $name0 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name0:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name0:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $name1 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin1<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name1:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name1:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $crate::ir::IrMapping<$button_ty> for $name0 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name0:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
impl $crate::ir::IrMapping<$button_ty> for $name1 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name1:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
pub struct $group_name;
impl $group_name {
pub fn new(
pin0: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
pin1: $crate::esp_hal::peripherals::$pin1<'static>,
channel_creator1: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map0: &[(u16, u8, $button_ty)],
button_map1: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<(&'static $name0, &'static $name1)> {
let (ir0, ir1) = [<__ $group_name:camel Irs>]::new(
pin0,
channel_creator0,
pin1,
channel_creator1,
spawner,
)?;
let name0 = [<$name0:upper _MAPPING_CELL>].init($name0 {
ir: ir0,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map0,
),
});
let name1 = [<$name1:upper _MAPPING_CELL>].init($name1 {
ir: ir1,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map1,
),
});
Ok((name0, name1))
}
}
}
};
(
button: $button_ty:ty,
capacity: $capacity:expr,
$group_name:ident {
$name0:ident : { pin: $pin0:ident $(,)? },
$name1:ident : { pin: $pin1:ident $(,)? },
$name2:ident : { pin: $pin2:ident $(,)? }
}
$(,)?
) => {
$crate::ir::paste::paste! {
$crate::irs! {
[<__ $group_name:camel Irs>] {
[<__ $name0:camel Ir>]: { pin: $pin0 },
[<__ $name1:camel Ir>]: { pin: $pin1 },
[<__ $name2:camel Ir>]: { pin: $pin2 }
}
}
static [<$name0:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name0> =
::static_cell::StaticCell::new();
static [<$name1:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name1> =
::static_cell::StaticCell::new();
static [<$name2:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name2> =
::static_cell::StaticCell::new();
pub struct $name0 {
ir: &'static [<__ $name0:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
pub struct $name1 {
ir: &'static [<__ $name1:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
pub struct $name2 {
ir: &'static [<__ $name2:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
impl $name0 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name0:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name0:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $name1 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin1<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name1:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name1:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $name2 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin2<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name2:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name2:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $crate::ir::IrMapping<$button_ty> for $name0 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name0:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
impl $crate::ir::IrMapping<$button_ty> for $name1 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name1:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
impl $crate::ir::IrMapping<$button_ty> for $name2 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name2:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
pub struct $group_name;
impl $group_name {
pub fn new(
pin0: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
pin1: $crate::esp_hal::peripherals::$pin1<'static>,
channel_creator1: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
pin2: $crate::esp_hal::peripherals::$pin2<'static>,
channel_creator2: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map0: &[(u16, u8, $button_ty)],
button_map1: &[(u16, u8, $button_ty)],
button_map2: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<(&'static $name0, &'static $name1, &'static $name2)> {
let (ir0, ir1, ir2) = [<__ $group_name:camel Irs>]::new(
pin0,
channel_creator0,
pin1,
channel_creator1,
pin2,
channel_creator2,
spawner,
)?;
let name0 = [<$name0:upper _MAPPING_CELL>].init($name0 {
ir: ir0,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map0,
),
});
let name1 = [<$name1:upper _MAPPING_CELL>].init($name1 {
ir: ir1,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map1,
),
});
let name2 = [<$name2:upper _MAPPING_CELL>].init($name2 {
ir: ir2,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map2,
),
});
Ok((name0, name1, name2))
}
}
}
};
(
button: $button_ty:ty,
capacity: $capacity:expr,
$group_name:ident {
$name0:ident : { pin: $pin0:ident $(,)? },
$name1:ident : { pin: $pin1:ident $(,)? },
$name2:ident : { pin: $pin2:ident $(,)? },
$name3:ident : { pin: $pin3:ident $(,)? }
}
$(,)?
) => {
$crate::ir::paste::paste! {
$crate::irs! {
[<__ $group_name:camel Irs>] {
[<__ $name0:camel Ir>]: { pin: $pin0 },
[<__ $name1:camel Ir>]: { pin: $pin1 },
[<__ $name2:camel Ir>]: { pin: $pin2 },
[<__ $name3:camel Ir>]: { pin: $pin3 }
}
}
static [<$name0:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name0> =
::static_cell::StaticCell::new();
static [<$name1:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name1> =
::static_cell::StaticCell::new();
static [<$name2:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name2> =
::static_cell::StaticCell::new();
static [<$name3:upper _MAPPING_CELL>]: ::static_cell::StaticCell<$name3> =
::static_cell::StaticCell::new();
pub struct $name0 {
ir: &'static [<__ $name0:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
pub struct $name1 {
ir: &'static [<__ $name1:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
pub struct $name2 {
ir: &'static [<__ $name2:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
pub struct $name3 {
ir: &'static [<__ $name3:camel Ir>],
button_map: ::heapless::LinearMap<(u16, u8), $button_ty, $capacity>,
}
impl $name0 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name0:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name0:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $name1 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin1<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name1:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name1:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $name2 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin2<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name2:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name2:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $name3 {
pub fn new(
pin: $crate::esp_hal::peripherals::$pin3<'static>,
channel_creator: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<&'static Self> {
let ir = [<__ $name3:camel Ir>]::new(pin, channel_creator, spawner)?;
Ok([<$name3:upper _MAPPING_CELL>].init(Self {
ir,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map,
),
}))
}
}
impl $crate::ir::IrMapping<$button_ty> for $name0 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name0:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
impl $crate::ir::IrMapping<$button_ty> for $name1 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name1:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
impl $crate::ir::IrMapping<$button_ty> for $name2 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name2:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
impl $crate::ir::IrMapping<$button_ty> for $name3 {
async fn wait_for_press(&self) -> $button_ty {
loop {
let $crate::ir::IrEvent::Press { addr, cmd } =
<[<__ $name3:camel Ir>] as $crate::ir::Ir>::wait_for_press(self.ir).await;
if let Some(&button) = self.button_map.get(&(addr, cmd)) {
return button;
}
}
}
}
pub struct $group_name;
impl $group_name {
pub fn new(
pin0: $crate::esp_hal::peripherals::$pin0<'static>,
channel_creator0: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
pin1: $crate::esp_hal::peripherals::$pin1<'static>,
channel_creator1: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
pin2: $crate::esp_hal::peripherals::$pin2<'static>,
channel_creator2: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
pin3: $crate::esp_hal::peripherals::$pin3<'static>,
channel_creator3: impl $crate::esp_hal::rmt::RxChannelCreator<'static, $crate::esp_hal::Async>,
button_map0: &[(u16, u8, $button_ty)],
button_map1: &[(u16, u8, $button_ty)],
button_map2: &[(u16, u8, $button_ty)],
button_map3: &[(u16, u8, $button_ty)],
spawner: embassy_executor::Spawner,
) -> $crate::Result<(&'static $name0, &'static $name1, &'static $name2, &'static $name3)> {
let (ir0, ir1, ir2, ir3) = [<__ $group_name:camel Irs>]::new(
pin0,
channel_creator0,
pin1,
channel_creator1,
pin2,
channel_creator2,
pin3,
channel_creator3,
spawner,
)?;
let name0 = [<$name0:upper _MAPPING_CELL>].init($name0 {
ir: ir0,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map0,
),
});
let name1 = [<$name1:upper _MAPPING_CELL>].init($name1 {
ir: ir1,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map1,
),
});
let name2 = [<$name2:upper _MAPPING_CELL>].init($name2 {
ir: ir2,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map2,
),
});
let name3 = [<$name3:upper _MAPPING_CELL>].init($name3 {
ir: ir3,
button_map: $crate::ir::__build_button_map::<$button_ty, $capacity>(
button_map3,
),
});
Ok((name0, name1, name2, name3))
}
}
}
};
(
button: $button_ty:ty,
capacity: $capacity:expr,
$group_name:ident {
$name0:ident : { pin: $pin0:ident $(,)? },
$name1:ident : { pin: $pin1:ident $(,)? },
$name2:ident : { pin: $pin2:ident $(,)? },
$name3:ident : { pin: $pin3:ident $(,)? },
$($tail_name:ident : { pin: $tail_pin:ident $(,)? }),+ $(,)?
}
$(,)?
) => {
compile_error!("ir_mappings! currently supports up to 4 receivers in one group.");
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! ir_mapping {
(
$(#[$attrs:meta])*
$vis:vis $name:ident : { $($deprecated_fields:tt)* }
) => {
compile_error!(
"ir_mapping! no longer supports `Name: { ... }`. Use `Name { ... }` instead."
);
};
(
$(#[$attrs:meta])*
$vis:vis $name:ident {
pin: $pin:ident,
button: $button_ty:ty,
capacity: $capacity:expr $(,)?
}
) => {
$crate::ir::paste::paste! {
$crate::ir_mappings! {
button: $button_ty,
capacity: $capacity,
[<__ $name:camel Mappings>] {
[<__ $name:camel Mapping>]: { pin: $pin }
}
}
$(#[$attrs])*
$vis type $name = [<__ $name:camel Mapping>];
}
};
}
#[allow(unused_imports)]
#[doc(inline)]
pub use ir_mapping;
#[allow(unused_imports)]
#[doc(inline)]
pub use ir_mappings;