stm32: Add the ability to center-align timers
This commit is contained in:
parent
70005c3956
commit
561126b0d6
@ -57,11 +57,12 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
|||||||
_ch4: Option<PwmPin<'d, T, Ch4>>,
|
_ch4: Option<PwmPin<'d, T, Ch4>>,
|
||||||
_ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>,
|
_ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>,
|
||||||
freq: Hertz,
|
freq: Hertz,
|
||||||
|
counting_mode: CountingMode,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(tim, freq)
|
Self::new_inner(tim, freq, counting_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self {
|
fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
|
||||||
into_ref!(tim);
|
into_ref!(tim);
|
||||||
|
|
||||||
T::enable();
|
T::enable();
|
||||||
@ -70,6 +71,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
|||||||
let mut this = Self { inner: tim };
|
let mut this = Self { inner: tim };
|
||||||
|
|
||||||
this.inner.set_frequency(freq);
|
this.inner.set_frequency(freq);
|
||||||
|
this.inner.set_counting_mode(counting_mode);
|
||||||
this.inner.start();
|
this.inner.start();
|
||||||
|
|
||||||
this.inner.enable_outputs(true);
|
this.inner.enable_outputs(true);
|
||||||
|
@ -75,8 +75,16 @@ pub(crate) mod sealed {
|
|||||||
pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
|
pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
|
||||||
fn regs_gp16() -> crate::pac::timer::TimGp16;
|
fn regs_gp16() -> crate::pac::timer::TimGp16;
|
||||||
|
|
||||||
fn set_count_direction(&mut self, direction: vals::Dir) {
|
fn set_counting_mode(&mut self, mode: CountingMode) {
|
||||||
Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
|
let (cms, dir) = mode.values();
|
||||||
|
|
||||||
|
let timer_enabled = Self::regs().cr1().read().cen();
|
||||||
|
// Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running.
|
||||||
|
// Changing direction is discouraged while the timer is running.
|
||||||
|
assert!(timer_enabled);
|
||||||
|
|
||||||
|
Self::regs_gp16().cr1().modify(|r| r.set_dir(dir));
|
||||||
|
Self::regs_gp16().cr1().modify(|r| r.set_cms(cms))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clock_division(&mut self, ckd: vals::Ckd) {
|
fn set_clock_division(&mut self, ckd: vals::Ckd) {
|
||||||
@ -265,6 +273,43 @@ impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
|
pub enum CountingMode {
|
||||||
|
#[default]
|
||||||
|
/// The timer counts up to the reload value and then resets back to 0.
|
||||||
|
EdgeAlignedUp,
|
||||||
|
/// The timer counts down to 0 and then resets back to the reload value.
|
||||||
|
EdgeAlignedDown,
|
||||||
|
/// The timer counts up to the reload value and then counts back to 0.
|
||||||
|
///
|
||||||
|
/// The output compare interrupt flags of channels configured in output are
|
||||||
|
/// set when the counter is counting down.
|
||||||
|
CenterAlignedDownInterrupts,
|
||||||
|
/// The timer counts up to the reload value and then counts back to 0.
|
||||||
|
///
|
||||||
|
/// The output compare interrupt flags of channels configured in output are
|
||||||
|
/// set when the counter is counting up.
|
||||||
|
CenterAlignedUpInterrupts,
|
||||||
|
/// The timer counts up to the reload value and then counts back to 0.
|
||||||
|
///
|
||||||
|
/// The output compare interrupt flags of channels configured in output are
|
||||||
|
/// set when the counter is counting both up or down.
|
||||||
|
CenterAlignedBothInterrupts,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CountingMode {
|
||||||
|
/// Get the register values to set the timer mode to the current variant
|
||||||
|
pub fn values(&self) -> (vals::Cms, vals::Dir) {
|
||||||
|
match self {
|
||||||
|
CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP),
|
||||||
|
CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN),
|
||||||
|
CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP),
|
||||||
|
CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP),
|
||||||
|
CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum OutputCompareMode {
|
pub enum OutputCompareMode {
|
||||||
Frozen,
|
Frozen,
|
||||||
|
@ -56,11 +56,12 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
|||||||
_ch3: Option<PwmPin<'d, T, Ch3>>,
|
_ch3: Option<PwmPin<'d, T, Ch3>>,
|
||||||
_ch4: Option<PwmPin<'d, T, Ch4>>,
|
_ch4: Option<PwmPin<'d, T, Ch4>>,
|
||||||
freq: Hertz,
|
freq: Hertz,
|
||||||
|
counting_mode: CountingMode,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(tim, freq)
|
Self::new_inner(tim, freq, counting_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self {
|
fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
|
||||||
into_ref!(tim);
|
into_ref!(tim);
|
||||||
|
|
||||||
T::enable();
|
T::enable();
|
||||||
@ -69,6 +70,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
|||||||
let mut this = Self { inner: tim };
|
let mut this = Self { inner: tim };
|
||||||
|
|
||||||
this.inner.set_frequency(freq);
|
this.inner.set_frequency(freq);
|
||||||
|
this.inner.set_counting_mode(counting_mode);
|
||||||
this.inner.start();
|
this.inner.start();
|
||||||
|
|
||||||
this.inner.enable_outputs(true);
|
this.inner.enable_outputs(true);
|
||||||
|
Loading…
Reference in New Issue
Block a user