From d4e571c13ca30023cf24b0dbcf0781b27a6f9292 Mon Sep 17 00:00:00 2001 From: "K." Date: Mon, 21 Oct 2024 02:59:19 +0500 Subject: [PATCH 1/5] Add sigma-delta modulation driver Solution for issue #2370 --- esp-hal/src/lib.rs | 2 + esp-hal/src/sdm.rs | 257 ++++++++++++++++++++++++++++++ esp-metadata/devices/esp32.toml | 1 + esp-metadata/devices/esp32c3.toml | 1 + esp-metadata/devices/esp32c6.toml | 1 + esp-metadata/devices/esp32h2.toml | 1 + esp-metadata/devices/esp32p4.toml | 1 + esp-metadata/devices/esp32s2.toml | 1 + esp-metadata/devices/esp32s3.toml | 1 + 9 files changed, 266 insertions(+) create mode 100644 esp-hal/src/sdm.rs diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index df92a6d6f4d..2a9bd2b428a 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -216,6 +216,8 @@ pub mod rom; pub mod rsa; #[cfg(any(lp_clkrst, rtc_cntl))] pub mod rtc_cntl; +#[cfg(sdm)] +pub mod sdm; #[cfg(sha)] pub mod sha; #[cfg(any(spi0, spi1, spi2, spi3))] diff --git a/esp-hal/src/sdm.rs b/esp-hal/src/sdm.rs new file mode 100644 index 00000000000..88960e28e73 --- /dev/null +++ b/esp-hal/src/sdm.rs @@ -0,0 +1,257 @@ +//! Sigma-Delta modulation peripheral driver. + +use fugit::HertzU32; + +use crate::{ + clock::Clocks, + gpio::{OutputSignal, PeripheralOutput}, + peripheral::{Peripheral, PeripheralRef}, + peripherals, + private, +}; + +/// Sigma-Delta modulation peripheral driver. +pub struct Sdm<'d, SD> { + _sd: PeripheralRef<'d, SD>, + channels_usage: u8, +} + +/// Channel errors +#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + /// Prescale out of range + PrescaleRange, + /// No free channels to use + NoChannels, +} + +impl<'d, SD> Sdm<'d, SD> +where + SD: RegisterAccess, +{ + /// Initialize driver using a given SD instance. + pub fn new(sd_instance: impl crate::peripheral::Peripheral

+ 'd) -> Self { + Self { + _sd: sd_instance.into_ref(), + channels_usage: 0, + } + } + + /// Configure and acquire channel. + pub fn enable_pin( + &mut self, + pin: impl Peripheral

+ 'd, + frequency: HertzU32, + ) -> Result, Error> { + crate::into_ref!(pin); + + let chs = self.channels_usage; + let chidx = self.alloc_channel()?; + let signal = CHANNELS[chidx as usize]; + + if chs == 0 { + SD::enable_clock(true); + } + + pin.connect_peripheral_to_output(signal, private::Internal); + + let mut channel = Channel { + _sdm: self, + pin, + chidx, + }; + + channel.set_frequency(frequency)?; + + Ok(channel) + } + + /// Deconfigure and release channel. + pub fn disable_pin(&mut self, channel: Channel<'d, SD, PIN>) { + let Channel { mut pin, chidx, .. } = channel; + + let signal = CHANNELS[chidx as usize]; + + pin.disconnect_from_peripheral_output(signal, private::Internal); + + self.dealloc_channel(chidx); + + if self.channels_usage == 0 { + SD::enable_clock(false); + } + } + + fn alloc_channel(&mut self) -> Result { + let mut usage = self.channels_usage; + let mut chidx: u8 = 0; + while usage & 1 != 0 && chidx < CHANNELS.len() as u8 { + usage >>= 1; + chidx += 1; + } + if chidx < CHANNELS.len() as u8 { + self.channels_usage |= 1 << chidx; + Ok(chidx) + } else { + Err(Error::NoChannels) + } + } + + fn dealloc_channel(&mut self, chidx: u8) { + self.channels_usage &= !(1 << chidx); + } +} + +/// Sigma-Delta modulation channel handle. +pub struct Channel<'d, SD, PIN> { + _sdm: &'d Sdm<'d, SD>, + pin: PeripheralRef<'d, PIN>, + chidx: u8, +} + +impl<'d, SD, PIN> Channel<'d, SD, PIN> +where + SD: RegisterAccess, +{ + /// Set raw pulse density + /// + /// Sigma-delta quantized density of one channel, the value ranges from -128 + /// to 127, recommended range is -90 ~ 90. The waveform is more like a + /// random one in this range. + pub fn set_pulse_density(&mut self, density: i8) { + SD::set_pulse_density(self.chidx, density); + } + + /// Set duty cycle + pub fn set_duty(&mut self, duty: u8) { + let density = duty as i16 - 128; + self.set_pulse_density(density as i8) + } + + /// Set raw prescale + /// + /// The divider of source clock, ranges from 1 to 256 + pub fn set_prescale(&mut self, prescale: u16) -> Result<(), Error> { + if (1..=256).contains(&prescale) { + SD::set_prescale(self.chidx, prescale); + Ok(()) + } else { + Err(Error::PrescaleRange) + } + } + + /// Set prescale using frequency + pub fn set_frequency(&mut self, frequency: HertzU32) -> Result<(), Error> { + let clocks = Clocks::get(); + let clock_frequency = clocks.apb_clock.to_Hz(); + let frequency = frequency.to_Hz(); + + let prescale = prescale_from_frequency(clock_frequency, frequency); + + self.set_prescale(prescale) + } +} + +mod ehal1 { + use embedded_hal::pwm::{Error as PwmError, ErrorKind, ErrorType, SetDutyCycle}; + + use super::{Channel, Error, RegisterAccess}; + use crate::gpio::OutputPin; + + impl PwmError for Error { + fn kind(&self) -> ErrorKind { + ErrorKind::Other + } + } + + impl<'d, SD: RegisterAccess, PIN: OutputPin> ErrorType for Channel<'d, SD, PIN> { + type Error = Error; + } + + impl<'d, SD: RegisterAccess, PIN: OutputPin> SetDutyCycle for Channel<'d, SD, PIN> { + fn max_duty_cycle(&self) -> u16 { + 255 + } + + fn set_duty_cycle(&mut self, mut duty: u16) -> Result<(), Self::Error> { + let max = self.max_duty_cycle(); + duty = if duty > max { max } else { duty }; + self.set_duty(duty as u8); + Ok(()) + } + } +} + +#[cfg(any(esp32, esp32s2, esp32s3))] +const CHANNELS: [OutputSignal; 8] = [ + OutputSignal::GPIO_SD0, + OutputSignal::GPIO_SD1, + OutputSignal::GPIO_SD2, + OutputSignal::GPIO_SD3, + OutputSignal::GPIO_SD4, + OutputSignal::GPIO_SD5, + OutputSignal::GPIO_SD6, + OutputSignal::GPIO_SD7, +]; + +#[cfg(any(esp32c3, esp32c6, esp32h2))] +const CHANNELS: [OutputSignal; 4] = [ + OutputSignal::GPIO_SD0, + OutputSignal::GPIO_SD1, + OutputSignal::GPIO_SD2, + OutputSignal::GPIO_SD3, +]; + +#[doc(hidden)] +pub trait RegisterAccess { + /// Enable/disable sigma/delta clock + fn enable_clock(en: bool); + + /// Set channel pulse density + fn set_pulse_density(ch: u8, density: i8); + + /// Set channel clock pre-scale + fn set_prescale(ch: u8, prescale: u16); +} + +impl RegisterAccess for peripherals::GPIO_SD { + fn enable_clock(_en: bool) { + // The clk enable register does not exist on ESP32. + #[cfg(not(esp32))] + { + let sd = unsafe { &*Self::PTR }; + + sd.sigmadelta_misc() + .modify(|_, w| w.function_clk_en().bit(_en)); + } + } + + fn set_pulse_density(ch: u8, density: i8) { + let sd = unsafe { &*Self::PTR }; + + sd.sigmadelta(ch as _) + .modify(|_, w| unsafe { w.in_().bits(density as _) }); + } + + fn set_prescale(ch: u8, prescale: u16) { + let sd = unsafe { &*Self::PTR }; + + sd.sigmadelta(ch as _) + .modify(|_, w| unsafe { w.prescale().bits((prescale - 1) as _) }); + } +} + +fn prescale_from_frequency(clk_freq: u32, req_freq: u32) -> u16 { + let pre = clk_freq / req_freq; + let err = clk_freq % req_freq; + + // Do the normal rounding and error >= (src/n + src/(n+1)) / 2, + // then carry the bit + let pre = if err >= clk_freq / (2 * pre * (pre + 1)) { + pre + 1 + } else { + pre + }; + + pre as _ +} diff --git a/esp-metadata/devices/esp32.toml b/esp-metadata/devices/esp32.toml index e5a70a666f4..6b885acf57a 100644 --- a/esp-metadata/devices/esp32.toml +++ b/esp-metadata/devices/esp32.toml @@ -33,6 +33,7 @@ peripherals = [ "rtc_io", "sdhost", "sens", + "sdm", "sha", "slc", "slchost", diff --git a/esp-metadata/devices/esp32c3.toml b/esp-metadata/devices/esp32c3.toml index 08a62907cb3..f385b633119 100644 --- a/esp-metadata/devices/esp32c3.toml +++ b/esp-metadata/devices/esp32c3.toml @@ -26,6 +26,7 @@ peripherals = [ "rsa", "rtc_cntl", "sensitive", + "sdm", "sha", "spi0", "spi1", diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 128e8a06c24..4c57a6a917a 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -50,6 +50,7 @@ peripherals = [ "rmt", "rng", "rsa", + "sdm", "sha", "slchost", "soc_etm", diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 901f4bd8ef9..803a1ad4bf7 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -44,6 +44,7 @@ peripherals = [ "rmt", "rng", "rsa", + "sdm", "sha", "soc_etm", "spi0", diff --git a/esp-metadata/devices/esp32p4.toml b/esp-metadata/devices/esp32p4.toml index 9d745becd85..4766b8efb7c 100644 --- a/esp-metadata/devices/esp32p4.toml +++ b/esp-metadata/devices/esp32p4.toml @@ -71,6 +71,7 @@ peripherals = [ # "rmt", # "rsa", # "sdhost", + # "sdm", # "sha", # "soc_etm", # "spi0", diff --git a/esp-metadata/devices/esp32s2.toml b/esp-metadata/devices/esp32s2.toml index 2b556cd00cf..0505462981f 100644 --- a/esp-metadata/devices/esp32s2.toml +++ b/esp-metadata/devices/esp32s2.toml @@ -29,6 +29,7 @@ peripherals = [ "rtc_i2c", "rtc_io", "sens", + "sdm", "sha", "spi0", "spi1", diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index 96fbe57278a..b9bd0d29658 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -37,6 +37,7 @@ peripherals = [ "rtc_io", "sens", "sensitive", + "sdm", "sha", "spi0", "spi1", From 89a3b1aea24053a117e59b5747b84eb8d7d35295 Mon Sep 17 00:00:00 2001 From: "K." Date: Mon, 21 Oct 2024 03:00:21 +0500 Subject: [PATCH 2/5] Add example for sigma-delta modulation Issue #2370 --- examples/src/bin/sdm.rs | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 examples/src/bin/sdm.rs diff --git a/examples/src/bin/sdm.rs b/examples/src/bin/sdm.rs new file mode 100644 index 00000000000..c79ca8baa80 --- /dev/null +++ b/examples/src/bin/sdm.rs @@ -0,0 +1,47 @@ +//! Connect an oscilloscope to an IO pin and see the modulation sine wave. +//! +//! Also you may connect low-pass filter to SDM output. +//! +//! The following wiring is assumed for ESP32: +//! - SDM pin => GPIO32 +//! The following wiring is assumed for ESP32S2/S3: +//! - SDM pin => GPIO3 +//! The following wiring is assumed for others: +//! - SDM pin => GPIO2 + +//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 + +#![no_std] +#![no_main] + +use esp_backtrace as _; +use esp_hal::{delay::Delay, gpio::Io, prelude::*, sdm::Sdm}; +use esp_println::println; + +#[entry] +fn main() -> ! { + let peripherals = esp_hal::init(esp_hal::Config::default()); + + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + let modulation_pin = io.pins.gpio32; + } else if #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] { + let modulation_pin = io.pins.gpio3; + } else { + let modulation_pin = io.pins.gpio2; + } + } + + let mut sdm = Sdm::new(peripherals.GPIO_SD); + let mut sdm_ch = sdm.enable_pin(modulation_pin, 100.kHz()).unwrap(); + + let delay = Delay::new(); + + println!("Sigma-delta modulation is on"); + + loop { + sdm_ch.set_pulse_density(0); + delay.delay_millis(1500); + } +} From 8a6260a764f4a8e15b72f639f9af44e12e7c60dc Mon Sep 17 00:00:00 2001 From: "K." Date: Mon, 21 Oct 2024 03:10:55 +0500 Subject: [PATCH 3/5] Add sigma-delta modulation driver to changelog Issue #2370 --- esp-hal/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 4cc717c9cc9..32743ca5265 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add burst transfer support to DMA buffers (#2336) - `AnyPin` now implements `From>`. (#2326) - `Pins::steal()` to unsafely obtain GPIO. (#2335) +- Added `esp_hal::sdm` Sigma-Delta modulation driver (#2370) ### Changed From fa0e2a06f800063be83aed54801649b412aa0f21 Mon Sep 17 00:00:00 2001 From: "K." Date: Mon, 21 Oct 2024 23:01:52 +0500 Subject: [PATCH 4/5] Rework sigma-delta modulation driver --- esp-hal/src/sdm.rs | 211 +++++++++++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 86 deletions(-) diff --git a/esp-hal/src/sdm.rs b/esp-hal/src/sdm.rs index 88960e28e73..b07631fe7c8 100644 --- a/esp-hal/src/sdm.rs +++ b/esp-hal/src/sdm.rs @@ -1,19 +1,72 @@ -//! Sigma-Delta modulation peripheral driver. +//! # Sigma-Delta modulation (SDM) +//! +//! ## Overview +//! +//! Almost all ESP SoCs has a second-order sigma-delta modulator, which +//! can generate independent PDM pulses to multiple channels. Please refer +//! to the TRM to check how many hardware channels are available. +//! +//! Delta-sigma modulation converts an analog voltage signal into a pulse +//! frequency, or pulse density, which can be understood as pulse-density +//! modulation (PDM) (refer to [Delta-sigma modulation on Wikipedia](https://en.wikipedia.org/wiki/Delta-sigma_modulation)). +//! +//! Typically, a Sigma-Delta modulated channel can be used in scenarios like: +//! +//! - LED dimming +//! - Simple DAC (8-bit), with the help of an active RC low-pass filter +//! - Class D amplifier, with the help of a half-bridge or full-bridge circuit +//! plus an LC low-pass filter +//! +//! ## Configuration +//! +//! After creating [`Sdm`] instance you should connect individual channels to +//! GPIO outputs. Also you need set modulation frequency. +//! +//! ## Usage +//! +//! Connected channels accepts pulse density in range -128..127. + +use core::marker::PhantomData; use fugit::HertzU32; use crate::{ clock::Clocks, - gpio::{OutputSignal, PeripheralOutput}, + gpio::{OutputPin, OutputSignal}, peripheral::{Peripheral, PeripheralRef}, - peripherals, + peripherals::GPIO_SD, private, }; /// Sigma-Delta modulation peripheral driver. -pub struct Sdm<'d, SD> { - _sd: PeripheralRef<'d, SD>, - channels_usage: u8, +pub struct Sdm<'d> { + /// Channel 0 + pub channel0: ChannelRef<'d, 0>, + + /// Channel 1 + pub channel1: ChannelRef<'d, 1>, + + /// Channel 2 + pub channel2: ChannelRef<'d, 2>, + + /// Channel 3 + pub channel3: ChannelRef<'d, 3>, + + #[cfg(any(esp32, esp32s2, esp32s3))] + /// Channel 4 + pub channel4: ChannelRef<'d, 4>, + + #[cfg(any(esp32, esp32s2, esp32s3))] + /// Channel 5 + pub channel5: ChannelRef<'d, 5>, + + #[cfg(any(esp32, esp32s2, esp32s3))] + /// Channel 6 + pub channel6: ChannelRef<'d, 6>, + + #[cfg(any(esp32, esp32s2, esp32s3))] + /// Channel 7 + pub channel7: ChannelRef<'d, 7>, } /// Channel errors @@ -22,108 +75,95 @@ pub struct Sdm<'d, SD> { pub enum Error { /// Prescale out of range PrescaleRange, - /// No free channels to use - NoChannels, } -impl<'d, SD> Sdm<'d, SD> -where - SD: RegisterAccess, -{ +impl<'d> Drop for Sdm<'d> { + fn drop(&mut self) { + GPIO_SD::enable_clock(false); + } +} + +impl<'d> Sdm<'d> { /// Initialize driver using a given SD instance. - pub fn new(sd_instance: impl crate::peripheral::Peripheral

+ 'd) -> Self { + pub fn new(_sd: impl crate::peripheral::Peripheral

+ 'd) -> Self { + GPIO_SD::enable_clock(true); + Self { - _sd: sd_instance.into_ref(), - channels_usage: 0, + channel0: ChannelRef::new(), + channel1: ChannelRef::new(), + channel2: ChannelRef::new(), + channel3: ChannelRef::new(), + + #[cfg(any(esp32, esp32s2, esp32s3))] + channel4: ChannelRef::new(), + #[cfg(any(esp32, esp32s2, esp32s3))] + channel5: ChannelRef::new(), + #[cfg(any(esp32, esp32s2, esp32s3))] + channel6: ChannelRef::new(), + #[cfg(any(esp32, esp32s2, esp32s3))] + channel7: ChannelRef::new(), } } +} - /// Configure and acquire channel. - pub fn enable_pin( - &mut self, - pin: impl Peripheral

+ 'd, - frequency: HertzU32, - ) -> Result, Error> { - crate::into_ref!(pin); - - let chs = self.channels_usage; - let chidx = self.alloc_channel()?; - let signal = CHANNELS[chidx as usize]; +/// Sigma-Delta modulation channel reference. +pub struct ChannelRef<'d, const N: u8> { + _phantom: PhantomData<&'d ()>, +} - if chs == 0 { - SD::enable_clock(true); +impl<'d, const N: u8> ChannelRef<'d, N> { + fn new() -> Self { + Self { + _phantom: PhantomData, } - - pin.connect_peripheral_to_output(signal, private::Internal); - - let mut channel = Channel { - _sdm: self, - pin, - chidx, - }; - - channel.set_frequency(frequency)?; - - Ok(channel) } - /// Deconfigure and release channel. - pub fn disable_pin(&mut self, channel: Channel<'d, SD, PIN>) { - let Channel { mut pin, chidx, .. } = channel; - - let signal = CHANNELS[chidx as usize]; + /// Configure and connect sigma-delta channel to output + pub fn connect( + &'d self, + output: impl Peripheral

+ 'd, + frequency: HertzU32, + ) -> Result, Error> { + crate::into_ref!(output); - pin.disconnect_from_peripheral_output(signal, private::Internal); + let signal = CHANNELS[N as usize]; - self.dealloc_channel(chidx); + output.connect_peripheral_to_output(signal, private::Internal); - if self.channels_usage == 0 { - SD::enable_clock(false); - } - } + let channel = Channel { _ref: self, output }; - fn alloc_channel(&mut self) -> Result { - let mut usage = self.channels_usage; - let mut chidx: u8 = 0; - while usage & 1 != 0 && chidx < CHANNELS.len() as u8 { - usage >>= 1; - chidx += 1; - } - if chidx < CHANNELS.len() as u8 { - self.channels_usage |= 1 << chidx; - Ok(chidx) - } else { - Err(Error::NoChannels) - } - } + channel.set_frequency(frequency)?; - fn dealloc_channel(&mut self, chidx: u8) { - self.channels_usage &= !(1 << chidx); + Ok(channel) } } /// Sigma-Delta modulation channel handle. -pub struct Channel<'d, SD, PIN> { - _sdm: &'d Sdm<'d, SD>, - pin: PeripheralRef<'d, PIN>, - chidx: u8, +pub struct Channel<'d, const N: u8, O: OutputPin> { + _ref: &'d ChannelRef<'d, N>, + output: PeripheralRef<'d, O>, +} + +impl<'d, const N: u8, O: OutputPin> Drop for Channel<'d, N, O> { + fn drop(&mut self) { + let signal = CHANNELS[N as usize]; + self.output + .disconnect_from_peripheral_output(signal, private::Internal); + } } -impl<'d, SD, PIN> Channel<'d, SD, PIN> -where - SD: RegisterAccess, -{ +impl<'d, const N: u8, O: OutputPin> Channel<'d, N, O> { /// Set raw pulse density /// /// Sigma-delta quantized density of one channel, the value ranges from -128 /// to 127, recommended range is -90 ~ 90. The waveform is more like a /// random one in this range. - pub fn set_pulse_density(&mut self, density: i8) { - SD::set_pulse_density(self.chidx, density); + pub fn set_pulse_density(&self, density: i8) { + GPIO_SD::set_pulse_density(N, density); } /// Set duty cycle - pub fn set_duty(&mut self, duty: u8) { + pub fn set_duty(&self, duty: u8) { let density = duty as i16 - 128; self.set_pulse_density(density as i8) } @@ -131,9 +171,9 @@ where /// Set raw prescale /// /// The divider of source clock, ranges from 1 to 256 - pub fn set_prescale(&mut self, prescale: u16) -> Result<(), Error> { + pub fn set_prescale(&self, prescale: u16) -> Result<(), Error> { if (1..=256).contains(&prescale) { - SD::set_prescale(self.chidx, prescale); + GPIO_SD::set_prescale(N, prescale); Ok(()) } else { Err(Error::PrescaleRange) @@ -141,7 +181,7 @@ where } /// Set prescale using frequency - pub fn set_frequency(&mut self, frequency: HertzU32) -> Result<(), Error> { + pub fn set_frequency(&self, frequency: HertzU32) -> Result<(), Error> { let clocks = Clocks::get(); let clock_frequency = clocks.apb_clock.to_Hz(); let frequency = frequency.to_Hz(); @@ -155,8 +195,7 @@ where mod ehal1 { use embedded_hal::pwm::{Error as PwmError, ErrorKind, ErrorType, SetDutyCycle}; - use super::{Channel, Error, RegisterAccess}; - use crate::gpio::OutputPin; + use super::{Channel, Error, OutputPin}; impl PwmError for Error { fn kind(&self) -> ErrorKind { @@ -164,11 +203,11 @@ mod ehal1 { } } - impl<'d, SD: RegisterAccess, PIN: OutputPin> ErrorType for Channel<'d, SD, PIN> { + impl<'d, const N: u8, O: OutputPin> ErrorType for Channel<'d, N, O> { type Error = Error; } - impl<'d, SD: RegisterAccess, PIN: OutputPin> SetDutyCycle for Channel<'d, SD, PIN> { + impl<'d, const N: u8, O: OutputPin> SetDutyCycle for Channel<'d, N, O> { fn max_duty_cycle(&self) -> u16 { 255 } @@ -214,7 +253,7 @@ pub trait RegisterAccess { fn set_prescale(ch: u8, prescale: u16); } -impl RegisterAccess for peripherals::GPIO_SD { +impl RegisterAccess for GPIO_SD { fn enable_clock(_en: bool) { // The clk enable register does not exist on ESP32. #[cfg(not(esp32))] From 4c6c403d0ba303e1e817a2b6f52af79a3b55023f Mon Sep 17 00:00:00 2001 From: "K." Date: Mon, 21 Oct 2024 23:02:06 +0500 Subject: [PATCH 5/5] Update sigma-delta modulation example --- examples/src/bin/sdm.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/src/bin/sdm.rs b/examples/src/bin/sdm.rs index c79ca8baa80..4d468cd6af6 100644 --- a/examples/src/bin/sdm.rs +++ b/examples/src/bin/sdm.rs @@ -1,4 +1,4 @@ -//! Connect an oscilloscope to an IO pin and see the modulation sine wave. +//! Connect an oscilloscope to an IO pin and see the modulation sawtooth wave. //! //! Also you may connect low-pass filter to SDM output. //! @@ -33,15 +33,17 @@ fn main() -> ! { } } - let mut sdm = Sdm::new(peripherals.GPIO_SD); - let mut sdm_ch = sdm.enable_pin(modulation_pin, 100.kHz()).unwrap(); + let sdm = Sdm::new(peripherals.GPIO_SD); + let sdm_ch = sdm.channel0.connect(modulation_pin, 100.kHz()).unwrap(); let delay = Delay::new(); println!("Sigma-delta modulation is on"); loop { - sdm_ch.set_pulse_density(0); - delay.delay_millis(1500); + for density in -90..90 { + sdm_ch.set_pulse_density(density); + delay.delay_millis(1); + } } }