use esp_hal::gpio::DriveMode;
use esp_hal::ledc::channel::{self, Channel, ChannelHW, ChannelIFace};
use esp_hal::ledc::timer::{self, LSClockSource, Timer, TimerIFace};
use esp_hal::ledc::{LSGlobalClkSource, Ledc, LowSpeed};
use esp_hal::peripherals::{GPIO38, LEDC};
use esp_hal::time::Rate;
use static_cell::StaticCell;
pub const PWM_FREQUENCY: Rate = Rate::from_khz(2);
#[allow(missing_docs)]
pub struct BacklightResources {
pub ledc: LEDC<'static>,
pub pin: GPIO38<'static>,
}
impl BacklightResources {
pub fn init(self) -> Backlight {
static TIMER: StaticCell<Timer<'static, LowSpeed>> = StaticCell::new();
let mut ledc = Ledc::new(self.ledc);
ledc.set_global_slow_clock(LSGlobalClkSource::APBClk);
let mut t = ledc.timer::<LowSpeed>(timer::Number::Timer0);
t.configure(timer::config::Config {
duty: timer::config::Duty::Duty8Bit,
clock_source: LSClockSource::APBClk,
frequency: PWM_FREQUENCY,
})
.expect("2 kHz at 8 bits is reachable from APB");
let timer = TIMER.init(t);
let mut ch = ledc.channel(channel::Number::Channel0, self.pin);
ch.configure(channel::config::Config {
timer,
duty_pct: 100,
drive_mode: DriveMode::PushPull,
})
.expect("valid LEDC channel configuration");
Backlight {
ch,
level: Backlight::MAX,
}
}
}
pub struct Backlight {
ch: Channel<'static, LowSpeed>,
level: u8,
}
impl Backlight {
pub const MAX: u8 = u8::MAX;
pub fn set(&mut self, level: u8) {
let duty = if level == Self::MAX {
1 << 8
} else {
u32::from(level)
};
self.ch.set_duty_hw(duty);
self.level = level;
}
pub fn level(&self) -> u8 {
self.level
}
}