mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +00:00
feat set frequency embedded hal (#880)
* Add SetDutyCycle and PwmPin trait * Add comments * Fix method call for esp32c6 and esp32h2 * Add changelog
This commit is contained in:
parent
c196b67587
commit
62894e3f84
@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Implement SetFrequencyCycle and PwmPin from embedded_hal for PwmPin of MCPWM. (#880)
|
||||||
- Added `embassy-time-systick` to ESP32-S2 (#827)
|
- Added `embassy-time-systick` to ESP32-S2 (#827)
|
||||||
- Implement enabling/disabling BLE clock on ESP32-C6 (#784)
|
- Implement enabling/disabling BLE clock on ESP32-C6 (#784)
|
||||||
- Async support for RMT (#787)
|
- Async support for RMT (#787)
|
||||||
|
@ -501,6 +501,27 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the old timestamp.
|
||||||
|
/// The value of the timestamp will take effect according to the set
|
||||||
|
/// [`PwmUpdateMethod`].
|
||||||
|
#[cfg(esp32)]
|
||||||
|
pub fn get_timestamp(&self) -> u16 {
|
||||||
|
// SAFETY:
|
||||||
|
// We only read to our GENx_TSTMP_x register
|
||||||
|
let block = unsafe { &*PWM::block() };
|
||||||
|
match (OP, IS_A) {
|
||||||
|
(0, true) => block.gen0_tstmp_a.read().gen0_a().bits(),
|
||||||
|
(1, true) => block.gen1_tstmp_a.read().gen1_a().bits(),
|
||||||
|
(2, true) => block.gen2_tstmp_a.read().gen2_a().bits(),
|
||||||
|
(0, false) => block.gen0_tstmp_b.read().gen0_b().bits(),
|
||||||
|
(1, false) => block.gen1_tstmp_b.read().gen1_b().bits(),
|
||||||
|
(2, false) => block.gen2_tstmp_b.read().gen2_b().bits(),
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Write a new timestamp.
|
/// Write a new timestamp.
|
||||||
/// The written value will take effect according to the set
|
/// The written value will take effect according to the set
|
||||||
/// [`PwmUpdateMethod`].
|
/// [`PwmUpdateMethod`].
|
||||||
@ -522,6 +543,27 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the old timestamp.
|
||||||
|
/// The value of the timestamp will take effect according to the set
|
||||||
|
/// [`PwmUpdateMethod`].
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
pub fn get_timestamp(&self) -> u16 {
|
||||||
|
// SAFETY:
|
||||||
|
// We only read to our GENx_TSTMP_x register
|
||||||
|
let block = unsafe { &*PWM::block() };
|
||||||
|
match (OP, IS_A) {
|
||||||
|
(0, true) => block.cmpr0_value0.read().cmpr0_a().bits(),
|
||||||
|
(1, true) => block.cmpr1_value0.read().cmpr1_a().bits(),
|
||||||
|
(2, true) => block.cmpr2_value0.read().cmpr2_a().bits(),
|
||||||
|
(0, false) => block.cmpr0_value1.read().cmpr0_b().bits(),
|
||||||
|
(1, false) => block.cmpr1_value1.read().cmpr1_b().bits(),
|
||||||
|
(2, false) => block.cmpr2_value1.read().cmpr2_b().bits(),
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Write a new timestamp.
|
/// Write a new timestamp.
|
||||||
/// The written value will take effect according to the set
|
/// The written value will take effect according to the set
|
||||||
/// [`PwmUpdateMethod`].
|
/// [`PwmUpdateMethod`].
|
||||||
@ -542,6 +584,112 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the old timestamp.
|
||||||
|
/// The value of the timestamp will take effect according to the set
|
||||||
|
/// [`PwmUpdateMethod`].
|
||||||
|
#[cfg(any(esp32c6, esp32h2))]
|
||||||
|
pub fn get_timestamp(&self) -> u16 {
|
||||||
|
// SAFETY:
|
||||||
|
// We only read to our GENx_TSTMP_x register
|
||||||
|
let block = unsafe { &*PWM::block() };
|
||||||
|
match (OP, IS_A) {
|
||||||
|
(0, true) => block.gen0_tstmp_a.read().cmpr0_a().bits(),
|
||||||
|
(1, true) => block.gen1_tstmp_a.read().cmpr1_a().bits(),
|
||||||
|
(2, true) => block.gen2_tstmp_a.read().cmpr2_a().bits(),
|
||||||
|
(0, false) => block.gen0_tstmp_b.read().cmpr0_b().bits(),
|
||||||
|
(1, false) => block.gen1_tstmp_b.read().cmpr1_b().bits(),
|
||||||
|
(2, false) => block.gen2_tstmp_b.read().cmpr2_b().bits(),
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the period of the timer.
|
||||||
|
fn get_period(&self) -> u16 {
|
||||||
|
// SAFETY:
|
||||||
|
// We only grant access to our CFG0 register with the lifetime of &mut self
|
||||||
|
let block = unsafe { &*PWM::block() };
|
||||||
|
|
||||||
|
let tim_select = block.operator_timersel.read();
|
||||||
|
let tim = match OP {
|
||||||
|
0 => tim_select.operator0_timersel().bits(),
|
||||||
|
1 => tim_select.operator1_timersel().bits(),
|
||||||
|
2 => tim_select.operator2_timersel().bits(),
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// SAFETY:
|
||||||
|
// The CFG0 registers are identical for all timers so we can pretend they're
|
||||||
|
// TIMER0_CFG0
|
||||||
|
let timer0_cfg = match tim {
|
||||||
|
0 => &block.timer0_cfg0,
|
||||||
|
1 => unsafe { &*(&block.timer1_cfg0 as *const _ as *const _) },
|
||||||
|
2 => unsafe { &*(&block.timer2_cfg0 as *const _ as *const _) },
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
timer0_cfg.read().timer0_period().bits()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> embedded_hal::PwmPin
|
||||||
|
for PwmPin<'d, Pin, PWM, OP, IS_A>
|
||||||
|
{
|
||||||
|
type Duty = u16;
|
||||||
|
|
||||||
|
/// This only set the timestamp to 0, if you want to disable the PwmPin,
|
||||||
|
/// it must be done on the timer itself.
|
||||||
|
fn disable(&mut self) {
|
||||||
|
self.set_timestamp(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This only set the timestamp to the maximum, if you want to disable the
|
||||||
|
/// PwmPin, it must be done on the timer itself.
|
||||||
|
fn enable(&mut self) {
|
||||||
|
self.set_timestamp(u16::MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the duty of the pin
|
||||||
|
fn get_duty(&self) -> Self::Duty {
|
||||||
|
self.get_timestamp()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the max duty of the pin
|
||||||
|
fn get_max_duty(&self) -> Self::Duty {
|
||||||
|
self.get_period()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the duty of the pin
|
||||||
|
fn set_duty(&mut self, duty: Self::Duty) {
|
||||||
|
self.set_timestamp(duty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement no error type for the PwmPin because the method are infallible
|
||||||
|
#[cfg(feature = "eh1")]
|
||||||
|
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
|
||||||
|
embedded_hal_1::pwm::ErrorType for &mut PwmPin<'d, Pin, PWM, OP, IS_A>
|
||||||
|
{
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement the trait SetDutyCycle for PwmPin
|
||||||
|
#[cfg(feature = "eh1")]
|
||||||
|
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
|
||||||
|
embedded_hal_1::pwm::SetDutyCycle for &mut PwmPin<'d, Pin, PWM, OP, IS_A>
|
||||||
|
{
|
||||||
|
/// Get the max duty of the PwmPin
|
||||||
|
fn get_max_duty_cycle(&self) -> u16 {
|
||||||
|
self.get_period()
|
||||||
|
}
|
||||||
|
/// Set the max duty of the PwmPin
|
||||||
|
fn set_duty_cycle(&mut self, duty: u16) -> Result<(), core::convert::Infallible> {
|
||||||
|
self.set_timestamp(duty);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An action the operator applies to an output
|
/// An action the operator applies to an output
|
||||||
|
Loading…
x
Reference in New Issue
Block a user