From 663c83377a4b3da05dbf954203ed04865f13eafa Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 2 Jan 2023 06:03:25 -0800 Subject: [PATCH 01/16] start of pulse counter implementation --- esp-hal-common/src/gpio/esp32s3.rs | 16 ++ esp-hal-common/src/lib.rs | 1 + esp-hal-common/src/pcnt/channel.rs | 261 ++++++++++++++++++++++ esp-hal-common/src/pcnt/mod.rs | 29 +++ esp-hal-common/src/pcnt/unit.rs | 177 +++++++++++++++ esp-hal-common/src/peripherals/esp32s3.rs | 1 + esp-hal-common/src/system.rs | 7 + esp32s3-hal/src/lib.rs | 1 + 8 files changed, 493 insertions(+) create mode 100644 esp-hal-common/src/pcnt/channel.rs create mode 100644 esp-hal-common/src/pcnt/mod.rs create mode 100644 esp-hal-common/src/pcnt/unit.rs diff --git a/esp-hal-common/src/gpio/esp32s3.rs b/esp-hal-common/src/gpio/esp32s3.rs index e51df318e41..aaafc52773a 100644 --- a/esp-hal-common/src/gpio/esp32s3.rs +++ b/esp-hal-common/src/gpio/esp32s3.rs @@ -63,6 +63,22 @@ pub enum InputSignal { I2S1I_SD = 30, I2S1I_BCK = 31, I2S1I_WS = 32, + PCNT0_SIG_CH0 = 33, + PCNT0_SIG_CH1 = 34, + PCNT0_CTRL_CH0 = 35, + PCNT0_CTRL_CH1 = 36, + PCNT1_SIG_CH0 = 37, + PCNT1_SIG_CH1 = 38, + PCNT1_CTRL_CH0 = 39, + PCNT1_CTRL_CH1 = 40, + PCNT2_SIG_CH0 = 41, + PCNT2_SIG_CH1 = 42, + PCNT2_CTRL_CH0 = 43, + PCNT2_CTRL_CH1 = 44, + PCNT3_SIG_CH0 = 45, + PCNT3_SIG_CH1 = 46, + PCNT3_CTRL_CH0 = 47, + PCNT3_CTRL_CH1 = 48, I2S0I_SD1 = 51, I2S0I_SD2 = 52, I2S0I_SD3 = 53, diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 89070691f34..38dfeb29e99 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -60,6 +60,7 @@ pub mod ledc; pub mod mcpwm; #[cfg(usb_otg)] pub mod otg_fs; +pub mod pcnt; pub mod peripheral; pub mod prelude; #[cfg(rmt)] diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs new file mode 100644 index 00000000000..b3f3c3d0174 --- /dev/null +++ b/esp-hal-common/src/pcnt/channel.rs @@ -0,0 +1,261 @@ +use crate::{ + gpio::{types::InputSignal, InputPin}, + peripheral::{PeripheralRef, Peripheral}, + peripherals::{GPIO, pcnt::RegisterBlock}, +}; + +use super::unit; + + +/// Channel number +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum Number { + Channel0, + Channel1, +} + +/// PCNT channel action on signal edge +#[derive(Debug, Copy, Clone, Default)] +pub enum EdgeMode { + /// Hold current count value + Hold = 0, + /// Increase count value + #[default] + Increment = 1, + /// Decrease count value + Decrement = 2, +} + +/// PCNT channel action on control level +#[derive(Debug, Copy, Clone, Default)] +pub enum CtrlMode { + /// Keep current count mode + Keep = 0, + /// Invert current count mode (increase -> decrease, decrease -> increase) + #[default] + Reverse = 1, + /// Hold current count value + Disable = 2, +} + +/// Pulse Counter configuration for a single channel +#[derive(Debug, Copy, Clone, Default)] +pub struct Config { + /// PCNT low control mode + pub lctrl_mode: CtrlMode, + /// PCNT high control mode + pub hctrl_mode: CtrlMode, + /// PCNT signal positive edge count mode + pub pos_edge: EdgeMode, + /// PCNT signal negative edge count mode + pub neg_edge: EdgeMode, + pub invert_ctrl: bool, + pub invert_sig: bool +} + +/// PcntPin can be always high, always low, or an actual pin +pub enum PcntPin<'a, P: InputPin> { + Pin(PeripheralRef<'a, P>), + High, + Low, +} + +impl<'a, P: InputPin> PcntPin<'a, P> { + pub fn from_pin(pin: impl Peripheral

+ 'a) -> Self { + crate::into_ref!(pin); + PcntPin::Pin(pin) + } +} + +impl<'a, P: InputPin> From> for u8 { + fn from(pin: PcntPin<'a, P>) -> Self { + match pin { + PcntPin::Pin(pin) => { + pin.number() + } + PcntPin::High => 0x38u8, + PcntPin::Low => 0x3cu8, + } + } +} + +pub struct Channel<'a> { + pcnt: &'a RegisterBlock, + unit: unit::Number, + channel: Number, +} +impl<'a> Channel<'a> { + /// return a new Unit + pub fn new( + unit: unit::Number, + channel: Number, + ) -> Self { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + Self { + pcnt, + unit, + channel, + } + } + + pub fn configure<'b, CP: InputPin, EP: InputPin>( + &mut self, + ctrl_pin: PcntPin<'b, CP>, + sig_pin: PcntPin<'b, EP>, + config: Config + ) { + + let conf0 = match self.unit { + unit::Number::Unit0 => &self.pcnt.u0_conf0, + unit::Number::Unit1 => &self.pcnt.u1_conf0, + unit::Number::Unit2 => &self.pcnt.u2_conf0, + unit::Number::Unit3 => &self.pcnt.u3_conf0, + #[cfg(not(esp32s3))] + unit::Number::Unit4 => &self.pcnt.u4_conf0, + #[cfg(not(esp32s3))] + unit::Number::Unit5 => &self.pcnt.u5_conf0, + #[cfg(not(esp32s3))] + unit::Number::Unit6 => &self.pcnt.u6_conf0, + #[cfg(not(esp32s3))] + unit::Number::Unit7 => &self.pcnt.u7_conf0, + }; + match self.channel { + Number::Channel0 => { + conf0.modify(|_, w| unsafe { + w.ch0_hctrl_mode_u().bits(config.hctrl_mode as u8) + .ch0_lctrl_mode_u().bits(config.lctrl_mode as u8) + .ch0_neg_mode_u().bits(config.neg_edge as u8) + .ch0_pos_mode_u().bits(config.pos_edge as u8) + }); + }, + Number::Channel1 => { + conf0.modify(|_, w| unsafe { + w.ch1_hctrl_mode_u().bits(config.hctrl_mode as u8) + .ch1_lctrl_mode_u().bits(config.lctrl_mode as u8) + .ch1_neg_mode_u().bits(config.neg_edge as u8) + .ch1_pos_mode_u().bits(config.pos_edge as u8) + }); + }, + } + self.set_ctrl_pin(ctrl_pin, config.invert_ctrl); + self.set_sig_pin(sig_pin, config.invert_sig); + } + + pub fn set_ctrl_pin<'b, P: InputPin>( + &self, + pin: PcntPin<'b, P>, + invert: bool, + ) -> &Self { + let signal = match self.unit { + unit::Number::Unit0 => match self.channel { + Number::Channel0 => InputSignal::PCNT0_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT0_CTRL_CH1, + }, + unit::Number::Unit1 => match self.channel { + Number::Channel0 => InputSignal::PCNT1_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT1_CTRL_CH1, + }, + unit::Number::Unit2 => match self.channel { + Number::Channel0 => InputSignal::PCNT2_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT2_CTRL_CH1, + }, + unit::Number::Unit3 => match self.channel { + Number::Channel0 => InputSignal::PCNT3_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT3_CTRL_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit4 => match self.channel { + Number::Channel0 => InputSignal::PCNT4_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT4_CTRL_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit5 => match self.channel { + Number::Channel0 => InputSignal::PCNT5_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT5_CTRL_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit6 => match self.channel { + Number::Channel0 => InputSignal::PCNT6_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT6_CTRL_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit7 => match self.channel { + Number::Channel0 => InputSignal::PCNT7_CTRL_CH0, + Number::Channel1 => InputSignal::PCNT7_CTRL_CH1, + }, + }; + let pin_num: u8 = pin.into(); + + if (signal as usize) <= crate::types::INPUT_SIGNAL_MAX as usize { + unsafe { &*GPIO::PTR }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { + w.sel() + .set_bit() + .in_inv_sel() + .bit(invert) + .in_sel() + .bits(pin_num) + }); + } + self + } + + pub fn set_sig_pin<'b, P: InputPin>( + &self, + pin: PcntPin<'b, P>, + invert: bool, + ) -> &Self { + let signal = match self.unit { + unit::Number::Unit0 => match self.channel { + Number::Channel0 => InputSignal::PCNT0_SIG_CH0, + Number::Channel1 => InputSignal::PCNT0_SIG_CH1, + }, + unit::Number::Unit1 => match self.channel { + Number::Channel0 => InputSignal::PCNT1_SIG_CH0, + Number::Channel1 => InputSignal::PCNT1_SIG_CH1, + }, + unit::Number::Unit2 => match self.channel { + Number::Channel0 => InputSignal::PCNT2_SIG_CH0, + Number::Channel1 => InputSignal::PCNT2_SIG_CH1, + }, + unit::Number::Unit3 => match self.channel { + Number::Channel0 => InputSignal::PCNT3_SIG_CH0, + Number::Channel1 => InputSignal::PCNT3_SIG_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit4 => match self.channel { + Number::Channel0 => InputSignal::PCNT4_SIG_CH0, + Number::Channel1 => InputSignal::PCNT4_SIG_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit5 => match self.channel { + Number::Channel0 => InputSignal::PCNT5_SIG_CH0, + Number::Channel1 => InputSignal::PCNT5_SIG_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit6 => match self.channel { + Number::Channel0 => InputSignal::PCNT6_SIG_CH0, + Number::Channel1 => InputSignal::PCNT6_SIG_CH1, + }, + #[cfg(not(esp32s3))] + unit::Number::Unit7 => match self.channel { + Number::Channel0 => InputSignal::PCNT7_SIG_CH0, + Number::Channel1 => InputSignal::PCNT7_SIG_CH1, + }, + }; + let pin_num: u8 = pin.into(); + + if (signal as usize) <= crate::types::INPUT_SIGNAL_MAX as usize { + unsafe { &*GPIO::PTR }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { + w.sel() + .set_bit() + .in_inv_sel() + .bit(invert) + .in_sel() + .bits(pin_num) + }); + } + self + } + + +} diff --git a/esp-hal-common/src/pcnt/mod.rs b/esp-hal-common/src/pcnt/mod.rs new file mode 100644 index 00000000000..21785c1dfd3 --- /dev/null +++ b/esp-hal-common/src/pcnt/mod.rs @@ -0,0 +1,29 @@ +use self::unit::Unit; +use crate::{peripheral::{PeripheralRef, Peripheral}, system::PeripheralClockControl}; + +pub mod unit; +pub mod channel; + +pub struct PCNT<'d> { + _instance: PeripheralRef<'d, crate::peripherals::PCNT>, +} + +impl<'d> PCNT<'d> { + /// Return a new PCNT + pub fn new( + _instance: impl Peripheral

+ 'd, + peripheral_clock_control: &mut PeripheralClockControl, + ) -> Self { + crate::into_ref!(_instance); + // Enable the PCNT peripherals clock in the system peripheral + peripheral_clock_control.enable(crate::system::Peripheral::Pcnt); + PCNT { + _instance, + } + } + + /// Return a unit + pub fn get_unit(&self, number: unit::Number) -> Unit { + Unit::new(number) + } +} diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs new file mode 100644 index 00000000000..2389b24cb0a --- /dev/null +++ b/esp-hal-common/src/pcnt/unit.rs @@ -0,0 +1,177 @@ +use esp32s3::pcnt::RegisterBlock; + +use super::channel; + +/// Unit number +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum Number { + Unit0, + Unit1, + Unit2, + Unit3, + #[cfg(not(esp32s3))] + Unit4, + #[cfg(not(esp32s3))] + Unit5, + #[cfg(not(esp32s3))] + Unit6, + #[cfg(not(esp32s3))] + Unit7, +} + +/// Unit configuration +#[derive(Copy, Clone)] +pub struct Config { + pub low_limit: i16, + pub high_limit: i16, +} + +pub struct Unit<'a> { + pcnt: &'a RegisterBlock, + number: Number, +} + +impl<'a> Unit<'a> { + /// return a new Unit + pub fn new(number: Number) -> Self { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + Self { + pcnt, + number, + } + } + + pub fn configure(&mut self, config: Config) { + + match self.number { + Number::Unit0 => { + self.pcnt.u0_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + Number::Unit1 => { + self.pcnt.u1_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + Number::Unit2 => { + self.pcnt.u2_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + Number::Unit3 => { + self.pcnt.u3_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + #[cfg(not(esp32s3))] + Number::Unit4 => { + self.pcnt.u4_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + #[cfg(not(esp32s3))] + Number::Unit5 => { + self.pcnt.u5_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + #[cfg(not(esp32s3))] + Number::Unit6 => { + self.pcnt.u6_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + #[cfg(not(esp32s3))] + Number::Unit7 => { + self.pcnt.u7_conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + }, + } + self.pause(); + self.clear(); + } + + pub fn get_channel(&self, number: channel::Number) -> super::channel::Channel { + super::channel::Channel::new(self.number, number) + } + + pub fn clear(&self) { + match self.number { + Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().set_bit()), + Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().set_bit()), + Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().set_bit()), + Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().set_bit()), + } + // TODO: does this need a delay? (liebman / Jan 2 2023) + match self.number { + Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().clear_bit()), + Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().clear_bit()), + Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().clear_bit()), + Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().clear_bit()), + } + } + + pub fn pause(&self) { + match self.number { + Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().set_bit()), + Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().set_bit()), + Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().set_bit()), + Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), + #[cfg(not(esp32s3))] + Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), + } + } + + pub fn resume(&self) { + match self.number { + Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().clear_bit()), + Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().clear_bit()), + Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().clear_bit()), + Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().clear_bit()), + #[cfg(not(esp32s3))] + Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().clear_bit()), + } + } + + pub fn get_value(&self) -> i16 { + self.pcnt.u_cnt[self.number as usize].read().pulse_cnt_u().bits() as i16 + } +} diff --git a/esp-hal-common/src/peripherals/esp32s3.rs b/esp-hal-common/src/peripherals/esp32s3.rs index 92248e320e3..66e74a29c8f 100644 --- a/esp-hal-common/src/peripherals/esp32s3.rs +++ b/esp-hal-common/src/peripherals/esp32s3.rs @@ -79,6 +79,7 @@ mod peripherals { USB_DEVICE, SYSTEM, LEDC, + PCNT, RMT, I2S0, I2S1, diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index bce01d8178d..484cd22b977 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -30,6 +30,8 @@ pub enum Peripheral { Mcpwm0, #[cfg(any(esp32, esp32s3))] Mcpwm1, + #[cfg(any(esp32, esp32s2, esp32s3))] + Pcnt, #[cfg(any(esp32c2, esp32c3))] ApbSarAdc, #[cfg(gdma)] @@ -108,6 +110,11 @@ impl PeripheralClockControl { perip_clk_en0.modify(|_, w| w.pwm1_clk_en().set_bit()); perip_rst_en0.modify(|_, w| w.pwm1_rst().clear_bit()); } + #[cfg(any(esp32, esp32s2, esp32s3))] + Peripheral::Pcnt => { + perip_clk_en0.modify(|_, w| w.pcnt_clk_en().set_bit()); + perip_rst_en0.modify(|_, w| w.pcnt_rst().clear_bit()); + } #[cfg(any(esp32c2, esp32c3))] Peripheral::ApbSarAdc => { perip_clk_en0.modify(|_, w| w.apb_saradc_clk_en().set_bit()); diff --git a/esp32s3-hal/src/lib.rs b/esp32s3-hal/src/lib.rs index 1025c82d5b4..86c4a3d3b72 100644 --- a/esp32s3-hal/src/lib.rs +++ b/esp32s3-hal/src/lib.rs @@ -20,6 +20,7 @@ pub use esp_hal_common::{ macros, mcpwm, otg_fs, + pcnt, peripherals, prelude, pulse_control, From bca0773428d29f53a27592ea0dd30d553b3fdd81 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 2 Jan 2023 09:19:09 -0800 Subject: [PATCH 02/16] implement interrupts implement pcnt for esp32, esp32s2, and esp32s3 --- esp-hal-common/src/lib.rs | 1 + esp-hal-common/src/pcnt/channel.rs | 52 ++-- esp-hal-common/src/pcnt/unit.rs | 278 +++++++++++++--------- esp-hal-common/src/peripherals/esp32.rs | 1 + esp-hal-common/src/peripherals/esp32s2.rs | 1 + esp32-hal/src/lib.rs | 1 + esp32s2-hal/src/lib.rs | 1 + 7 files changed, 192 insertions(+), 143 deletions(-) diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 38dfeb29e99..07234f7ded1 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -60,6 +60,7 @@ pub mod ledc; pub mod mcpwm; #[cfg(usb_otg)] pub mod otg_fs; +#[cfg(any(esp32, esp32s2, esp32s3))] pub mod pcnt; pub mod peripheral; pub mod prelude; diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index b3f3c3d0174..4cb0a9d136f 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -1,7 +1,7 @@ use crate::{ gpio::{types::InputSignal, InputPin}, peripheral::{PeripheralRef, Peripheral}, - peripherals::{GPIO, pcnt::RegisterBlock}, + peripherals::GPIO, }; use super::unit; @@ -79,20 +79,18 @@ impl<'a, P: InputPin> From> for u8 { } } -pub struct Channel<'a> { - pcnt: &'a RegisterBlock, +pub struct Channel { unit: unit::Number, channel: Number, } -impl<'a> Channel<'a> { + +impl Channel { /// return a new Unit pub fn new( unit: unit::Number, channel: Number, ) -> Self { - let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; Self { - pcnt, unit, channel, } @@ -104,20 +102,20 @@ impl<'a> Channel<'a> { sig_pin: PcntPin<'b, EP>, config: Config ) { - + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; let conf0 = match self.unit { - unit::Number::Unit0 => &self.pcnt.u0_conf0, - unit::Number::Unit1 => &self.pcnt.u1_conf0, - unit::Number::Unit2 => &self.pcnt.u2_conf0, - unit::Number::Unit3 => &self.pcnt.u3_conf0, - #[cfg(not(esp32s3))] - unit::Number::Unit4 => &self.pcnt.u4_conf0, - #[cfg(not(esp32s3))] - unit::Number::Unit5 => &self.pcnt.u5_conf0, - #[cfg(not(esp32s3))] - unit::Number::Unit6 => &self.pcnt.u6_conf0, - #[cfg(not(esp32s3))] - unit::Number::Unit7 => &self.pcnt.u7_conf0, + unit::Number::Unit0 => &pcnt.u0_conf0, + unit::Number::Unit1 => &pcnt.u1_conf0, + unit::Number::Unit2 => &pcnt.u2_conf0, + unit::Number::Unit3 => &pcnt.u3_conf0, + #[cfg(esp32)] + unit::Number::Unit4 => &pcnt.u4_conf0, + #[cfg(esp32)] + unit::Number::Unit5 => &pcnt.u5_conf0, + #[cfg(esp32)] + unit::Number::Unit6 => &pcnt.u6_conf0, + #[cfg(esp32)] + unit::Number::Unit7 => &pcnt.u7_conf0, }; match self.channel { Number::Channel0 => { @@ -163,22 +161,22 @@ impl<'a> Channel<'a> { Number::Channel0 => InputSignal::PCNT3_CTRL_CH0, Number::Channel1 => InputSignal::PCNT3_CTRL_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit4 => match self.channel { Number::Channel0 => InputSignal::PCNT4_CTRL_CH0, Number::Channel1 => InputSignal::PCNT4_CTRL_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit5 => match self.channel { Number::Channel0 => InputSignal::PCNT5_CTRL_CH0, Number::Channel1 => InputSignal::PCNT5_CTRL_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit6 => match self.channel { Number::Channel0 => InputSignal::PCNT6_CTRL_CH0, Number::Channel1 => InputSignal::PCNT6_CTRL_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit7 => match self.channel { Number::Channel0 => InputSignal::PCNT7_CTRL_CH0, Number::Channel1 => InputSignal::PCNT7_CTRL_CH1, @@ -221,22 +219,22 @@ impl<'a> Channel<'a> { Number::Channel0 => InputSignal::PCNT3_SIG_CH0, Number::Channel1 => InputSignal::PCNT3_SIG_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit4 => match self.channel { Number::Channel0 => InputSignal::PCNT4_SIG_CH0, Number::Channel1 => InputSignal::PCNT4_SIG_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit5 => match self.channel { Number::Channel0 => InputSignal::PCNT5_SIG_CH0, Number::Channel1 => InputSignal::PCNT5_SIG_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit6 => match self.channel { Number::Channel0 => InputSignal::PCNT6_SIG_CH0, Number::Channel1 => InputSignal::PCNT6_SIG_CH1, }, - #[cfg(not(esp32s3))] + #[cfg(esp32)] unit::Number::Unit7 => match self.channel { Number::Channel0 => InputSignal::PCNT7_SIG_CH0, Number::Channel1 => InputSignal::PCNT7_SIG_CH1, diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index 2389b24cb0a..3e610962834 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -1,4 +1,3 @@ -use esp32s3::pcnt::RegisterBlock; use super::channel; @@ -9,93 +8,64 @@ pub enum Number { Unit1, Unit2, Unit3, - #[cfg(not(esp32s3))] + #[cfg(esp32)] Unit4, - #[cfg(not(esp32s3))] + #[cfg(esp32)] Unit5, - #[cfg(not(esp32s3))] + #[cfg(esp32)] Unit6, - #[cfg(not(esp32s3))] + #[cfg(esp32)] Unit7, } /// Unit configuration -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] pub struct Config { pub low_limit: i16, pub high_limit: i16, + pub filter: Option, } -pub struct Unit<'a> { - pcnt: &'a RegisterBlock, +pub struct Unit { number: Number, } -impl<'a> Unit<'a> { +impl Unit { /// return a new Unit - pub fn new(number: Number) -> Self { - let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + pub(super) fn new(number: Number) -> Self { Self { - pcnt, number, } } pub fn configure(&mut self, config: Config) { - - match self.number { - Number::Unit0 => { - self.pcnt.u0_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, - Number::Unit1 => { - self.pcnt.u1_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, - Number::Unit2 => { - self.pcnt.u2_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, - Number::Unit3 => { - self.pcnt.u3_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, - #[cfg(not(esp32s3))] - Number::Unit4 => { - self.pcnt.u4_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, - #[cfg(not(esp32s3))] - Number::Unit5 => { - self.pcnt.u5_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, - #[cfg(not(esp32s3))] - Number::Unit6 => { - self.pcnt.u6_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, - #[cfg(not(esp32s3))] - Number::Unit7 => { - self.pcnt.u7_conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) - }); - }, + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + let (conf0, conf2) = match self.number { + Number::Unit0 => (&pcnt.u0_conf0, &pcnt.u0_conf2), + Number::Unit1 => (&pcnt.u1_conf0, &pcnt.u1_conf2), + Number::Unit2 => (&pcnt.u2_conf0, &pcnt.u2_conf2), + Number::Unit3 => (&pcnt.u3_conf0, &pcnt.u3_conf2), + #[cfg(esp32)] + Number::Unit4 => (&pcnt.u4_conf0, &pcnt.u4_conf2), + #[cfg(esp32)] + Number::Unit5 => (&pcnt.u5_conf0, &pcnt.u5_conf2), + #[cfg(esp32)] + Number::Unit6 => (&pcnt.u6_conf0, &pcnt.u6_conf2), + #[cfg(esp32)] + Number::Unit7 => (&pcnt.u7_conf0, &pcnt.u7_conf2), + }; + conf2.write(|w| unsafe { + w.cnt_l_lim_u().bits(config.low_limit as u16) + .cnt_h_lim_u().bits(config.high_limit as u16) + }); + if let Some(filter) = config.filter { + // TODO: needs range checking mac is 1023! + conf0.modify(|_, w| unsafe { + w.filter_thres_u().bits(filter) + .filter_en_u().set_bit() + }); + } else { + conf0.modify(|_, w| w.filter_en_u().clear_bit()); } self.pause(); self.clear(); @@ -106,72 +76,148 @@ impl<'a> Unit<'a> { } pub fn clear(&self) { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { - Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().set_bit()), - Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().set_bit()), - Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().set_bit()), - Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().set_bit()), + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().set_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().set_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().set_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().set_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().set_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().set_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().set_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().set_bit()), } // TODO: does this need a delay? (liebman / Jan 2 2023) match self.number { - Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().clear_bit()), - Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().clear_bit()), - Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().clear_bit()), - Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().clear_bit()), + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().clear_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().clear_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().clear_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().clear_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().clear_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().clear_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().clear_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().clear_bit()), } } pub fn pause(&self) { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { - Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().set_bit()), - Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().set_bit()), - Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().set_bit()), - Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), - #[cfg(not(esp32s3))] - Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().set_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().set_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().set_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().set_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().set_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().set_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), } } pub fn resume(&self) { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { - Number::Unit0 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().clear_bit()), - Number::Unit1 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().clear_bit()), - Number::Unit2 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().clear_bit()), - Number::Unit3 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit4 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit5 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit6 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().clear_bit()), - #[cfg(not(esp32s3))] - Number::Unit7 => self.pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().clear_bit()), - } + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().clear_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().clear_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().clear_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().clear_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().clear_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().clear_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().clear_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().clear_bit()), + } + } + + pub fn listen(&self) { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + pcnt.int_ena.write(|w| match self.number { + Number::Unit0 => w.cnt_thr_event_u0_int_ena().set_bit(), + Number::Unit1 => w.cnt_thr_event_u1_int_ena().set_bit(), + Number::Unit2 => w.cnt_thr_event_u2_int_ena().set_bit(), + Number::Unit3 => w.cnt_thr_event_u3_int_ena().set_bit(), + #[cfg(esp32)] + Number::Unit4 => w.cnt_thr_event_u4_int_ena().set_bit(), + #[cfg(esp32)] + Number::Unit5 => w.cnt_thr_event_u5_int_ena().set_bit(), + #[cfg(esp32)] + Number::Unit6 => w.cnt_thr_event_u6_int_ena().set_bit(), + #[cfg(esp32)] + Number::Unit7 => w.cnt_thr_event_u7_int_ena().set_bit(), + }); + } + + pub fn unlisten(&self) { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + pcnt.int_ena.write(|w| match self.number { + Number::Unit0 => w.cnt_thr_event_u0_int_ena().clear_bit(), + Number::Unit1 => w.cnt_thr_event_u1_int_ena().clear_bit(), + Number::Unit2 => w.cnt_thr_event_u2_int_ena().clear_bit(), + Number::Unit3 => w.cnt_thr_event_u3_int_ena().clear_bit(), + #[cfg(esp32)] + Number::Unit4 => w.cnt_thr_event_u4_int_ena().clear_bit(), + #[cfg(esp32)] + Number::Unit5 => w.cnt_thr_event_u5_int_ena().clear_bit(), + #[cfg(esp32)] + Number::Unit6 => w.cnt_thr_event_u6_int_ena().clear_bit(), + #[cfg(esp32)] + Number::Unit7 => w.cnt_thr_event_u7_int_ena().clear_bit(), + }); + } + + pub fn interrupt_set(&self) -> bool { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + match self.number { + Number::Unit0 => pcnt.int_st.read().cnt_thr_event_u0_int_st().bit(), + Number::Unit1 => pcnt.int_st.read().cnt_thr_event_u1_int_st().bit(), + Number::Unit2 => pcnt.int_st.read().cnt_thr_event_u2_int_st().bit(), + Number::Unit3 => pcnt.int_st.read().cnt_thr_event_u3_int_st().bit(), + #[cfg(esp32)] + Number::Unit4 => pcnt.int_st.read().cnt_thr_event_u4_int_st().bit(), + #[cfg(esp32)] + Number::Unit5 => pcnt.int_st.read().cnt_thr_event_u5_int_st().bit(), + #[cfg(esp32)] + Number::Unit6 => pcnt.int_st.read().cnt_thr_event_u6_int_st().bit(), + #[cfg(esp32)] + Number::Unit7 => pcnt.int_st.read().cnt_thr_event_u7_int_st().bit(), + } + } + + pub fn reset_interrupt(&self) { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + pcnt.int_clr.write(|w| match self.number { + Number::Unit0 => w.cnt_thr_event_u0_int_clr().set_bit(), + Number::Unit1 => w.cnt_thr_event_u1_int_clr().set_bit(), + Number::Unit2 => w.cnt_thr_event_u2_int_clr().set_bit(), + Number::Unit3 => w.cnt_thr_event_u3_int_clr().set_bit(), + #[cfg(esp32)] + Number::Unit4 => w.cnt_thr_event_u4_int_clr().set_bit(), + #[cfg(esp32)] + Number::Unit5 => w.cnt_thr_event_u5_int_clr().set_bit(), + #[cfg(esp32)] + Number::Unit6 => w.cnt_thr_event_u6_int_clr().set_bit(), + #[cfg(esp32)] + Number::Unit7 => w.cnt_thr_event_u7_int_clr().set_bit(), + }); } pub fn get_value(&self) -> i16 { - self.pcnt.u_cnt[self.number as usize].read().pulse_cnt_u().bits() as i16 + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + pcnt.u_cnt[self.number as usize].read().pulse_cnt_u().bits() as i16 } } diff --git a/esp-hal-common/src/peripherals/esp32.rs b/esp-hal-common/src/peripherals/esp32.rs index 9b213653bbd..4c647153bdb 100644 --- a/esp-hal-common/src/peripherals/esp32.rs +++ b/esp-hal-common/src/peripherals/esp32.rs @@ -68,6 +68,7 @@ mod peripherals { UART2, DPORT, LEDC, + PCNT, RMT, I2S0, I2S1, diff --git a/esp-hal-common/src/peripherals/esp32s2.rs b/esp-hal-common/src/peripherals/esp32s2.rs index 7c4d42c03df..ae0d7cd769e 100644 --- a/esp-hal-common/src/peripherals/esp32s2.rs +++ b/esp-hal-common/src/peripherals/esp32s2.rs @@ -67,6 +67,7 @@ mod peripherals { UART1, SYSTEM, LEDC, + PCNT, RMT, I2S, USB0, diff --git a/esp32-hal/src/lib.rs b/esp32-hal/src/lib.rs index a213b5a1813..c9c584d36ae 100644 --- a/esp32-hal/src/lib.rs +++ b/esp32-hal/src/lib.rs @@ -19,6 +19,7 @@ pub use esp_hal_common::{ ledc, macros, mcpwm, + pcnt, peripherals, prelude, pulse_control, diff --git a/esp32s2-hal/src/lib.rs b/esp32s2-hal/src/lib.rs index 1c9f481fb53..1b4c59ec1cb 100644 --- a/esp32s2-hal/src/lib.rs +++ b/esp32s2-hal/src/lib.rs @@ -18,6 +18,7 @@ pub use esp_hal_common::{ ledc, macros, otg_fs, + pcnt, peripherals, prelude, pulse_control, From d22563e22dfb7700583c9ff50c2f83bade134556 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 2 Jan 2023 09:28:43 -0800 Subject: [PATCH 03/16] implement pcnt for esp32s2 --- esp-hal-common/src/gpio/esp32s2.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/esp-hal-common/src/gpio/esp32s2.rs b/esp-hal-common/src/gpio/esp32s2.rs index 5d70cd0d3d0..0731fc4d784 100644 --- a/esp-hal-common/src/gpio/esp32s2.rs +++ b/esp-hal-common/src/gpio/esp32s2.rs @@ -102,6 +102,22 @@ pub enum InputSignal { I2S0I_WS = 28, I2CEXT0_SCL = 29, I2CEXT0_SDA = 30, + PCNT0_SIG_CH0 = 39, + PCNT0_SIG_CH1 = 40, + PCNT0_CTRL_CH0 = 41, + PCNT0_CTRL_CH1 = 42, + PCNT1_SIG_CH0 = 43, + PCNT1_SIG_CH1 = 44, + PCNT1_CTRL_CH0 = 45, + PCNT1_CTRL_CH1 = 46, + PCNT2_SIG_CH0 = 47, + PCNT2_SIG_CH1 = 48, + PCNT2_CTRL_CH0 = 49, + PCNT2_CTRL_CH1 = 50, + PCNT3_SIG_CH0 = 51, + PCNT3_SIG_CH1 = 52, + PCNT3_CTRL_CH0 = 53, + PCNT3_CTRL_CH1 = 54, USB_OTG_IDDIG = 64, USB_OTG_AVALID = 65, USB_SRP_BVALID = 66, From ee5b35ed11d7c62f63da10eaa5d31f74627693ae Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 2 Jan 2023 10:06:50 -0800 Subject: [PATCH 04/16] fix esp32 PCNT signal names --- esp-hal-common/src/gpio/esp32.rs | 64 ++++++++++++++++---------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/esp-hal-common/src/gpio/esp32.rs b/esp-hal-common/src/gpio/esp32.rs index 34a436bd00b..1b58efed106 100644 --- a/esp-hal-common/src/gpio/esp32.rs +++ b/esp-hal-common/src/gpio/esp32.rs @@ -116,26 +116,26 @@ pub enum InputSignal { PWM0_F2 = 36, GPIO_BT_ACTIVE = 37, GPIO_BT_PRIORITY = 38, - PCNT_SIG_CH0_0 = 39, - PCNT_SIG_CH1_0 = 40, - PCNT_CTRL_CH0_0 = 41, - PCNT_CTRL_CH1_0 = 42, - PCNT_SIG_CH0_1 = 43, - PCNT_SIG_CH1_1 = 44, - PCNT_CTRL_CH0_1 = 45, - PCNT_CTRL_CH1_1 = 46, - PCNT_SIG_CH0_2 = 47, - PCNT_SIG_CH1_2 = 48, - PCNT_CTRL_CH0_2 = 49, - PCNT_CTRL_CH1_2 = 50, - PCNT_SIG_CH0_3 = 51, - PCNT_SIG_CH1_3 = 52, - PCNT_CTRL_CH0_3 = 53, - PCNT_CTRL_CH1_3 = 54, - PCNT_SIG_CH0_4 = 55, - PCNT_SIG_CH1_4 = 56, - PCNT_CTRL_CH0_4 = 57, - PCNT_CTRL_CH1_4 = 58, + PCNT0_SIG_CH0 = 39, + PCNT0_SIG_CH1 = 40, + PCNT0_CTRL_CH0 = 41, + PCNT0_CTRL_CH1 = 42, + PCNT1_SIG_CH0 = 43, + PCNT1_SIG_CH1 = 44, + PCNT1_CTRL_CH0 = 45, + PCNT1_CTRL_CH1 = 46, + PCNT2_SIG_CH0 = 47, + PCNT2_SIG_CH1 = 48, + PCNT2_CTRL_CH0 = 49, + PCNT2_CTRL_CH1 = 50, + PCNT3_SIG_CH0 = 51, + PCNT3_SIG_CH1 = 52, + PCNT3_CTRL_CH0 = 53, + PCNT3_CTRL_CH1 = 54, + PCNT4_SIG_CH0 = 55, + PCNT4_SIG_CH1 = 56, + PCNT4_CTRL_CH0 = 57, + PCNT4_CTRL_CH1 = 58, HSPICS1 = 61, HSPICS2 = 62, VSPICLK = 63, @@ -146,18 +146,18 @@ pub enum InputSignal { VSPICS0 = 68, VSPICS1 = 69, VSPICS2 = 70, - PCNT_SIG_CH0_5 = 71, - PCNT_SIG_CH1_5 = 72, - PCNT_CTRL_CH0_5 = 73, - PCNT_CTRL_CH1_5 = 74, - PCNT_SIG_CH0_6 = 75, - PCNT_SIG_CH1_6 = 76, - PCNT_CTRL_CH0_6 = 77, - PCNT_CTRL_CH1_6 = 78, - PCNT_SIG_CH0_7 = 79, - PCNT_SIG_CH1_7 = 80, - PCNT_CTRL_CH0_7 = 81, - PCNT_CTRL_CH1_7 = 82, + PCNT5_SIG_CH0 = 71, + PCNT5_SIG_CH1 = 72, + PCNT5_CTRL_CH0 = 73, + PCNT5_CTRL_CH1 = 74, + PCNT6_SIG_CH0 = 75, + PCNT6_SIG_CH1 = 76, + PCNT6_CTRL_CH0 = 77, + PCNT6_CTRL_CH1 = 78, + PCNT7_SIG_CH0 = 79, + PCNT7_SIG_CH1 = 80, + PCNT7_CTRL_CH0 = 81, + PCNT7_CTRL_CH1 = 82, RMT_SIG_0 = 83, RMT_SIG_1 = 84, RMT_SIG_2 = 85, From 84ce7e5368b03a98d2837f13cb54d15c9f2c1f15 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Wed, 4 Jan 2023 09:01:56 -0800 Subject: [PATCH 05/16] update PCNT register/fields for cleaned up PAC --- esp-hal-common/src/pcnt/channel.rs | 16 ++--- esp-hal-common/src/pcnt/unit.rs | 108 ++++++++++++++--------------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index 4cb0a9d136f..a0535aaf89a 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -120,18 +120,18 @@ impl Channel { match self.channel { Number::Channel0 => { conf0.modify(|_, w| unsafe { - w.ch0_hctrl_mode_u().bits(config.hctrl_mode as u8) - .ch0_lctrl_mode_u().bits(config.lctrl_mode as u8) - .ch0_neg_mode_u().bits(config.neg_edge as u8) - .ch0_pos_mode_u().bits(config.pos_edge as u8) + w.ch0_hctrl_mode().bits(config.hctrl_mode as u8) + .ch0_lctrl_mode().bits(config.lctrl_mode as u8) + .ch0_neg_mode().bits(config.neg_edge as u8) + .ch0_pos_mode().bits(config.pos_edge as u8) }); }, Number::Channel1 => { conf0.modify(|_, w| unsafe { - w.ch1_hctrl_mode_u().bits(config.hctrl_mode as u8) - .ch1_lctrl_mode_u().bits(config.lctrl_mode as u8) - .ch1_neg_mode_u().bits(config.neg_edge as u8) - .ch1_pos_mode_u().bits(config.pos_edge as u8) + w.ch1_hctrl_mode().bits(config.hctrl_mode as u8) + .ch1_lctrl_mode().bits(config.lctrl_mode as u8) + .ch1_neg_mode().bits(config.neg_edge as u8) + .ch1_pos_mode().bits(config.pos_edge as u8) }); }, } diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index 3e610962834..ab7f164baca 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -55,17 +55,17 @@ impl Unit { Number::Unit7 => (&pcnt.u7_conf0, &pcnt.u7_conf2), }; conf2.write(|w| unsafe { - w.cnt_l_lim_u().bits(config.low_limit as u16) - .cnt_h_lim_u().bits(config.high_limit as u16) + w.cnt_l_lim().bits(config.low_limit as u16) + .cnt_h_lim().bits(config.high_limit as u16) }); if let Some(filter) = config.filter { // TODO: needs range checking mac is 1023! conf0.modify(|_, w| unsafe { - w.filter_thres_u().bits(filter) - .filter_en_u().set_bit() + w.filter_thres().bits(filter) + .filter_en().set_bit() }); } else { - conf0.modify(|_, w| w.filter_en_u().clear_bit()); + conf0.modify(|_, w| w.filter_en().clear_bit()); } self.pause(); self.clear(); @@ -78,33 +78,33 @@ impl Unit { pub fn clear(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().set_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().set_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().set_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().set_bit()), + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u0().set_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u1().set_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u2().set_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u3().set_bit()), #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().set_bit()), + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u4().set_bit()), #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().set_bit()), + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u5().set_bit()), #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().set_bit()), + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u6().set_bit()), #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().set_bit()), + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u7().set_bit()), } // TODO: does this need a delay? (liebman / Jan 2 2023) match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u0().clear_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u1().clear_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u2().clear_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u3().clear_bit()), + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u0().clear_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u1().clear_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u2().clear_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u3().clear_bit()), #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u4().clear_bit()), + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u4().clear_bit()), #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u5().clear_bit()), + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u5().clear_bit()), #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u6().clear_bit()), + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u6().clear_bit()), #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.pulse_cnt_rst_u7().clear_bit()), + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u7().clear_bit()), } } @@ -147,77 +147,77 @@ impl Unit { pub fn listen(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; pcnt.int_ena.write(|w| match self.number { - Number::Unit0 => w.cnt_thr_event_u0_int_ena().set_bit(), - Number::Unit1 => w.cnt_thr_event_u1_int_ena().set_bit(), - Number::Unit2 => w.cnt_thr_event_u2_int_ena().set_bit(), - Number::Unit3 => w.cnt_thr_event_u3_int_ena().set_bit(), + Number::Unit0 => w.cnt_thr_event_u0().set_bit(), + Number::Unit1 => w.cnt_thr_event_u1().set_bit(), + Number::Unit2 => w.cnt_thr_event_u2().set_bit(), + Number::Unit3 => w.cnt_thr_event_u3().set_bit(), #[cfg(esp32)] - Number::Unit4 => w.cnt_thr_event_u4_int_ena().set_bit(), + Number::Unit4 => w.cnt_thr_event_u4().set_bit(), #[cfg(esp32)] - Number::Unit5 => w.cnt_thr_event_u5_int_ena().set_bit(), + Number::Unit5 => w.cnt_thr_event_u5().set_bit(), #[cfg(esp32)] - Number::Unit6 => w.cnt_thr_event_u6_int_ena().set_bit(), + Number::Unit6 => w.cnt_thr_event_u6().set_bit(), #[cfg(esp32)] - Number::Unit7 => w.cnt_thr_event_u7_int_ena().set_bit(), + Number::Unit7 => w.cnt_thr_event_u7().set_bit(), }); } pub fn unlisten(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; pcnt.int_ena.write(|w| match self.number { - Number::Unit0 => w.cnt_thr_event_u0_int_ena().clear_bit(), - Number::Unit1 => w.cnt_thr_event_u1_int_ena().clear_bit(), - Number::Unit2 => w.cnt_thr_event_u2_int_ena().clear_bit(), - Number::Unit3 => w.cnt_thr_event_u3_int_ena().clear_bit(), + Number::Unit0 => w.cnt_thr_event_u0().clear_bit(), + Number::Unit1 => w.cnt_thr_event_u1().clear_bit(), + Number::Unit2 => w.cnt_thr_event_u2().clear_bit(), + Number::Unit3 => w.cnt_thr_event_u3().clear_bit(), #[cfg(esp32)] - Number::Unit4 => w.cnt_thr_event_u4_int_ena().clear_bit(), + Number::Unit4 => w.cnt_thr_event_u4().clear_bit(), #[cfg(esp32)] - Number::Unit5 => w.cnt_thr_event_u5_int_ena().clear_bit(), + Number::Unit5 => w.cnt_thr_event_u5().clear_bit(), #[cfg(esp32)] - Number::Unit6 => w.cnt_thr_event_u6_int_ena().clear_bit(), + Number::Unit6 => w.cnt_thr_event_u6().clear_bit(), #[cfg(esp32)] - Number::Unit7 => w.cnt_thr_event_u7_int_ena().clear_bit(), + Number::Unit7 => w.cnt_thr_event_u7().clear_bit(), }); } pub fn interrupt_set(&self) -> bool { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { - Number::Unit0 => pcnt.int_st.read().cnt_thr_event_u0_int_st().bit(), - Number::Unit1 => pcnt.int_st.read().cnt_thr_event_u1_int_st().bit(), - Number::Unit2 => pcnt.int_st.read().cnt_thr_event_u2_int_st().bit(), - Number::Unit3 => pcnt.int_st.read().cnt_thr_event_u3_int_st().bit(), + Number::Unit0 => pcnt.int_st.read().cnt_thr_event_u0().bit(), + Number::Unit1 => pcnt.int_st.read().cnt_thr_event_u1().bit(), + Number::Unit2 => pcnt.int_st.read().cnt_thr_event_u2().bit(), + Number::Unit3 => pcnt.int_st.read().cnt_thr_event_u3().bit(), #[cfg(esp32)] - Number::Unit4 => pcnt.int_st.read().cnt_thr_event_u4_int_st().bit(), + Number::Unit4 => pcnt.int_st.read().cnt_thr_event_u4().bit(), #[cfg(esp32)] - Number::Unit5 => pcnt.int_st.read().cnt_thr_event_u5_int_st().bit(), + Number::Unit5 => pcnt.int_st.read().cnt_thr_event_u5().bit(), #[cfg(esp32)] - Number::Unit6 => pcnt.int_st.read().cnt_thr_event_u6_int_st().bit(), + Number::Unit6 => pcnt.int_st.read().cnt_thr_event_u6().bit(), #[cfg(esp32)] - Number::Unit7 => pcnt.int_st.read().cnt_thr_event_u7_int_st().bit(), + Number::Unit7 => pcnt.int_st.read().cnt_thr_event_u7().bit(), } } pub fn reset_interrupt(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; pcnt.int_clr.write(|w| match self.number { - Number::Unit0 => w.cnt_thr_event_u0_int_clr().set_bit(), - Number::Unit1 => w.cnt_thr_event_u1_int_clr().set_bit(), - Number::Unit2 => w.cnt_thr_event_u2_int_clr().set_bit(), - Number::Unit3 => w.cnt_thr_event_u3_int_clr().set_bit(), + Number::Unit0 => w.cnt_thr_event_u0().set_bit(), + Number::Unit1 => w.cnt_thr_event_u1().set_bit(), + Number::Unit2 => w.cnt_thr_event_u2().set_bit(), + Number::Unit3 => w.cnt_thr_event_u3().set_bit(), #[cfg(esp32)] - Number::Unit4 => w.cnt_thr_event_u4_int_clr().set_bit(), + Number::Unit4 => w.cnt_thr_event_u4().set_bit(), #[cfg(esp32)] - Number::Unit5 => w.cnt_thr_event_u5_int_clr().set_bit(), + Number::Unit5 => w.cnt_thr_event_u5().set_bit(), #[cfg(esp32)] - Number::Unit6 => w.cnt_thr_event_u6_int_clr().set_bit(), + Number::Unit6 => w.cnt_thr_event_u6().set_bit(), #[cfg(esp32)] - Number::Unit7 => w.cnt_thr_event_u7_int_clr().set_bit(), + Number::Unit7 => w.cnt_thr_event_u7().set_bit(), }); } pub fn get_value(&self) -> i16 { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - pcnt.u_cnt[self.number as usize].read().pulse_cnt_u().bits() as i16 + pcnt.u_cnt[self.number as usize].read().cnt().bits() as i16 } } From c733a0142a840a9f75c28a903e8c12a8a157b9b1 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Fri, 6 Jan 2023 14:37:08 -0800 Subject: [PATCH 06/16] implement events/get_events (choosing what events interrupt) --- esp-hal-common/src/pcnt/channel.rs | 87 ++++++++--------- esp-hal-common/src/pcnt/mod.rs | 11 ++- esp-hal-common/src/pcnt/unit.rs | 145 ++++++++++++++++++++++++----- 3 files changed, 168 insertions(+), 75 deletions(-) diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index a0535aaf89a..35871f674f9 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -1,12 +1,13 @@ +use super::unit; use crate::{ - gpio::{types::InputSignal, InputPin}, - peripheral::{PeripheralRef, Peripheral}, + gpio::{ + types::{InputSignal, ONE_INPUT, ZERO_INPUT}, + InputPin, + }, + peripheral::{Peripheral, PeripheralRef}, peripherals::GPIO, }; -use super::unit; - - /// Channel number #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum Number { @@ -18,7 +19,7 @@ pub enum Number { #[derive(Debug, Copy, Clone, Default)] pub enum EdgeMode { /// Hold current count value - Hold = 0, + Hold = 0, /// Increase count value #[default] Increment = 1, @@ -30,7 +31,7 @@ pub enum EdgeMode { #[derive(Debug, Copy, Clone, Default)] pub enum CtrlMode { /// Keep current count mode - Keep = 0, + Keep = 0, /// Invert current count mode (increase -> decrease, decrease -> increase) #[default] Reverse = 1, @@ -50,7 +51,7 @@ pub struct Config { /// PCNT signal negative edge count mode pub neg_edge: EdgeMode, pub invert_ctrl: bool, - pub invert_sig: bool + pub invert_sig: bool, } /// PcntPin can be always high, always low, or an actual pin @@ -70,11 +71,9 @@ impl<'a, P: InputPin> PcntPin<'a, P> { impl<'a, P: InputPin> From> for u8 { fn from(pin: PcntPin<'a, P>) -> Self { match pin { - PcntPin::Pin(pin) => { - pin.number() - } - PcntPin::High => 0x38u8, - PcntPin::Low => 0x3cu8, + PcntPin::Pin(pin) => pin.number(), + PcntPin::High => ONE_INPUT, + PcntPin::Low => ZERO_INPUT, } } } @@ -85,22 +84,17 @@ pub struct Channel { } impl Channel { - /// return a new Unit - pub fn new( - unit: unit::Number, - channel: Number, - ) -> Self { - Self { - unit, - channel, - } + /// return a new Channel + pub fn new(unit: unit::Number, channel: Number) -> Self { + Self { unit, channel } } + /// Configure the channel pub fn configure<'b, CP: InputPin, EP: InputPin>( &mut self, ctrl_pin: PcntPin<'b, CP>, sig_pin: PcntPin<'b, EP>, - config: Config + config: Config, ) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; let conf0 = match self.unit { @@ -120,31 +114,36 @@ impl Channel { match self.channel { Number::Channel0 => { conf0.modify(|_, w| unsafe { - w.ch0_hctrl_mode().bits(config.hctrl_mode as u8) - .ch0_lctrl_mode().bits(config.lctrl_mode as u8) - .ch0_neg_mode().bits(config.neg_edge as u8) - .ch0_pos_mode().bits(config.pos_edge as u8) + w.ch0_hctrl_mode() + .bits(config.hctrl_mode as u8) + .ch0_lctrl_mode() + .bits(config.lctrl_mode as u8) + .ch0_neg_mode() + .bits(config.neg_edge as u8) + .ch0_pos_mode() + .bits(config.pos_edge as u8) }); - }, + } Number::Channel1 => { conf0.modify(|_, w| unsafe { - w.ch1_hctrl_mode().bits(config.hctrl_mode as u8) - .ch1_lctrl_mode().bits(config.lctrl_mode as u8) - .ch1_neg_mode().bits(config.neg_edge as u8) - .ch1_pos_mode().bits(config.pos_edge as u8) + w.ch1_hctrl_mode() + .bits(config.hctrl_mode as u8) + .ch1_lctrl_mode() + .bits(config.lctrl_mode as u8) + .ch1_neg_mode() + .bits(config.neg_edge as u8) + .ch1_pos_mode() + .bits(config.pos_edge as u8) }); - }, + } } self.set_ctrl_pin(ctrl_pin, config.invert_ctrl); self.set_sig_pin(sig_pin, config.invert_sig); } - pub fn set_ctrl_pin<'b, P: InputPin>( - &self, - pin: PcntPin<'b, P>, - invert: bool, - ) -> &Self { - let signal = match self.unit { + /// Set the control pin for this channel + pub fn set_ctrl_pin<'b, P: InputPin>(&self, pin: PcntPin<'b, P>, invert: bool) -> &Self { + let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_CTRL_CH0, Number::Channel1 => InputSignal::PCNT0_CTRL_CH1, @@ -197,12 +196,8 @@ impl Channel { self } - pub fn set_sig_pin<'b, P: InputPin>( - &self, - pin: PcntPin<'b, P>, - invert: bool, - ) -> &Self { - let signal = match self.unit { + pub fn set_sig_pin<'b, P: InputPin>(&self, pin: PcntPin<'b, P>, invert: bool) -> &Self { + let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_SIG_CH0, Number::Channel1 => InputSignal::PCNT0_SIG_CH1, @@ -254,6 +249,4 @@ impl Channel { } self } - - } diff --git a/esp-hal-common/src/pcnt/mod.rs b/esp-hal-common/src/pcnt/mod.rs index 21785c1dfd3..28d27cffe43 100644 --- a/esp-hal-common/src/pcnt/mod.rs +++ b/esp-hal-common/src/pcnt/mod.rs @@ -1,8 +1,11 @@ use self::unit::Unit; -use crate::{peripheral::{PeripheralRef, Peripheral}, system::PeripheralClockControl}; +use crate::{ + peripheral::{Peripheral, PeripheralRef}, + system::PeripheralClockControl, +}; -pub mod unit; pub mod channel; +pub mod unit; pub struct PCNT<'d> { _instance: PeripheralRef<'d, crate::peripherals::PCNT>, @@ -17,9 +20,7 @@ impl<'d> PCNT<'d> { crate::into_ref!(_instance); // Enable the PCNT peripherals clock in the system peripheral peripheral_clock_control.enable(crate::system::Peripheral::Pcnt); - PCNT { - _instance, - } + PCNT { _instance } } /// Return a unit diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index ab7f164baca..7a9d2f48975 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -1,4 +1,3 @@ - use super::channel; /// Unit number @@ -18,11 +17,49 @@ pub enum Number { Unit7, } +/// the current status of the counter. +#[derive(Copy, Clone, Debug, Default)] +pub enum ZeroMode { + /// pulse counter decreases from positive to 0. + #[default] + PosZero = 0, + /// pulse counter increases from negative to 0 + NegZero = 1, + /// pulse counter is negative (not implemented?) + Negitive = 2, + /// pulse counter is positive (not implemented?) + Positive = 3, +} + +impl From for ZeroMode { + fn from(value: u8) -> Self { + match value { + 0 => Self::PosZero, + 1 => Self::NegZero, + 2 => Self::Negitive, + 3 => Self::Positive, + _ => unreachable!(), // TODO: is this good enoough? should we use some default? + } + } +} + +// Events +#[derive(Copy, Clone, Debug, Default)] +pub struct Events { + pub low_limit: bool, + pub high_limit: bool, + pub thresh0: bool, + pub thresh1: bool, + pub zero: bool, +} + /// Unit configuration #[derive(Copy, Clone, Default)] pub struct Config { pub low_limit: i16, pub high_limit: i16, + pub thresh0: i16, + pub thresh1: i16, pub filter: Option, } @@ -33,37 +70,41 @@ pub struct Unit { impl Unit { /// return a new Unit pub(super) fn new(number: Number) -> Self { - Self { - number, - } + Self { number } } pub fn configure(&mut self, config: Config) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - let (conf0, conf2) = match self.number { - Number::Unit0 => (&pcnt.u0_conf0, &pcnt.u0_conf2), - Number::Unit1 => (&pcnt.u1_conf0, &pcnt.u1_conf2), - Number::Unit2 => (&pcnt.u2_conf0, &pcnt.u2_conf2), - Number::Unit3 => (&pcnt.u3_conf0, &pcnt.u3_conf2), + let (conf0, conf1, conf2) = match self.number { + Number::Unit0 => (&pcnt.u0_conf0, &pcnt.u0_conf1, &pcnt.u0_conf2), + Number::Unit1 => (&pcnt.u1_conf0, &pcnt.u1_conf1, &pcnt.u1_conf2), + Number::Unit2 => (&pcnt.u2_conf0, &pcnt.u2_conf1, &pcnt.u2_conf2), + Number::Unit3 => (&pcnt.u3_conf0, &pcnt.u3_conf1, &pcnt.u3_conf2), #[cfg(esp32)] - Number::Unit4 => (&pcnt.u4_conf0, &pcnt.u4_conf2), + Number::Unit4 => (&pcnt.u4_conf0, &pcnt.u4_conf1, &pcnt.u4_conf2), #[cfg(esp32)] - Number::Unit5 => (&pcnt.u5_conf0, &pcnt.u5_conf2), + Number::Unit5 => (&pcnt.u5_conf0, &pcnt.u5_conf1, &pcnt.u5_conf2), #[cfg(esp32)] - Number::Unit6 => (&pcnt.u6_conf0, &pcnt.u6_conf2), + Number::Unit6 => (&pcnt.u6_conf0, &pcnt.u6_conf1, &pcnt.u6_conf2), #[cfg(esp32)] - Number::Unit7 => (&pcnt.u7_conf0, &pcnt.u7_conf2), + Number::Unit7 => (&pcnt.u7_conf0, &pcnt.u7_conf1, &pcnt.u7_conf2), }; + // TODO: needs range checking low must be < 0 and high > 0! conf2.write(|w| unsafe { - w.cnt_l_lim().bits(config.low_limit as u16) - .cnt_h_lim().bits(config.high_limit as u16) + w.cnt_l_lim() + .bits(config.low_limit as u16) + .cnt_h_lim() + .bits(config.high_limit as u16) + }); + conf1.write(|w| unsafe { + w.cnt_thres0() + .bits(config.thresh0 as u16) + .cnt_thres1() + .bits(config.thresh1 as u16) }); if let Some(filter) = config.filter { - // TODO: needs range checking mac is 1023! - conf0.modify(|_, w| unsafe { - w.filter_thres().bits(filter) - .filter_en().set_bit() - }); + // TODO: needs range checking max is 1023! + conf0.modify(|_, w| unsafe { w.filter_thres().bits(filter).filter_en().set_bit() }); } else { conf0.modify(|_, w| w.filter_en().clear_bit()); } @@ -105,9 +146,10 @@ impl Unit { Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u6().clear_bit()), #[cfg(esp32)] Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u7().clear_bit()), - } + } } + /// Pause the counter pub fn pause(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { @@ -123,9 +165,10 @@ impl Unit { Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), #[cfg(esp32)] Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), - } + } } + /// Resume the counter pub fn resume(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { @@ -144,9 +187,61 @@ impl Unit { } } + /// Enable which events generate interrupts on this unit. + pub fn events(&self, events: Events) { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + let conf0 = match self.number { + Number::Unit0 => &pcnt.u0_conf0, + Number::Unit1 => &pcnt.u1_conf0, + Number::Unit2 => &pcnt.u2_conf0, + Number::Unit3 => &pcnt.u3_conf0, + #[cfg(esp32)] + Number::Unit4 => &pcnt.u4_conf0, + #[cfg(esp32)] + Number::Unit5 => &pcnt.u5_conf0, + #[cfg(esp32)] + Number::Unit6 => &pcnt.u6_conf0, + #[cfg(esp32)] + Number::Unit7 => &pcnt.u7_conf0, + }; + conf0.modify(|_, w| { + w.thr_l_lim_en() + .bit(events.low_limit) + .thr_h_lim_en() + .bit(events.high_limit) + .thr_thres0_en() + .bit(events.thresh0) + .thr_thres1_en() + .bit(events.thresh1) + .thr_zero_en() + .bit(events.zero) + }); + } + + /// Get the latest events for this unit. + pub fn get_events(&self) -> Events { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + let status = pcnt.u_status[self.number as usize].read(); + + Events { + low_limit: status.l_lim().bit(), + high_limit: status.h_lim().bit(), + thresh0: status.thres0().bit(), + thresh1: status.thres1().bit(), + zero: status.zero().bit(), + } + } + + /// Get the mode of the last zero crossing + pub fn get_zero_mode(&self) -> ZeroMode { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + pcnt.u_status[self.number as usize].read().zero_mode().bits().into() + } + + /// Enable interrupts for this unit. pub fn listen(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - pcnt.int_ena.write(|w| match self.number { + pcnt.int_ena.modify(|_, w| match self.number { Number::Unit0 => w.cnt_thr_event_u0().set_bit(), Number::Unit1 => w.cnt_thr_event_u1().set_bit(), Number::Unit2 => w.cnt_thr_event_u2().set_bit(), @@ -162,6 +257,7 @@ impl Unit { }); } + /// Disable interrupts for this unit. pub fn unlisten(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; pcnt.int_ena.write(|w| match self.number { @@ -180,6 +276,7 @@ impl Unit { }); } + /// Returns true if an interrupt is active for this unit. pub fn interrupt_set(&self) -> bool { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; match self.number { @@ -198,6 +295,7 @@ impl Unit { } } + /// Clear the interrupt bit for this unit. pub fn reset_interrupt(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; pcnt.int_clr.write(|w| match self.number { @@ -216,6 +314,7 @@ impl Unit { }); } + /// Get the current counter value. pub fn get_value(&self) -> i16 { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; pcnt.u_cnt[self.number as usize].read().cnt().bits() as i16 From 7b7d2edebd989a2d98ec3da17fefaa32d78c7205 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Sat, 7 Jan 2023 11:45:16 -0800 Subject: [PATCH 07/16] added pcnt example: simple encoder configuration --- esp32-hal/examples/pcnt-encoder.rs | 136 +++++++++++++++++++++++++++ esp32s2-hal/examples/pcnt-encoder.rs | 136 +++++++++++++++++++++++++++ esp32s3-hal/examples/pcnt-encoder.rs | 136 +++++++++++++++++++++++++++ 3 files changed, 408 insertions(+) create mode 100644 esp32-hal/examples/pcnt-encoder.rs create mode 100644 esp32s2-hal/examples/pcnt-encoder.rs create mode 100644 esp32s3-hal/examples/pcnt-encoder.rs diff --git a/esp32-hal/examples/pcnt-encoder.rs b/esp32-hal/examples/pcnt-encoder.rs new file mode 100644 index 00000000000..2568794c44c --- /dev/null +++ b/esp32-hal/examples/pcnt-encoder.rs @@ -0,0 +1,136 @@ +//! PCNT Encoder Demo +//! +//! This example decodes a quadrature encoder +//! +//! Since the PCNT units reset to zero when they reach their limits +//! we use enable an interrupt on the upper and lower limits and +//! track the overflow in an AtomicI32 + +#![no_std] +#![no_main] +use core::{cmp::min, cell::RefCell, sync::atomic::{AtomicI32, Ordering}}; +use critical_section::Mutex; + +use esp32_hal as esp_hal; + +use esp_hal::{ + clock::ClockControl, + peripherals::{Peripherals, self}, + prelude::*, + timer::TimerGroup, + Rtc, + IO, + pcnt::{PCNT, unit, channel, channel::PcntPin}, + interrupt, +}; +use esp_backtrace as _; +use esp_println::println; +use xtensa_lx_rt::entry; + +static UNIT0: Mutex>> = Mutex::new(RefCell::new(None)); +static VALUE: AtomicI32 = AtomicI32::new(0); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.DPORT.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt = timer_group0.wdt; + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + wdt.disable(); + rtc.rwdt.disable(); + + let unit_number = unit::Number::Unit1; + + // setup a pulse couter + println!("setup pulse counter unit 0"); + let pcnt = PCNT::new(peripherals.PCNT, &mut system.peripheral_clock_control); + let mut u0 = pcnt.get_unit(unit_number); + u0.configure(unit::Config { + low_limit: -100, + high_limit: 100, + filter: Some(min(10u16 * 80, 1023u16)), + ..Default::default() + }); + + println!("setup channel 0"); + let mut ch0 = u0.get_channel(channel::Number::Channel0); + let mut pin_a = io.pins.gpio22.into_pull_up_input(); + let mut pin_b = io.pins.gpio23.into_pull_up_input(); + + ch0.configure(PcntPin::from_pin(&mut pin_a), PcntPin::from_pin(&mut pin_b), channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Decrement, + neg_edge: channel::EdgeMode::Increment, + invert_ctrl: false, + invert_sig: false, + }); + + println!("setup channel 1"); + let mut ch1 = u0.get_channel(channel::Number::Channel1); + ch1.configure(PcntPin::from_pin(&mut pin_b), PcntPin::from_pin(&mut pin_a), channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Increment, + neg_edge: channel::EdgeMode::Decrement, + invert_ctrl: false, + invert_sig: false, + }); + println!("subscribing to events"); + u0.events(unit::Events { + low_limit: true, + high_limit: true, + thresh0: false, + thresh1: false, + zero: false, + }); + + println!("enabling interrupts"); + u0.listen(); + println!("resume pulse counter unit 0"); + u0.resume(); + + critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0)); + + interrupt::enable( + peripherals::Interrupt::PCNT, + interrupt::Priority::Priority2, + ) + .unwrap(); + + let mut last_value: i32 = 0; + loop { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + let value: i32 = u0.get_value()as i32 + VALUE.load(Ordering::SeqCst); + if value != last_value { + println!("value: {value}"); + last_value = value; + } + }); + } +} + +#[interrupt] +fn PCNT() { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + if u0.interrupt_set() { + let events = u0.get_events(); + if events.high_limit { + VALUE.fetch_add(100, Ordering::SeqCst); + } else if events.low_limit { + VALUE.fetch_add(-100, Ordering::SeqCst); + } + u0.reset_interrupt(); + } + }); +} diff --git a/esp32s2-hal/examples/pcnt-encoder.rs b/esp32s2-hal/examples/pcnt-encoder.rs new file mode 100644 index 00000000000..081f07eadd5 --- /dev/null +++ b/esp32s2-hal/examples/pcnt-encoder.rs @@ -0,0 +1,136 @@ +//! PCNT Encoder Demo +//! +//! This example decodes a quadrature encoder +//! +//! Since the PCNT units reset to zero when they reach their limits +//! we use enable an interrupt on the upper and lower limits and +//! track the overflow in an AtomicI32 + +#![no_std] +#![no_main] +use core::{cmp::min, cell::RefCell, sync::atomic::{AtomicI32, Ordering}}; +use critical_section::Mutex; + +use esp32s2_hal as esp_hal; + +use esp_hal::{ + clock::ClockControl, + peripherals::{Peripherals, self}, + prelude::*, + timer::TimerGroup, + Rtc, + IO, + pcnt::{PCNT, unit, channel, channel::PcntPin}, + interrupt, +}; +use esp_backtrace as _; +use esp_println::println; +use xtensa_lx_rt::entry; + +static UNIT0: Mutex>> = Mutex::new(RefCell::new(None)); +static VALUE: AtomicI32 = AtomicI32::new(0); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt = timer_group0.wdt; + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + wdt.disable(); + rtc.rwdt.disable(); + + let unit_number = unit::Number::Unit1; + + // setup a pulse couter + println!("setup pulse counter unit 0"); + let pcnt = PCNT::new(peripherals.PCNT, &mut system.peripheral_clock_control); + let mut u0 = pcnt.get_unit(unit_number); + u0.configure(unit::Config { + low_limit: -100, + high_limit: 100, + filter: Some(min(10u16 * 80, 1023u16)), + ..Default::default() + }); + + println!("setup channel 0"); + let mut ch0 = u0.get_channel(channel::Number::Channel0); + let mut pin_a = io.pins.gpio5.into_pull_up_input(); + let mut pin_b = io.pins.gpio6.into_pull_up_input(); + + ch0.configure(PcntPin::from_pin(&mut pin_a), PcntPin::from_pin(&mut pin_b), channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Decrement, + neg_edge: channel::EdgeMode::Increment, + invert_ctrl: false, + invert_sig: false, + }); + + println!("setup channel 1"); + let mut ch1 = u0.get_channel(channel::Number::Channel1); + ch1.configure(PcntPin::from_pin(&mut pin_b), PcntPin::from_pin(&mut pin_a), channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Increment, + neg_edge: channel::EdgeMode::Decrement, + invert_ctrl: false, + invert_sig: false, + }); + println!("subscribing to events"); + u0.events(unit::Events { + low_limit: true, + high_limit: true, + thresh0: false, + thresh1: false, + zero: false, + }); + + println!("enabling interrupts"); + u0.listen(); + println!("resume pulse counter unit 0"); + u0.resume(); + + critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0)); + + interrupt::enable( + peripherals::Interrupt::PCNT, + interrupt::Priority::Priority2, + ) + .unwrap(); + + let mut last_value: i32 = 0; + loop { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + let value: i32 = u0.get_value()as i32 + VALUE.load(Ordering::SeqCst); + if value != last_value { + println!("value: {value}"); + last_value = value; + } + }); + } +} + +#[interrupt] +fn PCNT() { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + if u0.interrupt_set() { + let events = u0.get_events(); + if events.high_limit { + VALUE.store(VALUE.load(Ordering::SeqCst) + 100, Ordering::SeqCst); + } else if events.low_limit { + VALUE.store(VALUE.load(Ordering::SeqCst) - 100, Ordering::SeqCst); + } + u0.reset_interrupt(); + } + }); +} diff --git a/esp32s3-hal/examples/pcnt-encoder.rs b/esp32s3-hal/examples/pcnt-encoder.rs new file mode 100644 index 00000000000..2f82a217e12 --- /dev/null +++ b/esp32s3-hal/examples/pcnt-encoder.rs @@ -0,0 +1,136 @@ +//! PCNT Encoder Demo +//! +//! This example decodes a quadrature encoder +//! +//! Since the PCNT units reset to zero when they reach their limits +//! we use enable an interrupt on the upper and lower limits and +//! track the overflow in an AtomicI32 + +#![no_std] +#![no_main] +use core::{cmp::min, cell::RefCell, sync::atomic::AtomicI32, sync::atomic::Ordering}; +use critical_section::Mutex; + +use esp32s3_hal as esp_hal; + +use esp_hal::{ + clock::ClockControl, + peripherals::{Peripherals, self}, + prelude::*, + timer::TimerGroup, + Rtc, + IO, + pcnt::{PCNT, unit, channel, channel::PcntPin}, + interrupt, +}; +use esp_backtrace as _; +use esp_println::println; +use xtensa_lx_rt::entry; + +static UNIT0: Mutex>> = Mutex::new(RefCell::new(None)); +static VALUE: AtomicI32 = AtomicI32::new(0); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt = timer_group0.wdt; + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + wdt.disable(); + rtc.rwdt.disable(); + + let unit_number = unit::Number::Unit1; + + // setup a pulse couter + println!("setup pulse counter unit 0"); + let pcnt = PCNT::new(peripherals.PCNT, &mut system.peripheral_clock_control); + let mut u0 = pcnt.get_unit(unit_number); + u0.configure(unit::Config { + low_limit: -100, + high_limit: 100, + filter: Some(min(10u16 * 80, 1023u16)), + ..Default::default() + }); + + println!("setup channel 0"); + let mut ch0 = u0.get_channel(channel::Number::Channel0); + let mut pin_a = io.pins.gpio5.into_pull_up_input(); + let mut pin_b = io.pins.gpio6.into_pull_up_input(); + + ch0.configure(PcntPin::from_pin(&mut pin_a), PcntPin::from_pin(&mut pin_b), channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Decrement, + neg_edge: channel::EdgeMode::Increment, + invert_ctrl: false, + invert_sig: false, + }); + + println!("setup channel 1"); + let mut ch1 = u0.get_channel(channel::Number::Channel1); + ch1.configure(PcntPin::from_pin(&mut pin_b), PcntPin::from_pin(&mut pin_a), channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Increment, + neg_edge: channel::EdgeMode::Decrement, + invert_ctrl: false, + invert_sig: false, + }); + println!("subscribing to events"); + u0.events(unit::Events { + low_limit: true, + high_limit: true, + thresh0: false, + thresh1: false, + zero: false, + }); + + println!("enabling interrupts"); + u0.listen(); + println!("resume pulse counter unit 0"); + u0.resume(); + + critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0)); + + interrupt::enable( + peripherals::Interrupt::PCNT, + interrupt::Priority::Priority2, + ) + .unwrap(); + + let mut last_value: i32 = 0; + loop { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + let value: i32 = u0.get_value()as i32 + VALUE.load(Ordering::SeqCst); + if value != last_value { + println!("value: {value}"); + last_value = value; + } + }); + } +} + +#[interrupt] +fn PCNT() { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + if u0.interrupt_set() { + let events = u0.get_events(); + if events.high_limit { + VALUE.fetch_add(100, Ordering::SeqCst); + } else if events.low_limit { + VALUE.fetch_add(-100, Ordering::SeqCst); + } + u0.reset_interrupt(); + } + }); +} From 9c1d9a18e956373c233a84be50890e1d77d5e295 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Sat, 7 Jan 2023 11:54:01 -0800 Subject: [PATCH 08/16] restrict pcnt::channel::Channel::new() to super --- esp-hal-common/src/pcnt/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index 35871f674f9..238fb037961 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -85,7 +85,7 @@ pub struct Channel { impl Channel { /// return a new Channel - pub fn new(unit: unit::Number, channel: Number) -> Self { + pub(super) fn new(unit: unit::Number, channel: Number) -> Self { Self { unit, channel } } From 6146b9a272d4f70bfd815057cec413d68cf90be5 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Sun, 8 Jan 2023 11:18:22 -0800 Subject: [PATCH 09/16] PcntPin -> PcntSignal added range checks for thresholds and limits --- esp-hal-common/src/pcnt/channel.rs | 35 +++++++------- esp-hal-common/src/pcnt/unit.rs | 70 ++++++++++++++++++++++++---- esp32-hal/examples/pcnt-encoder.rs | 69 +++++++++++++++------------ esp32s2-hal/examples/pcnt-encoder.rs | 69 +++++++++++++++------------ esp32s3-hal/examples/pcnt-encoder.rs | 67 ++++++++++++++------------ 5 files changed, 193 insertions(+), 117 deletions(-) diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index 238fb037961..b1d3009a39b 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -55,25 +55,25 @@ pub struct Config { } /// PcntPin can be always high, always low, or an actual pin -pub enum PcntPin<'a, P: InputPin> { +pub enum PcntSignal<'a, P: InputPin> { Pin(PeripheralRef<'a, P>), High, Low, } -impl<'a, P: InputPin> PcntPin<'a, P> { +impl<'a, P: InputPin> PcntSignal<'a, P> { pub fn from_pin(pin: impl Peripheral

+ 'a) -> Self { crate::into_ref!(pin); - PcntPin::Pin(pin) + PcntSignal::Pin(pin) } } -impl<'a, P: InputPin> From> for u8 { - fn from(pin: PcntPin<'a, P>) -> Self { +impl<'a, P: InputPin> From> for u8 { + fn from(pin: PcntSignal<'a, P>) -> Self { match pin { - PcntPin::Pin(pin) => pin.number(), - PcntPin::High => ONE_INPUT, - PcntPin::Low => ZERO_INPUT, + PcntSignal::Pin(pin) => pin.number(), + PcntSignal::High => ONE_INPUT, + PcntSignal::Low => ZERO_INPUT, } } } @@ -92,8 +92,8 @@ impl Channel { /// Configure the channel pub fn configure<'b, CP: InputPin, EP: InputPin>( &mut self, - ctrl_pin: PcntPin<'b, CP>, - sig_pin: PcntPin<'b, EP>, + ctrl_signal: PcntSignal<'b, CP>, + edge_signal: PcntSignal<'b, EP>, config: Config, ) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; @@ -137,12 +137,12 @@ impl Channel { }); } } - self.set_ctrl_pin(ctrl_pin, config.invert_ctrl); - self.set_sig_pin(sig_pin, config.invert_sig); + self.set_ctrl_signal(ctrl_signal, config.invert_ctrl); + self.set_edge_signal(edge_signal, config.invert_sig); } - /// Set the control pin for this channel - pub fn set_ctrl_pin<'b, P: InputPin>(&self, pin: PcntPin<'b, P>, invert: bool) -> &Self { + /// Set the control signal (pin/high/low) for this channel + pub fn set_ctrl_signal<'b, P: InputPin>(&self, source: PcntSignal<'b, P>, invert: bool) -> &Self { let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_CTRL_CH0, @@ -181,7 +181,7 @@ impl Channel { Number::Channel1 => InputSignal::PCNT7_CTRL_CH1, }, }; - let pin_num: u8 = pin.into(); + let pin_num: u8 = source.into(); if (signal as usize) <= crate::types::INPUT_SIGNAL_MAX as usize { unsafe { &*GPIO::PTR }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { @@ -196,7 +196,8 @@ impl Channel { self } - pub fn set_sig_pin<'b, P: InputPin>(&self, pin: PcntPin<'b, P>, invert: bool) -> &Self { + /// Set the edge signal (pin/high/low) for this channel + pub fn set_edge_signal<'b, P: InputPin>(&self, source: PcntSignal<'b, P>, invert: bool) -> &Self { let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_SIG_CH0, @@ -235,7 +236,7 @@ impl Channel { Number::Channel1 => InputSignal::PCNT7_SIG_CH1, }, }; - let pin_num: u8 = pin.into(); + let pin_num: u8 = source.into(); if (signal as usize) <= crate::types::INPUT_SIGNAL_MAX as usize { unsafe { &*GPIO::PTR }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index 7a9d2f48975..474be2483d6 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -17,6 +17,17 @@ pub enum Number { Unit7, } +/// Unit errors +#[derive(Debug)] +pub enum Error { + /// Invalid filter threshold value + InvalidFilterThresh, + /// Invalid low limit - must be < 0 + InvalidLowLimit, + /// Invalid high limit - must be > 0 + InvalidHighLimit, +} + /// the current status of the counter. #[derive(Copy, Clone, Debug, Default)] pub enum ZeroMode { @@ -70,10 +81,58 @@ pub struct Unit { impl Unit { /// return a new Unit pub(super) fn new(number: Number) -> Self { + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; + let conf0 = match number { + Number::Unit0 => &pcnt.u0_conf0, + Number::Unit1 => &pcnt.u1_conf0, + Number::Unit2 => &pcnt.u2_conf0, + Number::Unit3 => &pcnt.u3_conf0, + #[cfg(esp32)] + Number::Unit4 => &pcnt.u4_conf0, + #[cfg(esp32)] + Number::Unit5 => &pcnt.u5_conf0, + #[cfg(esp32)] + Number::Unit6 => &pcnt.u6_conf0, + #[cfg(esp32)] + Number::Unit7 => &pcnt.u7_conf0, + }; + // disable filter and all events + conf0.modify(|_, w| unsafe { + w.filter_en().clear_bit() + .filter_thres().bits(0) + .thr_l_lim_en() + .clear_bit() + .thr_h_lim_en() + .clear_bit() + .thr_thres0_en() + .clear_bit() + .thr_thres1_en() + .clear_bit() + .thr_zero_en() + .clear_bit() + } ); Self { number } } - pub fn configure(&mut self, config: Config) { + pub fn configure(&mut self, config: Config) -> Result<(), Error> { + // low limit must be >= or the limit is -32768 and when thats + // hit the event status claims it was the high limit. + // tested on an esp32s3 + if config.low_limit >= 0 { + return Err(Error::InvalidLowLimit); + } + if config.high_limit <= 0 { + return Err(Error::InvalidHighLimit); + } + let (filter_en, filter) = match config.filter { + Some(filter) => (true, filter), + None => (false, 0) + }; + // filter must be less than 1024 + if filter > 1023 { + return Err(Error::InvalidFilterThresh) + } + let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; let (conf0, conf1, conf2) = match self.number { Number::Unit0 => (&pcnt.u0_conf0, &pcnt.u0_conf1, &pcnt.u0_conf2), @@ -89,7 +148,6 @@ impl Unit { #[cfg(esp32)] Number::Unit7 => (&pcnt.u7_conf0, &pcnt.u7_conf1, &pcnt.u7_conf2), }; - // TODO: needs range checking low must be < 0 and high > 0! conf2.write(|w| unsafe { w.cnt_l_lim() .bits(config.low_limit as u16) @@ -102,14 +160,10 @@ impl Unit { .cnt_thres1() .bits(config.thresh1 as u16) }); - if let Some(filter) = config.filter { - // TODO: needs range checking max is 1023! - conf0.modify(|_, w| unsafe { w.filter_thres().bits(filter).filter_en().set_bit() }); - } else { - conf0.modify(|_, w| w.filter_en().clear_bit()); - } + conf0.modify(|_, w| unsafe { w.filter_thres().bits(filter).filter_en().bit(filter_en) }); self.pause(); self.clear(); + Ok(()) } pub fn get_channel(&self, number: channel::Number) -> super::channel::Channel { diff --git a/esp32-hal/examples/pcnt-encoder.rs b/esp32-hal/examples/pcnt-encoder.rs index 2568794c44c..0c35abf7574 100644 --- a/esp32-hal/examples/pcnt-encoder.rs +++ b/esp32-hal/examples/pcnt-encoder.rs @@ -1,34 +1,37 @@ //! PCNT Encoder Demo //! //! This example decodes a quadrature encoder -//! +//! //! Since the PCNT units reset to zero when they reach their limits //! we use enable an interrupt on the upper and lower limits and //! track the overflow in an AtomicI32 #![no_std] #![no_main] -use core::{cmp::min, cell::RefCell, sync::atomic::{AtomicI32, Ordering}}; -use critical_section::Mutex; +use core::{ + cell::RefCell, + cmp::min, + sync::atomic::{AtomicI32, Ordering}, +}; +use critical_section::Mutex; use esp32_hal as esp_hal; - +use esp_backtrace as _; use esp_hal::{ clock::ClockControl, - peripherals::{Peripherals, self}, + interrupt, + pcnt::{channel, channel::PcntSignal, unit, PCNT}, + peripherals::{self, Peripherals}, prelude::*, timer::TimerGroup, Rtc, IO, - pcnt::{PCNT, unit, channel, channel::PcntPin}, - interrupt, }; -use esp_backtrace as _; use esp_println::println; use xtensa_lx_rt::entry; static UNIT0: Mutex>> = Mutex::new(RefCell::new(None)); -static VALUE: AtomicI32 = AtomicI32::new(0); +static VALUE: AtomicI32 = AtomicI32::new(0); #[entry] fn main() -> ! { @@ -63,25 +66,33 @@ fn main() -> ! { let mut pin_a = io.pins.gpio22.into_pull_up_input(); let mut pin_b = io.pins.gpio23.into_pull_up_input(); - ch0.configure(PcntPin::from_pin(&mut pin_a), PcntPin::from_pin(&mut pin_b), channel::Config { - lctrl_mode: channel::CtrlMode::Reverse, - hctrl_mode: channel::CtrlMode::Keep, - pos_edge: channel::EdgeMode::Decrement, - neg_edge: channel::EdgeMode::Increment, - invert_ctrl: false, - invert_sig: false, - }); + ch0.configure( + PcntSignal::from_pin(&mut pin_a), + PcntSignal::from_pin(&mut pin_b), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Decrement, + neg_edge: channel::EdgeMode::Increment, + invert_ctrl: false, + invert_sig: false, + }, + ); println!("setup channel 1"); let mut ch1 = u0.get_channel(channel::Number::Channel1); - ch1.configure(PcntPin::from_pin(&mut pin_b), PcntPin::from_pin(&mut pin_a), channel::Config { - lctrl_mode: channel::CtrlMode::Reverse, - hctrl_mode: channel::CtrlMode::Keep, - pos_edge: channel::EdgeMode::Increment, - neg_edge: channel::EdgeMode::Decrement, - invert_ctrl: false, - invert_sig: false, - }); + ch1.configure( + PcntSignal::from_pin(&mut pin_b), + PcntSignal::from_pin(&mut pin_a), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Increment, + neg_edge: channel::EdgeMode::Decrement, + invert_ctrl: false, + invert_sig: false, + }, + ); println!("subscribing to events"); u0.events(unit::Events { low_limit: true, @@ -98,18 +109,14 @@ fn main() -> ! { critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0)); - interrupt::enable( - peripherals::Interrupt::PCNT, - interrupt::Priority::Priority2, - ) - .unwrap(); + interrupt::enable(peripherals::Interrupt::PCNT, interrupt::Priority::Priority2).unwrap(); let mut last_value: i32 = 0; loop { critical_section::with(|cs| { let mut u0 = UNIT0.borrow_ref_mut(cs); let u0 = u0.as_mut().unwrap(); - let value: i32 = u0.get_value()as i32 + VALUE.load(Ordering::SeqCst); + let value: i32 = u0.get_value() as i32 + VALUE.load(Ordering::SeqCst); if value != last_value { println!("value: {value}"); last_value = value; diff --git a/esp32s2-hal/examples/pcnt-encoder.rs b/esp32s2-hal/examples/pcnt-encoder.rs index 081f07eadd5..54bef1729f9 100644 --- a/esp32s2-hal/examples/pcnt-encoder.rs +++ b/esp32s2-hal/examples/pcnt-encoder.rs @@ -1,34 +1,37 @@ //! PCNT Encoder Demo //! //! This example decodes a quadrature encoder -//! +//! //! Since the PCNT units reset to zero when they reach their limits //! we use enable an interrupt on the upper and lower limits and //! track the overflow in an AtomicI32 #![no_std] #![no_main] -use core::{cmp::min, cell::RefCell, sync::atomic::{AtomicI32, Ordering}}; -use critical_section::Mutex; +use core::{ + cell::RefCell, + cmp::min, + sync::atomic::{AtomicI32, Ordering}, +}; +use critical_section::Mutex; use esp32s2_hal as esp_hal; - +use esp_backtrace as _; use esp_hal::{ clock::ClockControl, - peripherals::{Peripherals, self}, + interrupt, + pcnt::{channel, channel::PcntSignal, unit, PCNT}, + peripherals::{self, Peripherals}, prelude::*, timer::TimerGroup, Rtc, IO, - pcnt::{PCNT, unit, channel, channel::PcntPin}, - interrupt, }; -use esp_backtrace as _; use esp_println::println; use xtensa_lx_rt::entry; static UNIT0: Mutex>> = Mutex::new(RefCell::new(None)); -static VALUE: AtomicI32 = AtomicI32::new(0); +static VALUE: AtomicI32 = AtomicI32::new(0); #[entry] fn main() -> ! { @@ -63,25 +66,33 @@ fn main() -> ! { let mut pin_a = io.pins.gpio5.into_pull_up_input(); let mut pin_b = io.pins.gpio6.into_pull_up_input(); - ch0.configure(PcntPin::from_pin(&mut pin_a), PcntPin::from_pin(&mut pin_b), channel::Config { - lctrl_mode: channel::CtrlMode::Reverse, - hctrl_mode: channel::CtrlMode::Keep, - pos_edge: channel::EdgeMode::Decrement, - neg_edge: channel::EdgeMode::Increment, - invert_ctrl: false, - invert_sig: false, - }); + ch0.configure( + PcntSignal::from_pin(&mut pin_a), + PcntSignal::from_pin(&mut pin_b), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Decrement, + neg_edge: channel::EdgeMode::Increment, + invert_ctrl: false, + invert_sig: false, + }, + ); println!("setup channel 1"); let mut ch1 = u0.get_channel(channel::Number::Channel1); - ch1.configure(PcntPin::from_pin(&mut pin_b), PcntPin::from_pin(&mut pin_a), channel::Config { - lctrl_mode: channel::CtrlMode::Reverse, - hctrl_mode: channel::CtrlMode::Keep, - pos_edge: channel::EdgeMode::Increment, - neg_edge: channel::EdgeMode::Decrement, - invert_ctrl: false, - invert_sig: false, - }); + ch1.configure( + PcntSignal::from_pin(&mut pin_b), + PcntSignal::from_pin(&mut pin_a), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Increment, + neg_edge: channel::EdgeMode::Decrement, + invert_ctrl: false, + invert_sig: false, + }, + ); println!("subscribing to events"); u0.events(unit::Events { low_limit: true, @@ -98,18 +109,14 @@ fn main() -> ! { critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0)); - interrupt::enable( - peripherals::Interrupt::PCNT, - interrupt::Priority::Priority2, - ) - .unwrap(); + interrupt::enable(peripherals::Interrupt::PCNT, interrupt::Priority::Priority2).unwrap(); let mut last_value: i32 = 0; loop { critical_section::with(|cs| { let mut u0 = UNIT0.borrow_ref_mut(cs); let u0 = u0.as_mut().unwrap(); - let value: i32 = u0.get_value()as i32 + VALUE.load(Ordering::SeqCst); + let value: i32 = u0.get_value() as i32 + VALUE.load(Ordering::SeqCst); if value != last_value { println!("value: {value}"); last_value = value; diff --git a/esp32s3-hal/examples/pcnt-encoder.rs b/esp32s3-hal/examples/pcnt-encoder.rs index 2f82a217e12..aba553b06f0 100644 --- a/esp32s3-hal/examples/pcnt-encoder.rs +++ b/esp32s3-hal/examples/pcnt-encoder.rs @@ -1,29 +1,32 @@ //! PCNT Encoder Demo //! //! This example decodes a quadrature encoder -//! +//! //! Since the PCNT units reset to zero when they reach their limits //! we use enable an interrupt on the upper and lower limits and //! track the overflow in an AtomicI32 #![no_std] #![no_main] -use core::{cmp::min, cell::RefCell, sync::atomic::AtomicI32, sync::atomic::Ordering}; -use critical_section::Mutex; +use core::{ + cell::RefCell, + cmp::min, + sync::atomic::{AtomicI32, Ordering}, +}; +use critical_section::Mutex; use esp32s3_hal as esp_hal; - +use esp_backtrace as _; use esp_hal::{ clock::ClockControl, - peripherals::{Peripherals, self}, + interrupt, + pcnt::{channel, channel::PcntSignal, unit, PCNT}, + peripherals::{self, Peripherals}, prelude::*, timer::TimerGroup, Rtc, IO, - pcnt::{PCNT, unit, channel, channel::PcntPin}, - interrupt, }; -use esp_backtrace as _; use esp_println::println; use xtensa_lx_rt::entry; @@ -63,25 +66,33 @@ fn main() -> ! { let mut pin_a = io.pins.gpio5.into_pull_up_input(); let mut pin_b = io.pins.gpio6.into_pull_up_input(); - ch0.configure(PcntPin::from_pin(&mut pin_a), PcntPin::from_pin(&mut pin_b), channel::Config { - lctrl_mode: channel::CtrlMode::Reverse, - hctrl_mode: channel::CtrlMode::Keep, - pos_edge: channel::EdgeMode::Decrement, - neg_edge: channel::EdgeMode::Increment, - invert_ctrl: false, - invert_sig: false, - }); + ch0.configure( + PcntSignal::from_pin(&mut pin_a), + PcntSignal::from_pin(&mut pin_b), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Decrement, + neg_edge: channel::EdgeMode::Increment, + invert_ctrl: false, + invert_sig: false, + }, + ); println!("setup channel 1"); let mut ch1 = u0.get_channel(channel::Number::Channel1); - ch1.configure(PcntPin::from_pin(&mut pin_b), PcntPin::from_pin(&mut pin_a), channel::Config { - lctrl_mode: channel::CtrlMode::Reverse, - hctrl_mode: channel::CtrlMode::Keep, - pos_edge: channel::EdgeMode::Increment, - neg_edge: channel::EdgeMode::Decrement, - invert_ctrl: false, - invert_sig: false, - }); + ch1.configure( + PcntSignal::from_pin(&mut pin_b), + PcntSignal::from_pin(&mut pin_a), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Increment, + neg_edge: channel::EdgeMode::Decrement, + invert_ctrl: false, + invert_sig: false, + }, + ); println!("subscribing to events"); u0.events(unit::Events { low_limit: true, @@ -98,18 +109,14 @@ fn main() -> ! { critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0)); - interrupt::enable( - peripherals::Interrupt::PCNT, - interrupt::Priority::Priority2, - ) - .unwrap(); + interrupt::enable(peripherals::Interrupt::PCNT, interrupt::Priority::Priority2).unwrap(); let mut last_value: i32 = 0; loop { critical_section::with(|cs| { let mut u0 = UNIT0.borrow_ref_mut(cs); let u0 = u0.as_mut().unwrap(); - let value: i32 = u0.get_value()as i32 + VALUE.load(Ordering::SeqCst); + let value: i32 = u0.get_value() as i32 + VALUE.load(Ordering::SeqCst); if value != last_value { println!("value: {value}"); last_value = value; From a2037f1584c0228ff710d4f0f608aba6f2f1bcc7 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Sun, 8 Jan 2023 11:24:07 -0800 Subject: [PATCH 10/16] PcntSource is a better name I think --- esp-hal-common/src/pcnt/channel.rs | 32 ++++++++++++------- .../{pcnt-encoder.rs => pcnt_encoder.rs} | 10 +++--- .../{pcnt-encoder.rs => pcnt_encoder.rs} | 10 +++--- .../{pcnt-encoder.rs => pcnt_encoder.rs} | 10 +++--- 4 files changed, 35 insertions(+), 27 deletions(-) rename esp32-hal/examples/{pcnt-encoder.rs => pcnt_encoder.rs} (94%) rename esp32s2-hal/examples/{pcnt-encoder.rs => pcnt_encoder.rs} (94%) rename esp32s3-hal/examples/{pcnt-encoder.rs => pcnt_encoder.rs} (94%) diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index b1d3009a39b..b9333d4083d 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -55,25 +55,25 @@ pub struct Config { } /// PcntPin can be always high, always low, or an actual pin -pub enum PcntSignal<'a, P: InputPin> { +pub enum PcntSource<'a, P: InputPin> { Pin(PeripheralRef<'a, P>), High, Low, } -impl<'a, P: InputPin> PcntSignal<'a, P> { +impl<'a, P: InputPin> PcntSource<'a, P> { pub fn from_pin(pin: impl Peripheral

+ 'a) -> Self { crate::into_ref!(pin); - PcntSignal::Pin(pin) + PcntSource::Pin(pin) } } -impl<'a, P: InputPin> From> for u8 { - fn from(pin: PcntSignal<'a, P>) -> Self { +impl<'a, P: InputPin> From> for u8 { + fn from(pin: PcntSource<'a, P>) -> Self { match pin { - PcntSignal::Pin(pin) => pin.number(), - PcntSignal::High => ONE_INPUT, - PcntSignal::Low => ZERO_INPUT, + PcntSource::Pin(pin) => pin.number(), + PcntSource::High => ONE_INPUT, + PcntSource::Low => ZERO_INPUT, } } } @@ -92,8 +92,8 @@ impl Channel { /// Configure the channel pub fn configure<'b, CP: InputPin, EP: InputPin>( &mut self, - ctrl_signal: PcntSignal<'b, CP>, - edge_signal: PcntSignal<'b, EP>, + ctrl_signal: PcntSource<'b, CP>, + edge_signal: PcntSource<'b, EP>, config: Config, ) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; @@ -142,7 +142,11 @@ impl Channel { } /// Set the control signal (pin/high/low) for this channel - pub fn set_ctrl_signal<'b, P: InputPin>(&self, source: PcntSignal<'b, P>, invert: bool) -> &Self { + pub fn set_ctrl_signal<'b, P: InputPin>( + &self, + source: PcntSource<'b, P>, + invert: bool, + ) -> &Self { let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_CTRL_CH0, @@ -197,7 +201,11 @@ impl Channel { } /// Set the edge signal (pin/high/low) for this channel - pub fn set_edge_signal<'b, P: InputPin>(&self, source: PcntSignal<'b, P>, invert: bool) -> &Self { + pub fn set_edge_signal<'b, P: InputPin>( + &self, + source: PcntSource<'b, P>, + invert: bool, + ) -> &Self { let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_SIG_CH0, diff --git a/esp32-hal/examples/pcnt-encoder.rs b/esp32-hal/examples/pcnt_encoder.rs similarity index 94% rename from esp32-hal/examples/pcnt-encoder.rs rename to esp32-hal/examples/pcnt_encoder.rs index 0c35abf7574..0a6d9299b58 100644 --- a/esp32-hal/examples/pcnt-encoder.rs +++ b/esp32-hal/examples/pcnt_encoder.rs @@ -20,7 +20,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, interrupt, - pcnt::{channel, channel::PcntSignal, unit, PCNT}, + pcnt::{channel, channel::PcntSource, unit, PCNT}, peripherals::{self, Peripherals}, prelude::*, timer::TimerGroup, @@ -67,8 +67,8 @@ fn main() -> ! { let mut pin_b = io.pins.gpio23.into_pull_up_input(); ch0.configure( - PcntSignal::from_pin(&mut pin_a), - PcntSignal::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, @@ -82,8 +82,8 @@ fn main() -> ! { println!("setup channel 1"); let mut ch1 = u0.get_channel(channel::Number::Channel1); ch1.configure( - PcntSignal::from_pin(&mut pin_b), - PcntSignal::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, diff --git a/esp32s2-hal/examples/pcnt-encoder.rs b/esp32s2-hal/examples/pcnt_encoder.rs similarity index 94% rename from esp32s2-hal/examples/pcnt-encoder.rs rename to esp32s2-hal/examples/pcnt_encoder.rs index 54bef1729f9..50b4dae9bb4 100644 --- a/esp32s2-hal/examples/pcnt-encoder.rs +++ b/esp32s2-hal/examples/pcnt_encoder.rs @@ -20,7 +20,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, interrupt, - pcnt::{channel, channel::PcntSignal, unit, PCNT}, + pcnt::{channel, channel::PcntSource, unit, PCNT}, peripherals::{self, Peripherals}, prelude::*, timer::TimerGroup, @@ -67,8 +67,8 @@ fn main() -> ! { let mut pin_b = io.pins.gpio6.into_pull_up_input(); ch0.configure( - PcntSignal::from_pin(&mut pin_a), - PcntSignal::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, @@ -82,8 +82,8 @@ fn main() -> ! { println!("setup channel 1"); let mut ch1 = u0.get_channel(channel::Number::Channel1); ch1.configure( - PcntSignal::from_pin(&mut pin_b), - PcntSignal::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, diff --git a/esp32s3-hal/examples/pcnt-encoder.rs b/esp32s3-hal/examples/pcnt_encoder.rs similarity index 94% rename from esp32s3-hal/examples/pcnt-encoder.rs rename to esp32s3-hal/examples/pcnt_encoder.rs index aba553b06f0..9b203cb8ca5 100644 --- a/esp32s3-hal/examples/pcnt-encoder.rs +++ b/esp32s3-hal/examples/pcnt_encoder.rs @@ -20,7 +20,7 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, interrupt, - pcnt::{channel, channel::PcntSignal, unit, PCNT}, + pcnt::{channel, channel::PcntSource, unit, PCNT}, peripherals::{self, Peripherals}, prelude::*, timer::TimerGroup, @@ -67,8 +67,8 @@ fn main() -> ! { let mut pin_b = io.pins.gpio6.into_pull_up_input(); ch0.configure( - PcntSignal::from_pin(&mut pin_a), - PcntSignal::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, @@ -82,8 +82,8 @@ fn main() -> ! { println!("setup channel 1"); let mut ch1 = u0.get_channel(channel::Number::Channel1); ch1.configure( - PcntSignal::from_pin(&mut pin_b), - PcntSignal::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a), channel::Config { lctrl_mode: channel::CtrlMode::Reverse, hctrl_mode: channel::CtrlMode::Keep, From 0f6b358b352ff9000cd19d70a5ae57c2edf56081 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Sun, 8 Jan 2023 13:45:19 -0800 Subject: [PATCH 11/16] handle error for PCNT Unit configure() in example --- esp32-hal/examples/pcnt_encoder.rs | 2 +- esp32s2-hal/examples/pcnt_encoder.rs | 2 +- esp32s3-hal/examples/pcnt_encoder.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esp32-hal/examples/pcnt_encoder.rs b/esp32-hal/examples/pcnt_encoder.rs index 0a6d9299b58..0bb76691973 100644 --- a/esp32-hal/examples/pcnt_encoder.rs +++ b/esp32-hal/examples/pcnt_encoder.rs @@ -59,7 +59,7 @@ fn main() -> ! { high_limit: 100, filter: Some(min(10u16 * 80, 1023u16)), ..Default::default() - }); + }).unwrap(); println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); diff --git a/esp32s2-hal/examples/pcnt_encoder.rs b/esp32s2-hal/examples/pcnt_encoder.rs index 50b4dae9bb4..ae1b6193068 100644 --- a/esp32s2-hal/examples/pcnt_encoder.rs +++ b/esp32s2-hal/examples/pcnt_encoder.rs @@ -59,7 +59,7 @@ fn main() -> ! { high_limit: 100, filter: Some(min(10u16 * 80, 1023u16)), ..Default::default() - }); + }).unwrap(); println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); diff --git a/esp32s3-hal/examples/pcnt_encoder.rs b/esp32s3-hal/examples/pcnt_encoder.rs index 9b203cb8ca5..b345411a38b 100644 --- a/esp32s3-hal/examples/pcnt_encoder.rs +++ b/esp32s3-hal/examples/pcnt_encoder.rs @@ -59,7 +59,7 @@ fn main() -> ! { high_limit: 100, filter: Some(min(10u16 * 80, 1023u16)), ..Default::default() - }); + }).unwrap(); println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); From 92dd48aabe918f8d4ef430a9b2c8f0063fc6c412 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 9 Jan 2023 08:18:32 -0800 Subject: [PATCH 12/16] update pac versions for status register change --- esp-hal-common/Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index bb9331e300e..e8558e381a2 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -51,11 +51,11 @@ ufmt-write = { version = "0.1.0", optional = true } # Each supported device MUST have its PAC included below along with a # corresponding feature. We rename the PAC packages because we cannot # have dependencies and features with the same names. -esp32 = { version = "0.18.0", features = ["critical-section"], optional = true } -esp32c2 = { version = "0.5.1", features = ["critical-section"], optional = true } +esp32 = { version = "0.19.0", features = ["critical-section"], optional = true } +esp32c2 = { version = "0.6.0", features = ["critical-section"], optional = true } esp32c3 = { version = "0.9.0", features = ["critical-section"], optional = true } -esp32s2 = { version = "0.8.0", features = ["critical-section"], optional = true } -esp32s3 = { version = "0.12.0", features = ["critical-section"], optional = true } +esp32s2 = { version = "0.9.0", features = ["critical-section"], optional = true } +esp32s3 = { version = "0.13.0", features = ["critical-section"], optional = true } [features] esp32 = ["esp32/rt" , "xtensa", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "lock_api"] From 825b128b70be7f8279829584c3747677c04eb187 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 9 Jan 2023 08:27:31 -0800 Subject: [PATCH 13/16] cargo fmt --- esp-hal-common/src/pcnt/unit.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index 474be2483d6..16738ed57c9 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -98,8 +98,10 @@ impl Unit { }; // disable filter and all events conf0.modify(|_, w| unsafe { - w.filter_en().clear_bit() - .filter_thres().bits(0) + w.filter_en() + .clear_bit() + .filter_thres() + .bits(0) .thr_l_lim_en() .clear_bit() .thr_h_lim_en() @@ -110,12 +112,12 @@ impl Unit { .clear_bit() .thr_zero_en() .clear_bit() - } ); + }); Self { number } } pub fn configure(&mut self, config: Config) -> Result<(), Error> { - // low limit must be >= or the limit is -32768 and when thats + // low limit must be >= or the limit is -32768 and when thats // hit the event status claims it was the high limit. // tested on an esp32s3 if config.low_limit >= 0 { @@ -126,11 +128,11 @@ impl Unit { } let (filter_en, filter) = match config.filter { Some(filter) => (true, filter), - None => (false, 0) + None => (false, 0), }; // filter must be less than 1024 if filter > 1023 { - return Err(Error::InvalidFilterThresh) + return Err(Error::InvalidFilterThresh); } let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; @@ -289,7 +291,11 @@ impl Unit { /// Get the mode of the last zero crossing pub fn get_zero_mode(&self) -> ZeroMode { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - pcnt.u_status[self.number as usize].read().zero_mode().bits().into() + pcnt.u_status[self.number as usize] + .read() + .zero_mode() + .bits() + .into() } /// Enable interrupts for this unit. From 8e91d44324d3d63e3e05b5bdc55e8d810b814a69 Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 9 Jan 2023 08:32:23 -0800 Subject: [PATCH 14/16] cargo fmt (examples) --- esp32-hal/examples/pcnt_encoder.rs | 3 ++- esp32s2-hal/examples/pcnt_encoder.rs | 3 ++- esp32s3-hal/examples/pcnt_encoder.rs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/esp32-hal/examples/pcnt_encoder.rs b/esp32-hal/examples/pcnt_encoder.rs index 0bb76691973..f747728178f 100644 --- a/esp32-hal/examples/pcnt_encoder.rs +++ b/esp32-hal/examples/pcnt_encoder.rs @@ -59,7 +59,8 @@ fn main() -> ! { high_limit: 100, filter: Some(min(10u16 * 80, 1023u16)), ..Default::default() - }).unwrap(); + }) + .unwrap(); println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); diff --git a/esp32s2-hal/examples/pcnt_encoder.rs b/esp32s2-hal/examples/pcnt_encoder.rs index ae1b6193068..137651aed85 100644 --- a/esp32s2-hal/examples/pcnt_encoder.rs +++ b/esp32s2-hal/examples/pcnt_encoder.rs @@ -59,7 +59,8 @@ fn main() -> ! { high_limit: 100, filter: Some(min(10u16 * 80, 1023u16)), ..Default::default() - }).unwrap(); + }) + .unwrap(); println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); diff --git a/esp32s3-hal/examples/pcnt_encoder.rs b/esp32s3-hal/examples/pcnt_encoder.rs index b345411a38b..441aa26e141 100644 --- a/esp32s3-hal/examples/pcnt_encoder.rs +++ b/esp32s3-hal/examples/pcnt_encoder.rs @@ -59,7 +59,8 @@ fn main() -> ! { high_limit: 100, filter: Some(min(10u16 * 80, 1023u16)), ..Default::default() - }).unwrap(); + }) + .unwrap(); println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); From 0f3cc1ea2eb2c55ea576291ca90770e9fee0755c Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Sun, 15 Jan 2023 06:38:45 -0800 Subject: [PATCH 15/16] PcntSource now only stores the source id. add a critical section to protect the ctrl & isr_en registers --- esp-hal-common/src/pcnt/channel.rs | 49 +++--- esp-hal-common/src/pcnt/unit.rs | 214 ++++++++++++++------------- esp32-hal/examples/pcnt_encoder.rs | 2 +- esp32s2-hal/examples/pcnt_encoder.rs | 2 +- esp32s3-hal/examples/pcnt_encoder.rs | 2 +- 5 files changed, 138 insertions(+), 131 deletions(-) diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index b9333d4083d..446c5d38cf7 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -4,7 +4,7 @@ use crate::{ types::{InputSignal, ONE_INPUT, ZERO_INPUT}, InputPin, }, - peripheral::{Peripheral, PeripheralRef}, + peripheral::Peripheral, peripherals::GPIO, }; @@ -55,26 +55,21 @@ pub struct Config { } /// PcntPin can be always high, always low, or an actual pin -pub enum PcntSource<'a, P: InputPin> { - Pin(PeripheralRef<'a, P>), - High, - Low, +#[derive(Clone,Copy)] +pub struct PcntSource { + source: u8, } -impl<'a, P: InputPin> PcntSource<'a, P> { - pub fn from_pin(pin: impl Peripheral

+ 'a) -> Self { +impl PcntSource { + pub fn from_pin<'a, P: InputPin>(pin: impl Peripheral

+ 'a) -> Self { crate::into_ref!(pin); - PcntSource::Pin(pin) + Self { source: pin.number() } } -} - -impl<'a, P: InputPin> From> for u8 { - fn from(pin: PcntSource<'a, P>) -> Self { - match pin { - PcntSource::Pin(pin) => pin.number(), - PcntSource::High => ONE_INPUT, - PcntSource::Low => ZERO_INPUT, - } + pub fn always_high() -> Self { + Self { source: ONE_INPUT } + } + pub fn always_low() -> Self { + Self { source: ZERO_INPUT } } } @@ -90,10 +85,10 @@ impl Channel { } /// Configure the channel - pub fn configure<'b, CP: InputPin, EP: InputPin>( + pub fn configure( &mut self, - ctrl_signal: PcntSource<'b, CP>, - edge_signal: PcntSource<'b, EP>, + ctrl_signal: PcntSource, + edge_signal: PcntSource, config: Config, ) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; @@ -142,9 +137,9 @@ impl Channel { } /// Set the control signal (pin/high/low) for this channel - pub fn set_ctrl_signal<'b, P: InputPin>( + pub fn set_ctrl_signal( &self, - source: PcntSource<'b, P>, + source: PcntSource, invert: bool, ) -> &Self { let signal = match self.unit { @@ -185,7 +180,6 @@ impl Channel { Number::Channel1 => InputSignal::PCNT7_CTRL_CH1, }, }; - let pin_num: u8 = source.into(); if (signal as usize) <= crate::types::INPUT_SIGNAL_MAX as usize { unsafe { &*GPIO::PTR }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { @@ -194,16 +188,16 @@ impl Channel { .in_inv_sel() .bit(invert) .in_sel() - .bits(pin_num) + .bits(source.source) }); } self } /// Set the edge signal (pin/high/low) for this channel - pub fn set_edge_signal<'b, P: InputPin>( + pub fn set_edge_signal( &self, - source: PcntSource<'b, P>, + source: PcntSource, invert: bool, ) -> &Self { let signal = match self.unit { @@ -244,7 +238,6 @@ impl Channel { Number::Channel1 => InputSignal::PCNT7_SIG_CH1, }, }; - let pin_num: u8 = source.into(); if (signal as usize) <= crate::types::INPUT_SIGNAL_MAX as usize { unsafe { &*GPIO::PTR }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { @@ -253,7 +246,7 @@ impl Channel { .in_inv_sel() .bit(invert) .in_sel() - .bits(pin_num) + .bits(source.source) }); } self diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index 16738ed57c9..8ccbadb621e 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -1,3 +1,5 @@ +use critical_section::CriticalSection; + use super::channel; /// Unit number @@ -174,73 +176,79 @@ impl Unit { pub fn clear(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u0().set_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u1().set_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u2().set_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u3().set_bit()), - #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u4().set_bit()), - #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u5().set_bit()), - #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u6().set_bit()), - #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u7().set_bit()), - } - // TODO: does this need a delay? (liebman / Jan 2 2023) - match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u0().clear_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u1().clear_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u2().clear_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u3().clear_bit()), - #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u4().clear_bit()), - #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u5().clear_bit()), - #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u6().clear_bit()), - #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u7().clear_bit()), - } + critical_section::with(|_cs| { + match self.number { + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u0().set_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u1().set_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u2().set_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u3().set_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u4().set_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u5().set_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u6().set_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u7().set_bit()), + } + // TODO: does this need a delay? (liebman / Jan 2 2023) + match self.number { + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u0().clear_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u1().clear_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u2().clear_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u3().clear_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u4().clear_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u5().clear_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u6().clear_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_rst_u7().clear_bit()), + } + }); } /// Pause the counter pub fn pause(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().set_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().set_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().set_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().set_bit()), - #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().set_bit()), - #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().set_bit()), - #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), - #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), - } + critical_section::with(|_cs| + match self.number { + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().set_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().set_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().set_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().set_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().set_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().set_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), + } + ); } /// Resume the counter pub fn resume(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().clear_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().clear_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().clear_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().clear_bit()), - #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().clear_bit()), - #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().clear_bit()), - #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().clear_bit()), - #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().clear_bit()), - } + critical_section::with(|_cs| + match self.number { + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().clear_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().clear_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().clear_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().clear_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().clear_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().clear_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().clear_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().clear_bit()), + } + ); } /// Enable which events generate interrupts on this unit. @@ -301,39 +309,43 @@ impl Unit { /// Enable interrupts for this unit. pub fn listen(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - pcnt.int_ena.modify(|_, w| match self.number { - Number::Unit0 => w.cnt_thr_event_u0().set_bit(), - Number::Unit1 => w.cnt_thr_event_u1().set_bit(), - Number::Unit2 => w.cnt_thr_event_u2().set_bit(), - Number::Unit3 => w.cnt_thr_event_u3().set_bit(), - #[cfg(esp32)] - Number::Unit4 => w.cnt_thr_event_u4().set_bit(), - #[cfg(esp32)] - Number::Unit5 => w.cnt_thr_event_u5().set_bit(), - #[cfg(esp32)] - Number::Unit6 => w.cnt_thr_event_u6().set_bit(), - #[cfg(esp32)] - Number::Unit7 => w.cnt_thr_event_u7().set_bit(), - }); + critical_section::with(|_cs| + pcnt.int_ena.modify(|_, w| match self.number { + Number::Unit0 => w.cnt_thr_event_u0().set_bit(), + Number::Unit1 => w.cnt_thr_event_u1().set_bit(), + Number::Unit2 => w.cnt_thr_event_u2().set_bit(), + Number::Unit3 => w.cnt_thr_event_u3().set_bit(), + #[cfg(esp32)] + Number::Unit4 => w.cnt_thr_event_u4().set_bit(), + #[cfg(esp32)] + Number::Unit5 => w.cnt_thr_event_u5().set_bit(), + #[cfg(esp32)] + Number::Unit6 => w.cnt_thr_event_u6().set_bit(), + #[cfg(esp32)] + Number::Unit7 => w.cnt_thr_event_u7().set_bit(), + }) + ); } /// Disable interrupts for this unit. - pub fn unlisten(&self) { + pub fn unlisten(&self, _cs: CriticalSection) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - pcnt.int_ena.write(|w| match self.number { - Number::Unit0 => w.cnt_thr_event_u0().clear_bit(), - Number::Unit1 => w.cnt_thr_event_u1().clear_bit(), - Number::Unit2 => w.cnt_thr_event_u2().clear_bit(), - Number::Unit3 => w.cnt_thr_event_u3().clear_bit(), - #[cfg(esp32)] - Number::Unit4 => w.cnt_thr_event_u4().clear_bit(), - #[cfg(esp32)] - Number::Unit5 => w.cnt_thr_event_u5().clear_bit(), - #[cfg(esp32)] - Number::Unit6 => w.cnt_thr_event_u6().clear_bit(), - #[cfg(esp32)] - Number::Unit7 => w.cnt_thr_event_u7().clear_bit(), - }); + critical_section::with(|_cs| + pcnt.int_ena.write(|w| match self.number { + Number::Unit0 => w.cnt_thr_event_u0().clear_bit(), + Number::Unit1 => w.cnt_thr_event_u1().clear_bit(), + Number::Unit2 => w.cnt_thr_event_u2().clear_bit(), + Number::Unit3 => w.cnt_thr_event_u3().clear_bit(), + #[cfg(esp32)] + Number::Unit4 => w.cnt_thr_event_u4().clear_bit(), + #[cfg(esp32)] + Number::Unit5 => w.cnt_thr_event_u5().clear_bit(), + #[cfg(esp32)] + Number::Unit6 => w.cnt_thr_event_u6().clear_bit(), + #[cfg(esp32)] + Number::Unit7 => w.cnt_thr_event_u7().clear_bit(), + }) + ); } /// Returns true if an interrupt is active for this unit. @@ -358,20 +370,22 @@ impl Unit { /// Clear the interrupt bit for this unit. pub fn reset_interrupt(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - pcnt.int_clr.write(|w| match self.number { - Number::Unit0 => w.cnt_thr_event_u0().set_bit(), - Number::Unit1 => w.cnt_thr_event_u1().set_bit(), - Number::Unit2 => w.cnt_thr_event_u2().set_bit(), - Number::Unit3 => w.cnt_thr_event_u3().set_bit(), - #[cfg(esp32)] - Number::Unit4 => w.cnt_thr_event_u4().set_bit(), - #[cfg(esp32)] - Number::Unit5 => w.cnt_thr_event_u5().set_bit(), - #[cfg(esp32)] - Number::Unit6 => w.cnt_thr_event_u6().set_bit(), - #[cfg(esp32)] - Number::Unit7 => w.cnt_thr_event_u7().set_bit(), - }); + critical_section::with(|_cs| + pcnt.int_clr.write(|w| match self.number { + Number::Unit0 => w.cnt_thr_event_u0().set_bit(), + Number::Unit1 => w.cnt_thr_event_u1().set_bit(), + Number::Unit2 => w.cnt_thr_event_u2().set_bit(), + Number::Unit3 => w.cnt_thr_event_u3().set_bit(), + #[cfg(esp32)] + Number::Unit4 => w.cnt_thr_event_u4().set_bit(), + #[cfg(esp32)] + Number::Unit5 => w.cnt_thr_event_u5().set_bit(), + #[cfg(esp32)] + Number::Unit6 => w.cnt_thr_event_u6().set_bit(), + #[cfg(esp32)] + Number::Unit7 => w.cnt_thr_event_u7().set_bit(), + }) + ); } /// Get the current counter value. diff --git a/esp32-hal/examples/pcnt_encoder.rs b/esp32-hal/examples/pcnt_encoder.rs index f747728178f..819e03128ea 100644 --- a/esp32-hal/examples/pcnt_encoder.rs +++ b/esp32-hal/examples/pcnt_encoder.rs @@ -3,7 +3,7 @@ //! This example decodes a quadrature encoder //! //! Since the PCNT units reset to zero when they reach their limits -//! we use enable an interrupt on the upper and lower limits and +//! we enable an interrupt on the upper and lower limits and //! track the overflow in an AtomicI32 #![no_std] diff --git a/esp32s2-hal/examples/pcnt_encoder.rs b/esp32s2-hal/examples/pcnt_encoder.rs index 137651aed85..2bdfab326a5 100644 --- a/esp32s2-hal/examples/pcnt_encoder.rs +++ b/esp32s2-hal/examples/pcnt_encoder.rs @@ -3,7 +3,7 @@ //! This example decodes a quadrature encoder //! //! Since the PCNT units reset to zero when they reach their limits -//! we use enable an interrupt on the upper and lower limits and +//! we enable an interrupt on the upper and lower limits and //! track the overflow in an AtomicI32 #![no_std] diff --git a/esp32s3-hal/examples/pcnt_encoder.rs b/esp32s3-hal/examples/pcnt_encoder.rs index 441aa26e141..201fce31d46 100644 --- a/esp32s3-hal/examples/pcnt_encoder.rs +++ b/esp32s3-hal/examples/pcnt_encoder.rs @@ -3,7 +3,7 @@ //! This example decodes a quadrature encoder //! //! Since the PCNT units reset to zero when they reach their limits -//! we use enable an interrupt on the upper and lower limits and +//! we enable an interrupt on the upper and lower limits and //! track the overflow in an AtomicI32 #![no_std] From db7656cc3a67f3732286dd09d4a9b37dd7c93d2d Mon Sep 17 00:00:00 2001 From: Christopher Liebman Date: Mon, 16 Jan 2023 07:11:47 -0800 Subject: [PATCH 16/16] cargo fmt --- esp-hal-common/src/pcnt/channel.rs | 25 +++-------- esp-hal-common/src/pcnt/unit.rs | 72 ++++++++++++++---------------- 2 files changed, 41 insertions(+), 56 deletions(-) diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index 446c5d38cf7..00cf3492c1d 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -55,7 +55,7 @@ pub struct Config { } /// PcntPin can be always high, always low, or an actual pin -#[derive(Clone,Copy)] +#[derive(Clone, Copy)] pub struct PcntSource { source: u8, } @@ -63,7 +63,9 @@ pub struct PcntSource { impl PcntSource { pub fn from_pin<'a, P: InputPin>(pin: impl Peripheral

+ 'a) -> Self { crate::into_ref!(pin); - Self { source: pin.number() } + Self { + source: pin.number(), + } } pub fn always_high() -> Self { Self { source: ONE_INPUT } @@ -85,12 +87,7 @@ impl Channel { } /// Configure the channel - pub fn configure( - &mut self, - ctrl_signal: PcntSource, - edge_signal: PcntSource, - config: Config, - ) { + pub fn configure(&mut self, ctrl_signal: PcntSource, edge_signal: PcntSource, config: Config) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; let conf0 = match self.unit { unit::Number::Unit0 => &pcnt.u0_conf0, @@ -137,11 +134,7 @@ impl Channel { } /// Set the control signal (pin/high/low) for this channel - pub fn set_ctrl_signal( - &self, - source: PcntSource, - invert: bool, - ) -> &Self { + pub fn set_ctrl_signal(&self, source: PcntSource, invert: bool) -> &Self { let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_CTRL_CH0, @@ -195,11 +188,7 @@ impl Channel { } /// Set the edge signal (pin/high/low) for this channel - pub fn set_edge_signal( - &self, - source: PcntSource, - invert: bool, - ) -> &Self { + pub fn set_edge_signal(&self, source: PcntSource, invert: bool) -> &Self { let signal = match self.unit { unit::Number::Unit0 => match self.channel { Number::Channel0 => InputSignal::PCNT0_SIG_CH0, diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index 8ccbadb621e..9703d9caa6f 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -212,43 +212,39 @@ impl Unit { /// Pause the counter pub fn pause(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - critical_section::with(|_cs| - match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().set_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().set_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().set_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().set_bit()), - #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().set_bit()), - #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().set_bit()), - #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), - #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), - } - ); + critical_section::with(|_cs| match self.number { + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().set_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().set_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().set_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().set_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().set_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().set_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().set_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().set_bit()), + }); } /// Resume the counter pub fn resume(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - critical_section::with(|_cs| - match self.number { - Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().clear_bit()), - Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().clear_bit()), - Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().clear_bit()), - Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().clear_bit()), - #[cfg(esp32)] - Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().clear_bit()), - #[cfg(esp32)] - Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().clear_bit()), - #[cfg(esp32)] - Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().clear_bit()), - #[cfg(esp32)] - Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().clear_bit()), - } - ); + critical_section::with(|_cs| match self.number { + Number::Unit0 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u0().clear_bit()), + Number::Unit1 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u1().clear_bit()), + Number::Unit2 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u2().clear_bit()), + Number::Unit3 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u3().clear_bit()), + #[cfg(esp32)] + Number::Unit4 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u4().clear_bit()), + #[cfg(esp32)] + Number::Unit5 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u5().clear_bit()), + #[cfg(esp32)] + Number::Unit6 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u6().clear_bit()), + #[cfg(esp32)] + Number::Unit7 => pcnt.ctrl.modify(|_, w| w.cnt_pause_u7().clear_bit()), + }); } /// Enable which events generate interrupts on this unit. @@ -309,7 +305,7 @@ impl Unit { /// Enable interrupts for this unit. pub fn listen(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - critical_section::with(|_cs| + critical_section::with(|_cs| { pcnt.int_ena.modify(|_, w| match self.number { Number::Unit0 => w.cnt_thr_event_u0().set_bit(), Number::Unit1 => w.cnt_thr_event_u1().set_bit(), @@ -324,13 +320,13 @@ impl Unit { #[cfg(esp32)] Number::Unit7 => w.cnt_thr_event_u7().set_bit(), }) - ); + }); } /// Disable interrupts for this unit. pub fn unlisten(&self, _cs: CriticalSection) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - critical_section::with(|_cs| + critical_section::with(|_cs| { pcnt.int_ena.write(|w| match self.number { Number::Unit0 => w.cnt_thr_event_u0().clear_bit(), Number::Unit1 => w.cnt_thr_event_u1().clear_bit(), @@ -345,7 +341,7 @@ impl Unit { #[cfg(esp32)] Number::Unit7 => w.cnt_thr_event_u7().clear_bit(), }) - ); + }); } /// Returns true if an interrupt is active for this unit. @@ -370,7 +366,7 @@ impl Unit { /// Clear the interrupt bit for this unit. pub fn reset_interrupt(&self) { let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() }; - critical_section::with(|_cs| + critical_section::with(|_cs| { pcnt.int_clr.write(|w| match self.number { Number::Unit0 => w.cnt_thr_event_u0().set_bit(), Number::Unit1 => w.cnt_thr_event_u1().set_bit(), @@ -385,7 +381,7 @@ impl Unit { #[cfg(esp32)] Number::Unit7 => w.cnt_thr_event_u7().set_bit(), }) - ); + }); } /// Get the current counter value.