use huesmith_core::light::LightOutput;
use esp_idf_hal::gpio::OutputPin;
use esp_idf_hal::ledc::{LedcChannel, LedcDriver, LedcTimer, LedcTimerDriver};
use super::electrical_duty;
pub struct SimpleLed<'d> {
driver: LedcDriver<'d>,
max_duty: u32,
level: u8,
on: bool,
inverted: bool,
}
impl<'d> SimpleLed<'d> {
pub fn new<C, T, P>(channel: C, timer: T, pin: P, inverted: bool) -> Self
where
C: LedcChannel + 'd,
T: LedcTimer<SpeedMode = C::SpeedMode> + 'd,
P: OutputPin + 'd,
{
let timer_driver =
LedcTimerDriver::new(timer, &esp_idf_hal::ledc::config::TimerConfig::default())
.expect("LEDC timer init failed");
let driver = LedcDriver::new(channel, timer_driver, pin).expect("LEDC driver init failed");
let max_duty = driver.get_max_duty();
let mut this = Self {
driver,
max_duty,
level: 0,
on: false,
inverted,
};
this.apply_level();
this
}
fn apply_level(&mut self) {
let level = if self.on { self.level } else { 0 };
let duty = electrical_duty(level, self.max_duty, self.inverted);
if let Err(e) = self.driver.set_duty(duty) {
log::error!("LEDC set_duty failed: {e}");
}
}
}
impl<'d> LightOutput for SimpleLed<'d> {
fn set_on(&mut self, on: bool) {
self.on = on;
self.apply_level();
}
fn set_brightness(&mut self, level: u8) {
self.level = level.min(254);
self.apply_level();
}
fn set_color_xy(&mut self, _x: u16, _y: u16) {
}
fn set_color_temp(&mut self, _mireds: u16) {
}
fn set_rgb(&mut self, r: u8, g: u8, b: u8) {
let luminance = 0.2126 * f32::from(r) + 0.7152 * f32::from(g) + 0.0722 * f32::from(b);
self.level = (luminance / 255.0 * 254.0).round() as u8;
self.apply_level();
}
}