mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +00:00

* Unify the system peripheral Whilst the PCR, SYSTEM and DPORT peripherals are different, we currently use them all in the same way. This PR unifies the peripheral name in the hal to `SYSTEM`. The idea is that they all do the same sort of thing, so we can collect them under the same name, and later down the line we can being to expose differences under an extended API. The benifits to this are imo quite big, the examples now are all identical, which makes things easier for esp-wifi, and paves a path towards the multichip hal. Why not do this in the PAC? Imo the pac should be as close to the hardware as possible, and the HAL is where we should abstractions such as this. * changelog
134 lines
3.8 KiB
Rust
134 lines
3.8 KiB
Rust
//! PCNT Encoder Demo
|
|
//!
|
|
//! This example decodes a quadrature encoder
|
|
//!
|
|
//! Since the PCNT units reset to zero when they reach their limits
|
|
//! we enable an interrupt on the upper and lower limits and
|
|
//! track the overflow in an AtomicI32
|
|
|
|
#![no_std]
|
|
#![no_main]
|
|
use core::{
|
|
cell::RefCell,
|
|
cmp::min,
|
|
sync::atomic::{AtomicI32, Ordering},
|
|
};
|
|
|
|
use critical_section::Mutex;
|
|
use esp32h2_hal as esp_hal;
|
|
use esp_backtrace as _;
|
|
use esp_hal::{
|
|
clock::ClockControl,
|
|
interrupt,
|
|
pcnt::{channel, channel::PcntSource, unit, PCNT},
|
|
peripherals::{self, Peripherals},
|
|
prelude::*,
|
|
IO,
|
|
};
|
|
use esp_println::println;
|
|
|
|
static UNIT0: Mutex<RefCell<Option<unit::Unit>>> = Mutex::new(RefCell::new(None));
|
|
static VALUE: AtomicI32 = AtomicI32::new(0);
|
|
|
|
#[entry]
|
|
fn main() -> ! {
|
|
let peripherals = Peripherals::take();
|
|
let system = peripherals.SYSTEM.split();
|
|
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
|
|
|
let unit_number = unit::Number::Unit1;
|
|
|
|
// setup a pulse couter
|
|
println!("setup pulse counter unit 0");
|
|
let pcnt = PCNT::new(peripherals.PCNT);
|
|
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()
|
|
})
|
|
.unwrap();
|
|
|
|
println!("setup channel 0");
|
|
let mut ch0 = u0.get_channel(channel::Number::Channel0);
|
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
|
let mut pin_a = io.pins.gpio4.into_pull_up_input();
|
|
let mut pin_b = io.pins.gpio5.into_pull_up_input();
|
|
|
|
ch0.configure(
|
|
PcntSource::from_pin(&mut pin_a),
|
|
PcntSource::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(
|
|
PcntSource::from_pin(&mut pin_b),
|
|
PcntSource::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();
|
|
}
|
|
});
|
|
}
|