diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index faf7ca246..d98d6f890 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -44,10 +44,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - DMA channels can/have to be explicitly created for async or blocking drivers, added `set_interrupt_handler` to DMA channels, SPI, I2S, PARL_IO, don't enable interrupts on startup for DMA, I2S, PARL_IO, GPIO (#1300) - UART: Rework `change_baud` so it is possible to set baud rate even after instantiation (#1350) - Runtime ISR binding for SHA,ECC and RSA (#1354) -- Update `pac`s with removed suffixes in `int` field names. Use `W1TC` for `int_clr` (#1357) - MCPWM clusters (#1360) - TIMG clusters (#1364) - SOC_ETM clusters (#1365) ### Removed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 2bcc38190..a228a8f6f 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -52,14 +52,14 @@ xtensa-lx = { version = "0.9.0", optional = true } # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. -esp32 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32c2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32c3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32p4 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32s2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32s3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } +esp32 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32c2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32c3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32p4 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32s2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32s3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } [target.'cfg(target_arch = "riscv32")'.dependencies] esp-riscv-rt = { version = "0.7.0", optional = true, path = "../esp-riscv-rt" } diff --git a/esp-hal/src/ledc/channel.rs b/esp-hal/src/ledc/channel.rs index 21f7ba6f9..8106b8771 100644 --- a/esp-hal/src/ledc/channel.rs +++ b/esp-hal/src/ledc/channel.rs @@ -9,14 +9,7 @@ //! `Pulse-Width Modulation (PWM)` applications by offering configurable duty //! cycles and frequencies. -use paste::paste; - -#[cfg(esp32)] -use super::HighSpeed; -use super::{ - timer::{TimerIFace, TimerSpeed}, - LowSpeed, -}; +use super::timer::{TimerIFace, TimerSpeed}; use crate::{ gpio::{OutputPin, OutputSignal}, peripheral::{Peripheral, PeripheralRef}, @@ -55,16 +48,16 @@ pub enum Error { #[derive(PartialEq, Eq, Copy, Clone, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Number { - Channel0, - Channel1, - Channel2, - Channel3, - Channel4, - Channel5, + Channel0 = 0, + Channel1 = 1, + Channel2 = 2, + Channel3 = 3, + Channel4 = 4, + Channel5 = 5, #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Channel6, + Channel6 = 6, #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Channel7, + Channel7 = 7, } /// Channel configuration @@ -337,341 +330,210 @@ mod ehal1 { } } -#[cfg(esp32)] -/// Macro to configure channel parameters in hw -macro_rules! set_channel { - ($self: ident, $speed: ident, $num: literal, $timer_number: ident) => {{ - paste! { - $self.ledc.[<$speed sch $num _hpoint>]() - .write(|w| unsafe { w.hpoint().bits(0x0) }); - $self.ledc.[<$speed sch $num _conf0>]().modify(|_, w| unsafe { - w.sig_out_en() - .set_bit() - .timer_sel() - .bits($timer_number) +impl<'a, O: OutputPin, S: crate::ledc::timer::TimerSpeed> Channel<'a, S, O> { + #[cfg(esp32)] + fn set_channel(&mut self, timer_number: u8) { + if S::IS_HS { + let ch = self.ledc.hsch(self.number as usize); + ch.hpoint().write(|w| unsafe { w.hpoint().bits(0x0) }); + ch.conf0() + .modify(|_, w| unsafe { w.sig_out_en().set_bit().timer_sel().bits(timer_number) }); + } else { + let ch = self.ledc.lsch(self.number as usize); + ch.hpoint().write(|w| unsafe { w.hpoint().bits(0x0) }); + ch.conf0() + .modify(|_, w| unsafe { w.sig_out_en().set_bit().timer_sel().bits(timer_number) }); + } + self.start_duty_without_fading(); + } + #[cfg(not(esp32))] + fn set_channel(&mut self, timer_number: u8) { + { + let ch = self.ledc.ch(self.number as usize); + ch.hpoint().write(|w| unsafe { w.hpoint().bits(0x0) }); + ch.conf0().modify(|_, w| { + w.sig_out_en().set_bit(); + unsafe { w.timer_sel().bits(timer_number) } }); } - start_duty_without_fading!($self, $speed, $num); - }}; -} + self.start_duty_without_fading(); + } -#[cfg(not(esp32))] -/// Macro to configure channel parameters in hw -macro_rules! set_channel { - ($self: ident, $speed: ident, $num: literal, $timer_number: ident) => {{ - paste! { - $self.ledc.[]() - .write(|w| unsafe { w.hpoint().bits(0x0) }); - $self.ledc.[]().modify(|_, w| unsafe { - w.sig_out_en() - .set_bit() - .timer_sel() - .bits($timer_number) + #[cfg(esp32)] + fn start_duty_without_fading(&self) { + if S::IS_HS { + self.ledc + .hsch(self.number as usize) + .conf1() + .write(|w| unsafe { + w.duty_start().set_bit(); + w.duty_inc().set_bit(); + w.duty_num().bits(0x1); + w.duty_cycle().bits(0x1); + w.duty_scale().bits(0x0) + }); + } else { + self.ledc + .lsch(self.number as usize) + .conf1() + .write(|w| unsafe { + w.duty_start().set_bit(); + w.duty_inc().set_bit(); + w.duty_num().bits(0x1); + w.duty_cycle().bits(0x1); + w.duty_scale().bits(0x0) + }); + } + } + #[cfg(any(esp32c6, esp32h2))] + fn start_duty_without_fading(&self) { + let cnum = self.number as usize; + self.ledc + .ch(cnum) + .conf1() + .write(|w| w.duty_start().set_bit()); + self.ledc.ch_gamma_wr(cnum).write(|w| { + w.ch_gamma_duty_inc().set_bit(); + unsafe { + w.ch_gamma_duty_num().bits(0x1); + w.ch_gamma_duty_cycle().bits(0x1); + w.ch_gamma_scale().bits(0x0) + } + }); + } + #[cfg(not(any(esp32, esp32c6, esp32h2)))] + fn start_duty_without_fading(&self) { + self.ledc.ch(self.number as usize).conf1().write(|w| { + w.duty_start().set_bit(); + w.duty_inc().set_bit(); + unsafe { + w.duty_num().bits(0x1); + w.duty_cycle().bits(0x1); + w.duty_scale().bits(0x0) + } + }); + } + + #[cfg(esp32)] + fn start_duty_fade_inner( + &self, + duty_inc: bool, + duty_steps: u16, + cycles_per_step: u16, + duty_per_cycle: u16, + ) { + if S::IS_HS { + self.ledc + .hsch(self.number as usize) + .conf1() + .write(|w| unsafe { + w.duty_start() + .set_bit() + .duty_inc() + .variant(duty_inc) + .duty_num() // count of incs before stopping + .bits(duty_steps) + .duty_cycle() // overflows between incs + .bits(cycles_per_step) + .duty_scale() + .bits(duty_per_cycle) + }); + } else { + self.ledc + .lsch(self.number as usize) + .conf1() + .write(|w| unsafe { + w.duty_start() + .set_bit() + .duty_inc() + .variant(duty_inc) + .duty_num() // count of incs before stopping + .bits(duty_steps) + .duty_cycle() // overflows between incs + .bits(cycles_per_step) + .duty_scale() + .bits(duty_per_cycle) + }); + } + } + + #[cfg(any(esp32c6, esp32h2))] + fn start_duty_fade_inner( + &self, + duty_inc: bool, + duty_steps: u16, + cycles_per_step: u16, + duty_per_cycle: u16, + ) { + let cnum = self.number as usize; + self.ledc + .ch(cnum) + .conf1() + .write(|w| w.duty_start().set_bit()); + self.ledc.ch_gamma_wr(cnum).write(|w| unsafe { + w.ch_gamma_duty_inc() + .variant(duty_inc) + .ch_gamma_duty_num() // count of incs before stopping + .bits(duty_steps) + .ch_gamma_duty_cycle() // overflows between incs + .bits(cycles_per_step) + .ch_gamma_scale() + .bits(duty_per_cycle) + }); + self.ledc + .ch_gamma_wr_addr(cnum) + .write(|w| unsafe { w.ch_gamma_wr_addr().bits(0) }); + self.ledc + .ch_gamma_conf(cnum) + .write(|w| unsafe { w.ch_gamma_entry_num().bits(0x1) }); + } + + #[cfg(not(any(esp32, esp32c6, esp32h2)))] + fn start_duty_fade_inner( + &self, + duty_inc: bool, + duty_steps: u16, + cycles_per_step: u16, + duty_per_cycle: u16, + ) { + self.ledc + .ch(self.number as usize) + .conf1() + .write(|w| unsafe { + w.duty_start().set_bit(); + w.duty_inc().variant(duty_inc); + // count of incs before stopping + w.duty_num().bits(duty_steps); + // overflows between incs + w.duty_cycle().bits(cycles_per_step); + w.duty_scale().bits(duty_per_cycle) }); - } - start_duty_without_fading!($self, $num); - }}; -} + } -#[cfg(esp32)] -/// Macro to start duty cycle, without fading -macro_rules! start_duty_without_fading { - ($self: ident, $speed: ident, $num: literal) => { - paste! { - $self.ledc.[<$speed sch $num _conf1>]().write(|w| unsafe { - w.duty_start() - .set_bit() - .duty_inc() - .set_bit() - .duty_num() - .bits(0x1) - .duty_cycle() - .bits(0x1) - .duty_scale() - .bits(0x0) - }); - } - }; -} - -#[cfg(any(esp32c6, esp32h2))] -/// Macro to start duty cycle, without fading -macro_rules! start_duty_without_fading { - ($self: ident, $num: literal) => { - paste! { - $self.ledc.[]().write(|w| - w.duty_start() - .set_bit() - ); - $self.ledc.[]().write(|w| unsafe { - w.ch_gamma_duty_inc() - .set_bit() - .ch_gamma_duty_num() - .bits(0x1) - .ch_gamma_duty_cycle() - .bits(0x1) - .ch_gamma_scale() - .bits(0x0) - }); - } - }; -} - -#[cfg(not(any(esp32, esp32c6, esp32h2)))] -/// Macro to start duty cycle, without fading -macro_rules! start_duty_without_fading { - ($self: ident, $num: literal) => { - paste! { - $self.ledc.[]().write(|w| unsafe { - w.duty_start() - .set_bit() - .duty_inc() - .set_bit() - .duty_num() - .bits(0x1) - .duty_cycle() - .bits(0x1) - .duty_scale() - .bits(0x0) - }); - } - }; -} - -#[cfg(esp32)] -/// Macro to start duty cycle fade -macro_rules! start_duty_fade { - ($self: ident, $speed: ident, $num: literal, $duty_inc: ident, $duty_steps: ident, $cycles_per_step: ident, $duty_per_cycle: ident) => { - paste! { - $self.ledc.[<$speed sch $num _conf1>]().write(|w| unsafe { - w.duty_start() - .set_bit() - .duty_inc() - .variant($duty_inc) - .duty_num() /* count of incs before stopping */ - .bits($duty_steps) - .duty_cycle() /* overflows between incs */ - .bits($cycles_per_step) - .duty_scale() - .bits($duty_per_cycle) - }); - } - }; -} - -#[cfg(any(esp32c6, esp32h2))] -/// Macro to start a duty cycle fade -macro_rules! start_duty_fade { - ($self: ident, $num: literal, $duty_inc: ident, $duty_steps: ident, $cycles_per_step: ident, $duty_per_cycle: ident) => { - paste! { - $self.ledc.[]().write(|w| - w.duty_start() - .set_bit() - ); - $self.ledc.[]().write(|w| unsafe { - w.ch_gamma_duty_inc() - .variant($duty_inc) - .ch_gamma_duty_num() /* count of incs before stopping */ - .bits($duty_steps) - .ch_gamma_duty_cycle() /* overflows between incs */ - .bits($cycles_per_step) - .ch_gamma_scale() - .bits($duty_per_cycle) - }); - $self.ledc.[]().write(|w| unsafe { - w.ch_gamma_wr_addr() - .bits(0) - }); - $self.ledc.ch_gamma_conf($num).write(|w| unsafe { - w.ch_gamma_entry_num() - .bits(0x1) - }); - } - }; -} - -#[cfg(not(any(esp32, esp32c6, esp32h2)))] -/// Macro to start a duty cycle fade -macro_rules! start_duty_fade { - ($self: ident, $num: literal, $duty_inc: ident, $duty_steps: ident, $cycles_per_step: ident, $duty_per_cycle: ident) => { - paste! {{ - $self.ledc.[]().write(|w| unsafe { - w.duty_start() - .set_bit() - .duty_inc() - .variant($duty_inc) - .duty_num() /* count of incs before stopping */ - .bits($duty_steps) - .duty_cycle() /* overflows between incs */ - .bits($cycles_per_step) - .duty_scale() - .bits($duty_per_cycle) - }); - }} - }; -} - -#[cfg(esp32)] -/// Macro to set duty parameters in hw -macro_rules! set_duty { - ($self: ident, $speed: ident, $num: literal, $duty: ident) => {{ - paste! { - $self.ledc - .[<$speed sch $num _duty>]() - .write(|w| unsafe { w.duty().bits($duty << 4) }); - } - start_duty_without_fading!($self, $speed, $num); - update_channel!($self, $speed, $num); - }}; -} - -#[cfg(not(esp32))] -/// Macro to set duty parameters in hw -macro_rules! set_duty { - ($self: ident, $speed: ident, $num: literal, $duty: ident) => {{ - paste! { - $self.ledc - .[]() - .write(|w| unsafe { w.duty().bits($duty << 4) }); - } - start_duty_without_fading!($self, $num); - update_channel!($self, $speed, $num); - }}; -} - -#[cfg(esp32)] -/// Macro to set duty parameters in hw for a fade -macro_rules! set_duty_fade { - ($self: ident, $speed: ident, $num: literal, $start_duty: ident, $duty_inc: ident, $duty_steps: ident, $cycles_per_step: ident, $duty_per_cycle: ident) => {{ - paste! { - $self.ledc - .[<$speed sch $num _duty>]() - .write(|w| unsafe { w.duty().bits($start_duty << 4) }); - $self.ledc - .int_clr() - .write(|w| { w.[]().clear_bit_by_one() }); - } - start_duty_fade!( - $self, - $speed, - $num, - $duty_inc, - $duty_steps, - $cycles_per_step, - $duty_per_cycle - ); - update_channel!($self, $speed, $num); - }}; -} - -#[cfg(esp32c3)] -/// Macro to set duty parameters in hw for a fade -macro_rules! set_duty_fade { - ($self: ident, $speed: ident, $num: literal, $start_duty: ident, $duty_inc: ident, $duty_steps: ident, $cycles_per_step: ident, $duty_per_cycle: ident) => {{ - paste! { - $self.ledc - .[]() - .write(|w| unsafe { w.duty().bits($start_duty << 4) }); - $self.ledc - .int_clr() - .write(|w| { w.[]().clear_bit_by_one() }); - } - start_duty_fade!( - $self, - $num, - $duty_inc, - $duty_steps, - $cycles_per_step, - $duty_per_cycle - ); - update_channel!($self, $speed, $num); - }}; -} - -#[cfg(not(any(esp32, esp32c3)))] -/// Macro to set duty parameters in hw for a fade -macro_rules! set_duty_fade { - ($self: ident, $speed: ident, $num: literal, $start_duty: ident, $duty_inc: ident, $duty_steps: ident, $cycles_per_step: ident, $duty_per_cycle: ident) => {{ - paste! { - $self.ledc - .[]() - .write(|w| unsafe { w.duty().bits($start_duty << 4) }); - $self.ledc - .int_clr() - .write(|w| { w.[]().clear_bit_by_one() }); - } - start_duty_fade!( - $self, - $num, - $duty_inc, - $duty_steps, - $cycles_per_step, - $duty_per_cycle - ); - update_channel!($self, $speed, $num); - }}; -} - -/// Macro to check if a duty-cycle fade is running -#[cfg(any(esp32, esp32c3))] -macro_rules! is_duty_fade_running { - ($self: ident, $speed: ident, $num: literal) => {{ - paste! { - $self.ledc - .int_raw() - .read() - .[]() - .bit_is_clear() - } - }}; -} - -#[cfg(not(any(esp32, esp32c3)))] -macro_rules! is_duty_fade_running { - ($self: ident, $speed: ident, $num: literal) => {{ - paste! { - $self.ledc - .int_raw() - .read() - .[]() - .bit_is_clear() - } - }}; -} - -#[cfg(esp32)] -/// Macro to update channel configuration (only for LowSpeed channels) -macro_rules! update_channel { - ($self: ident, l, $num: literal) => { - paste! { - $self.ledc - .[]() + #[cfg(esp32)] + fn update_channel(&self) { + if !S::IS_HS { + self.ledc + .lsch(self.number as usize) + .conf0() .modify(|_, w| w.para_up().set_bit()); } - }; - ($self: ident, h, $num: literal) => {}; + } + #[cfg(not(esp32))] + fn update_channel(&self) { + self.ledc + .ch(self.number as usize) + .conf0() + .modify(|_, w| w.para_up().set_bit()); + } } -#[cfg(not(esp32))] -/// Macro to update channel configuration (only for LowSpeed channels) -macro_rules! update_channel { - ($self: ident, l, $num: literal) => { - paste! { - $self.ledc - .[]() - .modify(|_, w| w.para_up().set_bit()); - } - }; -} - -#[cfg(esp32)] -/// Channel HW interface for HighSpeed channels -impl<'a, O> ChannelHW for Channel<'a, HighSpeed, O> +impl<'a, O, S> ChannelHW for Channel<'a, S, O> where O: OutputPin, + S: crate::ledc::timer::TimerSpeed, { - /// Configure Channel HW except for the duty which is set via - /// [`Self::set_duty_hw`]. + /// Configure Channel HW fn configure_hw(&mut self) -> Result<(), Error> { self.configure_hw_with_pin_config(config::PinConfig::PushPull) } @@ -687,48 +549,51 @@ where }; let timer_number = timer.get_number() as u8; - match self.number { - Number::Channel0 => { - set_channel!(self, h, 0, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG0); + + self.set_channel(timer_number); + self.update_channel(); + + #[cfg(esp32)] + let signal = if S::IS_HS { + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + match self.number { + Number::Channel0 => OutputSignal::LEDC_HS_SIG0, + Number::Channel1 => OutputSignal::LEDC_HS_SIG1, + Number::Channel2 => OutputSignal::LEDC_HS_SIG2, + Number::Channel3 => OutputSignal::LEDC_HS_SIG3, + Number::Channel4 => OutputSignal::LEDC_HS_SIG4, + Number::Channel5 => OutputSignal::LEDC_HS_SIG5, + Number::Channel6 => OutputSignal::LEDC_HS_SIG6, + Number::Channel7 => OutputSignal::LEDC_HS_SIG7, } - Number::Channel1 => { - set_channel!(self, h, 1, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG1); + } else { + match self.number { + Number::Channel0 => OutputSignal::LEDC_LS_SIG0, + Number::Channel1 => OutputSignal::LEDC_LS_SIG1, + Number::Channel2 => OutputSignal::LEDC_LS_SIG2, + Number::Channel3 => OutputSignal::LEDC_LS_SIG3, + Number::Channel4 => OutputSignal::LEDC_LS_SIG4, + Number::Channel5 => OutputSignal::LEDC_LS_SIG5, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + Number::Channel6 => OutputSignal::LEDC_LS_SIG6, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + Number::Channel7 => OutputSignal::LEDC_LS_SIG7, } - Number::Channel2 => { - set_channel!(self, h, 2, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG2); - } - Number::Channel3 => { - set_channel!(self, h, 3, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG3); - } - Number::Channel4 => { - set_channel!(self, h, 4, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG4); - } - Number::Channel5 => { - set_channel!(self, h, 5, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG5); - } - Number::Channel6 => { - set_channel!(self, h, 6, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG6); - } - Number::Channel7 => { - set_channel!(self, h, 7, timer_number); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_HS_SIG7); - } - } + }; + #[cfg(not(esp32))] + let signal = match self.number { + Number::Channel0 => OutputSignal::LEDC_LS_SIG0, + Number::Channel1 => OutputSignal::LEDC_LS_SIG1, + Number::Channel2 => OutputSignal::LEDC_LS_SIG2, + Number::Channel3 => OutputSignal::LEDC_LS_SIG3, + Number::Channel4 => OutputSignal::LEDC_LS_SIG4, + Number::Channel5 => OutputSignal::LEDC_LS_SIG5, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + Number::Channel6 => OutputSignal::LEDC_LS_SIG6, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + Number::Channel7 => OutputSignal::LEDC_LS_SIG7, + }; + self.output_pin.connect_peripheral_to_output(signal); } else { return Err(Error::Timer); } @@ -737,227 +602,36 @@ where } /// Set duty in channel HW + #[cfg(esp32)] fn set_duty_hw(&self, duty: u32) { - match self.number { - Number::Channel0 => set_duty!(self, h, 0, duty), - Number::Channel1 => set_duty!(self, h, 1, duty), - Number::Channel2 => set_duty!(self, h, 2, duty), - Number::Channel3 => set_duty!(self, h, 3, duty), - Number::Channel4 => set_duty!(self, h, 4, duty), - Number::Channel5 => set_duty!(self, h, 5, duty), - Number::Channel6 => set_duty!(self, h, 6, duty), - Number::Channel7 => set_duty!(self, h, 7, duty), - }; - } - - /// Start a duty-cycle fade HW - fn start_duty_fade_hw( - &self, - start_duty: u32, - duty_inc: bool, - duty_steps: u16, - cycles_per_step: u16, - duty_per_cycle: u16, - ) { - match self.number { - Number::Channel0 => set_duty_fade!( - self, - h, - 0, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel1 => set_duty_fade!( - self, - h, - 1, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel2 => set_duty_fade!( - self, - h, - 2, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel3 => set_duty_fade!( - self, - h, - 3, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel4 => set_duty_fade!( - self, - h, - 4, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel5 => set_duty_fade!( - self, - h, - 5, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel6 => set_duty_fade!( - self, - h, - 6, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel7 => set_duty_fade!( - self, - h, - 7, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - } - } - - fn is_duty_fade_running_hw(&self) -> bool { - match self.number { - Number::Channel0 => is_duty_fade_running!(self, h, 0), - Number::Channel1 => is_duty_fade_running!(self, h, 1), - Number::Channel2 => is_duty_fade_running!(self, h, 2), - Number::Channel3 => is_duty_fade_running!(self, h, 3), - Number::Channel4 => is_duty_fade_running!(self, h, 4), - Number::Channel5 => is_duty_fade_running!(self, h, 5), - Number::Channel6 => is_duty_fade_running!(self, h, 6), - Number::Channel7 => is_duty_fade_running!(self, h, 7), - } - } -} - -/// Channel HW interface for LowSpeed channels -impl<'a, O: OutputPin> ChannelHW for Channel<'a, LowSpeed, O> -where - O: OutputPin, -{ - /// Configure Channel HW - fn configure_hw(&mut self) -> Result<(), Error> { - self.configure_hw_with_pin_config(config::PinConfig::PushPull) - } - fn configure_hw_with_pin_config(&mut self, cfg: config::PinConfig) -> Result<(), Error> { - if let Some(timer) = self.timer { - if !timer.is_configured() { - return Err(Error::Timer); - } - - match cfg { - config::PinConfig::PushPull => { - self.output_pin.set_to_push_pull_output(); - } - config::PinConfig::OpenDrain => { - self.output_pin.set_to_open_drain_output(); - } - } - - let timer_number = timer.get_number() as u8; - match self.number { - Number::Channel0 => { - set_channel!(self, l, 0, timer_number); - update_channel!(self, l, 0); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG0); - } - Number::Channel1 => { - set_channel!(self, l, 1, timer_number); - update_channel!(self, l, 1); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG1); - } - Number::Channel2 => { - set_channel!(self, l, 2, timer_number); - update_channel!(self, l, 2); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG2); - } - Number::Channel3 => { - set_channel!(self, l, 3, timer_number); - update_channel!(self, l, 3); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG3); - } - Number::Channel4 => { - set_channel!(self, l, 4, timer_number); - update_channel!(self, l, 4); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG4); - } - Number::Channel5 => { - set_channel!(self, l, 5, timer_number); - update_channel!(self, l, 5); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG5); - } - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel6 => { - set_channel!(self, l, 6, timer_number); - update_channel!(self, l, 6); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG6); - } - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel7 => { - set_channel!(self, l, 7, timer_number); - update_channel!(self, l, 7); - self.output_pin - .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG7); - } - } + if S::IS_HS { + self.ledc + .hsch(self.number as usize) + .duty() + .write(|w| unsafe { w.duty().bits(duty << 4) }); } else { - return Err(Error::Timer); + self.ledc + .hsch(self.number as usize) + .duty() + .write(|w| unsafe { w.duty().bits(duty << 4) }); } - - Ok(()) + self.start_duty_without_fading(); + self.update_channel(); } /// Set duty in channel HW + #[cfg(not(esp32))] fn set_duty_hw(&self, duty: u32) { - match self.number { - Number::Channel0 => set_duty!(self, l, 0, duty), - Number::Channel1 => set_duty!(self, l, 1, duty), - Number::Channel2 => set_duty!(self, l, 2, duty), - Number::Channel3 => set_duty!(self, l, 3, duty), - Number::Channel4 => set_duty!(self, l, 4, duty), - Number::Channel5 => set_duty!(self, l, 5, duty), - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel6 => set_duty!(self, l, 6, duty), - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel7 => set_duty!(self, l, 7, duty), - }; + self.ledc + .ch(self.number as usize) + .duty() + .write(|w| unsafe { w.duty().bits(duty << 4) }); + self.start_duty_without_fading(); + self.update_channel(); } /// Start a duty-cycle fade HW + #[cfg(esp32)] fn start_duty_fade_hw( &self, start_duty: u32, @@ -966,104 +640,64 @@ where cycles_per_step: u16, duty_per_cycle: u16, ) { - match self.number { - Number::Channel0 => set_duty_fade!( - self, - l, - 0, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel1 => set_duty_fade!( - self, - l, - 1, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel2 => set_duty_fade!( - self, - l, - 2, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel3 => set_duty_fade!( - self, - l, - 3, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel4 => set_duty_fade!( - self, - l, - 4, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - Number::Channel5 => set_duty_fade!( - self, - l, - 5, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel6 => set_duty_fade!( - self, - l, - 6, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel7 => set_duty_fade!( - self, - l, - 7, - start_duty, - duty_inc, - duty_steps, - cycles_per_step, - duty_per_cycle - ), + if S::IS_HS { + self.ledc + .hsch(self.number as usize) + .duty() + .write(|w| unsafe { w.duty().bits(start_duty << 4) }); + self.ledc + .int_clr() + .write(|w| w.duty_chng_end_hsch(self.number as u8).clear_bit_by_one()); + } else { + self.ledc + .lsch(self.number as usize) + .duty() + .write(|w| unsafe { w.duty().bits(start_duty << 4) }); + self.ledc + .int_clr() + .write(|w| w.duty_chng_end_lsch(self.number as u8).clear_bit_by_one()); + } + self.start_duty_fade_inner(duty_inc, duty_steps, cycles_per_step, duty_per_cycle); + self.update_channel(); + } + + /// Start a duty-cycle fade HW + #[cfg(not(esp32))] + fn start_duty_fade_hw( + &self, + start_duty: u32, + duty_inc: bool, + duty_steps: u16, + cycles_per_step: u16, + duty_per_cycle: u16, + ) { + self.ledc + .ch(self.number as usize) + .duty() + .write(|w| unsafe { w.duty().bits(start_duty << 4) }); + self.ledc + .int_clr() + .write(|w| w.duty_chng_end_ch(self.number as u8).clear_bit_by_one()); + self.start_duty_fade_inner(duty_inc, duty_steps, cycles_per_step, duty_per_cycle); + self.update_channel(); + } + + #[cfg(esp32)] + fn is_duty_fade_running_hw(&self) -> bool { + let reg = self.ledc.int_raw().read(); + if S::IS_HS { + reg.duty_chng_end_hsch(self.number as u8).bit_is_clear() + } else { + reg.duty_chng_end_lsch(self.number as u8).bit_is_clear() } } + #[cfg(not(esp32))] fn is_duty_fade_running_hw(&self) -> bool { - match self.number { - Number::Channel0 => is_duty_fade_running!(self, l, 0), - Number::Channel1 => is_duty_fade_running!(self, l, 1), - Number::Channel2 => is_duty_fade_running!(self, l, 2), - Number::Channel3 => is_duty_fade_running!(self, l, 3), - Number::Channel4 => is_duty_fade_running!(self, l, 4), - Number::Channel5 => is_duty_fade_running!(self, l, 5), - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel6 => is_duty_fade_running!(self, l, 6), - #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - Number::Channel7 => is_duty_fade_running!(self, l, 7), - } + self.ledc + .int_raw() + .read() + .duty_chng_end_ch(self.number as u8) + .bit_is_clear() } } diff --git a/esp-hal/src/ledc/mod.rs b/esp-hal/src/ledc/mod.rs index 882c2f3eb..cfe5c138a 100644 --- a/esp-hal/src/ledc/mod.rs +++ b/esp-hal/src/ledc/mod.rs @@ -96,12 +96,18 @@ pub struct HighSpeed {} /// Used to specify LowSpeed Timer/Channel pub struct LowSpeed {} -pub trait Speed {} +pub trait Speed { + const IS_HS: bool; +} #[cfg(esp32)] -impl Speed for HighSpeed {} +impl Speed for HighSpeed { + const IS_HS: bool = true; +} -impl Speed for LowSpeed {} +impl Speed for LowSpeed { + const IS_HS: bool = false; +} impl<'d> LEDC<'d> { /// Return a new LEDC @@ -125,7 +131,8 @@ impl<'d> LEDC<'d> { 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() + .lstimer(0) + .conf() .modify(|_, w| w.para_up().set_bit()); } @@ -152,7 +159,10 @@ impl<'d> LEDC<'d> { .write(|w| unsafe { w.ledc_sclk_sel().bits(0) }); } } - self.ledc.timer0_conf().modify(|_, w| w.para_up().set_bit()); + self.ledc + .timer(0) + .conf() + .modify(|_, w| w.para_up().set_bit()); } /// Return a new timer diff --git a/esp-hal/src/ledc/timer.rs b/esp-hal/src/ledc/timer.rs index a6b613a9e..68a507a0d 100644 --- a/esp-hal/src/ledc/timer.rs +++ b/esp-hal/src/ledc/timer.rs @@ -47,10 +47,10 @@ pub enum LSClockSource { #[derive(PartialEq, Eq, Copy, Clone, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Number { - Timer0, - Timer1, - Timer2, - Timer3, + Timer0 = 0, + Timer1 = 1, + Timer2 = 2, + Timer3 = 3, } /// Timer configuration @@ -256,56 +256,16 @@ impl<'a> TimerHW for Timer<'a, LowSpeed> { let duty = unwrap!(self.duty) as u8; let use_apb = !self.use_ref_tick; - match self.number { - Number::Timer0 => self.ledc.lstimer0_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_apb) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer1 => self.ledc.lstimer1_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_apb) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer2 => self.ledc.lstimer2_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_apb) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer3 => self.ledc.lstimer3_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_apb) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - }; + self.ledc + .lstimer(self.number as usize) + .conf() + .modify(|_, w| unsafe { + w.tick_sel().bit(use_apb); + w.rst().clear_bit(); + w.pause().clear_bit(); + w.div_num().bits(divisor); + w.duty_res().bits(duty) + }); } #[cfg(not(esp32))] @@ -314,90 +274,26 @@ impl<'a> TimerHW for Timer<'a, LowSpeed> { let duty = unwrap!(self.duty) as u8; let use_ref_tick = self.use_ref_tick; - match self.number { - Number::Timer0 => self.ledc.timer0_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_ref_tick) - .rst() - .clear_bit() - .pause() - .clear_bit() - .clk_div() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer1 => self.ledc.timer1_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_ref_tick) - .rst() - .clear_bit() - .pause() - .clear_bit() - .clk_div() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer2 => self.ledc.timer2_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_ref_tick) - .rst() - .clear_bit() - .pause() - .clear_bit() - .clk_div() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer3 => self.ledc.timer3_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(use_ref_tick) - .rst() - .clear_bit() - .pause() - .clear_bit() - .clk_div() - .bits(divisor) - .duty_res() - .bits(duty) - }), - }; + self.ledc + .timer(self.number as usize) + .conf() + .modify(|_, w| unsafe { + w.tick_sel().bit(use_ref_tick); + w.rst().clear_bit(); + w.pause().clear_bit(); + w.clk_div().bits(divisor); + w.duty_res().bits(duty) + }); } - #[cfg(esp32)] /// Update the timer in HW fn update_hw(&self) { - match self.number { - Number::Timer0 => self - .ledc - .lstimer0_conf() - .modify(|_, w| w.para_up().set_bit()), - Number::Timer1 => self - .ledc - .lstimer1_conf() - .modify(|_, w| w.para_up().set_bit()), - Number::Timer2 => self - .ledc - .lstimer2_conf() - .modify(|_, w| w.para_up().set_bit()), - Number::Timer3 => self - .ledc - .lstimer3_conf() - .modify(|_, w| w.para_up().set_bit()), - }; - } + #[cfg(esp32)] + let tmr = self.ledc.lstimer(self.number as usize); + #[cfg(not(esp32))] + let tmr = self.ledc.timer(self.number as usize); - #[cfg(not(esp32))] - /// Update the timer in HW - fn update_hw(&self) { - match self.number { - Number::Timer0 => self.ledc.timer0_conf().modify(|_, w| w.para_up().set_bit()), - Number::Timer1 => self.ledc.timer1_conf().modify(|_, w| w.para_up().set_bit()), - Number::Timer2 => self.ledc.timer2_conf().modify(|_, w| w.para_up().set_bit()), - Number::Timer3 => self.ledc.timer3_conf().modify(|_, w| w.para_up().set_bit()), - }; + tmr.conf().modify(|_, w| w.para_up().set_bit()); } } @@ -417,56 +313,16 @@ impl<'a> TimerHW for Timer<'a, HighSpeed> { let duty = unwrap!(self.duty) as u8; let sel_hstimer = self.clock_source == Some(HSClockSource::APBClk); - match self.number { - Number::Timer0 => self.ledc.hstimer0_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(sel_hstimer) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer1 => self.ledc.hstimer1_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(sel_hstimer) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer2 => self.ledc.hstimer2_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(sel_hstimer) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - Number::Timer3 => self.ledc.hstimer3_conf().modify(|_, w| unsafe { - w.tick_sel() - .bit(sel_hstimer) - .rst() - .clear_bit() - .pause() - .clear_bit() - .div_num() - .bits(divisor) - .duty_res() - .bits(duty) - }), - }; + self.ledc + .hstimer(self.number as usize) + .conf() + .modify(|_, w| unsafe { + w.tick_sel().bit(sel_hstimer); + w.rst().clear_bit(); + w.pause().clear_bit(); + w.div_num().bits(divisor); + w.duty_res().bits(duty) + }); } /// Update the timer in HW diff --git a/esp-lp-hal/Cargo.toml b/esp-lp-hal/Cargo.toml index 4bde78770..2dcf21502 100644 --- a/esp-lp-hal/Cargo.toml +++ b/esp-lp-hal/Cargo.toml @@ -24,9 +24,9 @@ categories = [ cfg-if = "1.0.0" embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", optional = true, features = ["unproven"] } embedded-hal-1 = { version = "1.0.0", package = "embedded-hal", optional = true } -esp32c6-lp = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32s2-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } -esp32s3-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "efd414c", features = ["critical-section"], optional = true } +esp32c6-lp = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32s2-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } +esp32s3-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "a8a8340", features = ["critical-section"], optional = true } nb = { version = "1.1.0", optional = true } paste = { version = "1.0.14", optional = true } procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }