use self::{
channel::Channel,
timer::{Timer, TimerSpeed},
};
use crate::{
clock::Clocks,
gpio::OutputPin,
peripheral::{Peripheral, PeripheralRef},
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
};
pub mod channel;
pub mod timer;
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum LSGlobalClkSource {
APBClk,
}
pub struct LEDC<'d> {
_instance: PeripheralRef<'d, crate::peripherals::LEDC>,
ledc: &'d crate::peripherals::ledc::RegisterBlock,
clock_control_config: &'d Clocks<'d>,
}
#[cfg(esp32)]
pub struct HighSpeed {}
pub struct LowSpeed {}
pub trait Speed {}
#[cfg(esp32)]
impl Speed for HighSpeed {}
impl Speed for LowSpeed {}
impl<'d> LEDC<'d> {
pub fn new(
_instance: impl Peripheral<P = crate::peripherals::LEDC> + 'd,
clock_control_config: &'d Clocks,
) -> Self {
crate::into_ref!(_instance);
PeripheralClockControl::enable(PeripheralEnable::Ledc);
let ledc = unsafe { &*crate::peripherals::LEDC::ptr() };
LEDC {
_instance,
ledc,
clock_control_config,
}
}
#[cfg(esp32)]
pub fn set_global_slow_clock(&mut self, _clock_source: LSGlobalClkSource) {
self.ledc.conf().write(|w| w.apb_clk_sel().set_bit());
self.ledc
.lstimer0_conf()
.modify(|_, w| w.para_up().set_bit());
}
#[cfg(not(esp32))]
pub fn set_global_slow_clock(&mut self, clock_source: LSGlobalClkSource) {
#[cfg(any(esp32c6, esp32h2))]
let pcr = unsafe { &*crate::peripherals::PCR::ptr() };
#[cfg(any(esp32c6, esp32h2))]
pcr.ledc_sclk_conf().write(|w| w.ledc_sclk_en().set_bit());
match clock_source {
LSGlobalClkSource::APBClk => {
#[cfg(not(any(esp32c6, esp32h2)))]
self.ledc
.conf()
.write(|w| unsafe { w.apb_clk_sel().bits(1) });
#[cfg(esp32c6)]
pcr.ledc_sclk_conf()
.write(|w| unsafe { w.ledc_sclk_sel().bits(1) });
#[cfg(esp32h2)]
pcr.ledc_sclk_conf()
.write(|w| unsafe { w.ledc_sclk_sel().bits(0) });
}
}
self.ledc.timer0_conf().modify(|_, w| w.para_up().set_bit());
}
pub fn get_timer<S: TimerSpeed>(&self, number: timer::Number) -> Timer<S> {
Timer::new(self.ledc, self.clock_control_config, number)
}
pub fn get_channel<S: TimerSpeed, O: OutputPin>(
&self,
number: channel::Number,
output_pin: impl Peripheral<P = O> + 'd,
) -> Channel<S, O> {
Channel::new(number, output_pin)
}
}