use embassy_time::{Duration, Timer};
use embedded_graphics_core::pixelcolor::{Rgb888, RgbColor};
use esp_hal::{
Async,
gpio::Level,
peripherals::GPIO21,
rmt::{PulseCode, TxChannelConfig, TxChannelCreator},
};
use crate::{Error, remote::RmtTx};
const LED_ZERO: PulseCode = PulseCode::new(Level::High, 4, Level::Low, 8);
const LED_ONE: PulseCode = PulseCode::new(Level::High, 8, Level::Low, 4);
const LED_LATCH: Duration = Duration::from_micros(300);
#[derive(Debug)]
pub struct RgbLed {
channel: RmtTx,
}
impl RgbLed {
pub async fn set_color(&mut self, color: Rgb888) -> Result<(), Error> {
let grb = (u32::from(color.g()) << 16) | (u32::from(color.r()) << 8) | u32::from(color.b());
let mut codes = [PulseCode::end_marker(); 25];
for (bit, code) in (0..24).rev().zip(&mut codes) {
*code = if (grb >> bit) & 1 == 1 {
LED_ONE
} else {
LED_ZERO
};
}
self.channel
.transmit(&codes)
.await
.map_err(|_| Error::Led)?;
Timer::after(LED_LATCH).await;
Ok(())
}
}
pub fn rgb_led(
channel: impl TxChannelCreator<'static, Async>,
pin: GPIO21<'static>,
) -> Result<RgbLed, Error> {
let config = TxChannelConfig::default()
.with_clk_divider(1)
.with_idle_output(true)
.with_idle_output_level(Level::Low);
let channel = channel
.configure_tx(&config)
.map_err(|_| Error::Rmt)?
.with_pin(pin);
Ok(RgbLed { channel })
}