use esp_hal::{
Async,
gpio::Level,
peripherals::GPIO44,
rmt::{PulseCode, TxChannelConfig, TxChannelCreator},
};
use crate::{Error, remote::RmtTx};
const IR_DIVIDER: u8 = 10;
const IR_CARRIER_HIGH: u16 = 88;
const IR_CARRIER_LOW: u16 = 175;
const NEC_START: PulseCode = PulseCode::new(Level::High, 9000, Level::Low, 4500);
const NEC_REPEAT: PulseCode = PulseCode::new(Level::High, 9000, Level::Low, 2250);
const NEC_ZERO: PulseCode = PulseCode::new(Level::High, 562, Level::Low, 563);
const NEC_ONE: PulseCode = PulseCode::new(Level::High, 562, Level::Low, 1688);
const NEC_STOP: PulseCode = PulseCode::new(Level::High, 562, Level::Low, 0);
#[derive(Debug)]
pub struct IrTransmitter {
channel: RmtTx,
}
impl IrTransmitter {
pub async fn send_nec(&mut self, address: u8, command: u8) -> Result<(), Error> {
self.send_nec_extended(u16::from_le_bytes([address, !address]), command)
.await
}
pub async fn send_nec_extended(&mut self, address: u16, command: u8) -> Result<(), Error> {
let [low, high] = address.to_le_bytes();
let data = u32::from_le_bytes([low, high, command, !command]);
let mut codes = [NEC_STOP; 34];
codes[0] = NEC_START;
for (bit, code) in (0..32).zip(&mut codes[1..]) {
*code = if (data >> bit) & 1 == 1 {
NEC_ONE
} else {
NEC_ZERO
};
}
self.transmit(&codes).await
}
pub async fn send_nec_repeat(&mut self) -> Result<(), Error> {
self.transmit(&[NEC_REPEAT, NEC_STOP]).await
}
async fn transmit(&mut self, codes: &[PulseCode]) -> Result<(), Error> {
self.channel.transmit(codes).await.map_err(|_| Error::Ir)
}
}
pub fn ir_transmitter(
channel: impl TxChannelCreator<'static, Async>,
pin: GPIO44<'static>,
) -> Result<IrTransmitter, Error> {
let config = TxChannelConfig::default()
.with_clk_divider(IR_DIVIDER)
.with_idle_output(true)
.with_idle_output_level(Level::Low)
.with_carrier_modulation(true)
.with_carrier_high(IR_CARRIER_HIGH)
.with_carrier_low(IR_CARRIER_LOW)
.with_carrier_level(Level::High);
let channel = channel
.configure_tx(&config)
.map_err(|_| Error::Rmt)?
.with_pin(pin);
Ok(IrTransmitter { channel })
}