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, pulses::ws2812_bits, 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 mut codes = [PulseCode::end_marker(); 25];
for (code, one) in codes
.iter_mut()
.zip(ws2812_bits(color.r(), color.g(), color.b()))
{
*code = if one { 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 })
}