Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pulse counter implementation #328

Merged
merged 19 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions esp-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
64 changes: 32 additions & 32 deletions esp-hal-common/src/gpio/esp32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
16 changes: 16 additions & 0 deletions esp-hal-common/src/gpio/esp32s2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
16 changes: 16 additions & 0 deletions esp-hal-common/src/gpio/esp32s3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions esp-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ 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;
#[cfg(rmt)]
Expand Down
243 changes: 243 additions & 0 deletions esp-hal-common/src/pcnt/channel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
use super::unit;
use crate::{
gpio::{
types::{InputSignal, ONE_INPUT, ZERO_INPUT},
InputPin,
},
peripheral::Peripheral,
peripherals::GPIO,
};

/// 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
#[derive(Clone, Copy)]
pub struct PcntSource {
source: u8,
}

impl PcntSource {
pub fn from_pin<'a, P: InputPin>(pin: impl Peripheral<P = P> + 'a) -> Self {
crate::into_ref!(pin);
Self {
source: pin.number(),
}
}
pub fn always_high() -> Self {
Self { source: ONE_INPUT }
}
pub fn always_low() -> Self {
Self { source: ZERO_INPUT }
}
}

pub struct Channel {
unit: unit::Number,
channel: Number,
}

impl Channel {
/// return a new Channel
pub(super) fn new(unit: unit::Number, channel: Number) -> Self {
Self { unit, channel }
}

/// Configure the channel
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,
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 => {
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)
});
}
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)
});
}
}
self.set_ctrl_signal(ctrl_signal, config.invert_ctrl);
self.set_edge_signal(edge_signal, config.invert_sig);
}

/// Set the control signal (pin/high/low) for this channel
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,
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(esp32)]
unit::Number::Unit4 => match self.channel {
Number::Channel0 => InputSignal::PCNT4_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT4_CTRL_CH1,
},
#[cfg(esp32)]
unit::Number::Unit5 => match self.channel {
Number::Channel0 => InputSignal::PCNT5_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT5_CTRL_CH1,
},
#[cfg(esp32)]
unit::Number::Unit6 => match self.channel {
Number::Channel0 => InputSignal::PCNT6_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT6_CTRL_CH1,
},
#[cfg(esp32)]
unit::Number::Unit7 => match self.channel {
Number::Channel0 => InputSignal::PCNT7_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT7_CTRL_CH1,
},
};

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(source.source)
});
}
self
}

/// Set the edge signal (pin/high/low) for this channel
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,
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(esp32)]
unit::Number::Unit4 => match self.channel {
Number::Channel0 => InputSignal::PCNT4_SIG_CH0,
Number::Channel1 => InputSignal::PCNT4_SIG_CH1,
},
#[cfg(esp32)]
unit::Number::Unit5 => match self.channel {
Number::Channel0 => InputSignal::PCNT5_SIG_CH0,
Number::Channel1 => InputSignal::PCNT5_SIG_CH1,
},
#[cfg(esp32)]
unit::Number::Unit6 => match self.channel {
Number::Channel0 => InputSignal::PCNT6_SIG_CH0,
Number::Channel1 => InputSignal::PCNT6_SIG_CH1,
},
#[cfg(esp32)]
unit::Number::Unit7 => match self.channel {
Number::Channel0 => InputSignal::PCNT7_SIG_CH0,
Number::Channel1 => InputSignal::PCNT7_SIG_CH1,
},
};

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(source.source)
});
}
self
}
}
Loading