mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-10-02 22:54:52 +00:00
stm32: rename timer channel trait; replace impls via macro with impls generic over timer channels
This commit is contained in:
parent
cbd24bf2ee
commit
6f88c2c73c
@ -6,11 +6,11 @@ use stm32_metapac::timer::vals::Ckd;
|
|||||||
|
|
||||||
use super::low_level::{CountingMode, OutputPolarity, Timer};
|
use super::low_level::{CountingMode, OutputPolarity, Timer};
|
||||||
use super::simple_pwm::PwmPin;
|
use super::simple_pwm::PwmPin;
|
||||||
use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, TimerChannel, TimerComplementaryPin};
|
use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin};
|
||||||
use crate::gpio::{AnyPin, OutputType};
|
use crate::gpio::{AnyPin, OutputType};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::timer::low_level::OutputCompareMode;
|
use crate::timer::low_level::OutputCompareMode;
|
||||||
use crate::timer::Channel;
|
use crate::timer::TimerChannel;
|
||||||
use crate::Peri;
|
use crate::Peri;
|
||||||
|
|
||||||
/// Complementary PWM pin wrapper.
|
/// Complementary PWM pin wrapper.
|
||||||
@ -21,7 +21,7 @@ pub struct ComplementaryPwmPin<'d, T, C> {
|
|||||||
phantom: PhantomData<(T, C)>,
|
phantom: PhantomData<(T, C)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: AdvancedInstance4Channel, C: Channel> ComplementaryPwmPin<'d, T, C> {
|
impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> {
|
||||||
/// Create a new complementary PWM pin instance.
|
/// Create a new complementary PWM pin instance.
|
||||||
pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self {
|
pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
@ -71,29 +71,24 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
|
|||||||
|
|
||||||
this.inner.enable_outputs();
|
this.inner.enable_outputs();
|
||||||
|
|
||||||
[
|
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
|
||||||
TimerChannel::Ch1,
|
.iter()
|
||||||
TimerChannel::Ch2,
|
.for_each(|&channel| {
|
||||||
TimerChannel::Ch3,
|
this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
|
||||||
TimerChannel::Ch4,
|
this.inner.set_output_compare_preload(channel, true);
|
||||||
]
|
});
|
||||||
.iter()
|
|
||||||
.for_each(|&channel| {
|
|
||||||
this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
|
|
||||||
this.inner.set_output_compare_preload(channel, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable the given channel.
|
/// Enable the given channel.
|
||||||
pub fn enable(&mut self, channel: TimerChannel) {
|
pub fn enable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_channel(channel, true);
|
self.inner.enable_channel(channel, true);
|
||||||
self.inner.enable_complementary_channel(channel, true);
|
self.inner.enable_complementary_channel(channel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable the given channel.
|
/// Disable the given channel.
|
||||||
pub fn disable(&mut self, channel: TimerChannel) {
|
pub fn disable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_complementary_channel(channel, false);
|
self.inner.enable_complementary_channel(channel, false);
|
||||||
self.inner.enable_channel(channel, false);
|
self.inner.enable_channel(channel, false);
|
||||||
}
|
}
|
||||||
@ -121,13 +116,13 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
|
|||||||
/// Set the duty for a given channel.
|
/// Set the duty for a given channel.
|
||||||
///
|
///
|
||||||
/// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
|
/// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
|
||||||
pub fn set_duty(&mut self, channel: TimerChannel, duty: u16) {
|
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
|
||||||
assert!(duty <= self.get_max_duty());
|
assert!(duty <= self.get_max_duty());
|
||||||
self.inner.set_compare_value(channel, duty as _)
|
self.inner.set_compare_value(channel, duty as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the output polarity for a given channel.
|
/// Set the output polarity for a given channel.
|
||||||
pub fn set_polarity(&mut self, channel: TimerChannel, polarity: OutputPolarity) {
|
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
||||||
self.inner.set_output_polarity(channel, polarity);
|
self.inner.set_output_polarity(channel, polarity);
|
||||||
self.inner.set_complementary_output_polarity(channel, polarity);
|
self.inner.set_complementary_output_polarity(channel, polarity);
|
||||||
}
|
}
|
||||||
@ -142,7 +137,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
|
impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
|
||||||
type Channel = TimerChannel;
|
type Channel = Channel;
|
||||||
type Time = Hertz;
|
type Time = Hertz;
|
||||||
type Duty = u16;
|
type Duty = u16;
|
||||||
|
|
||||||
|
@ -6,12 +6,12 @@ use core::pin::Pin;
|
|||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
|
|
||||||
use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer};
|
use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer};
|
||||||
use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, TimerChannel, TimerPin};
|
use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, Channel, TimerPin};
|
||||||
pub use super::{Ch1, Ch2, Ch3, Ch4};
|
pub use super::{Ch1, Ch2, Ch3, Ch4};
|
||||||
use crate::gpio::{AfType, AnyPin, Pull};
|
use crate::gpio::{AfType, AnyPin, Pull};
|
||||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::timer::Channel;
|
use crate::timer::TimerChannel;
|
||||||
use crate::Peri;
|
use crate::Peri;
|
||||||
|
|
||||||
/// Capture pin wrapper.
|
/// Capture pin wrapper.
|
||||||
@ -21,7 +21,7 @@ pub struct CapturePin<'d, T, C> {
|
|||||||
_pin: Peri<'d, AnyPin>,
|
_pin: Peri<'d, AnyPin>,
|
||||||
phantom: PhantomData<(T, C)>,
|
phantom: PhantomData<(T, C)>,
|
||||||
}
|
}
|
||||||
impl<'d, T: GeneralInstance4Channel, C: Channel> CapturePin<'d, T, C> {
|
impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
|
||||||
/// Create a new capture pin instance.
|
/// Create a new capture pin instance.
|
||||||
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
|
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
|
||||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||||
@ -68,46 +68,41 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Enable the given channel.
|
/// Enable the given channel.
|
||||||
pub fn enable(&mut self, channel: TimerChannel) {
|
pub fn enable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_channel(channel, true);
|
self.inner.enable_channel(channel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable the given channel.
|
/// Disable the given channel.
|
||||||
pub fn disable(&mut self, channel: TimerChannel) {
|
pub fn disable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_channel(channel, false);
|
self.inner.enable_channel(channel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether given channel is enabled
|
/// Check whether given channel is enabled
|
||||||
pub fn is_enabled(&self, channel: TimerChannel) -> bool {
|
pub fn is_enabled(&self, channel: Channel) -> bool {
|
||||||
self.inner.get_channel_enable_state(channel)
|
self.inner.get_channel_enable_state(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the input capture mode for a given channel.
|
/// Set the input capture mode for a given channel.
|
||||||
pub fn set_input_capture_mode(&mut self, channel: TimerChannel, mode: InputCaptureMode) {
|
pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
|
||||||
self.inner.set_input_capture_mode(channel, mode);
|
self.inner.set_input_capture_mode(channel, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set input TI selection.
|
/// Set input TI selection.
|
||||||
pub fn set_input_ti_selection(&mut self, channel: TimerChannel, tisel: InputTISelection) {
|
pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
|
||||||
self.inner.set_input_ti_selection(channel, tisel)
|
self.inner.set_input_ti_selection(channel, tisel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get capture value for a channel.
|
/// Get capture value for a channel.
|
||||||
pub fn get_capture_value(&self, channel: TimerChannel) -> u32 {
|
pub fn get_capture_value(&self, channel: Channel) -> u32 {
|
||||||
self.inner.get_capture_value(channel)
|
self.inner.get_capture_value(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get input interrupt.
|
/// Get input interrupt.
|
||||||
pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool {
|
pub fn get_input_interrupt(&self, channel: Channel) -> bool {
|
||||||
self.inner.get_input_interrupt(channel)
|
self.inner.get_input_interrupt(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_future(
|
fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> {
|
||||||
&self,
|
|
||||||
channel: TimerChannel,
|
|
||||||
mode: InputCaptureMode,
|
|
||||||
tisel: InputTISelection,
|
|
||||||
) -> InputCaptureFuture<T> {
|
|
||||||
// Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5
|
// Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5
|
||||||
// or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode
|
// or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode
|
||||||
self.inner.set_input_ti_selection(channel, tisel);
|
self.inner.set_input_ti_selection(channel, tisel);
|
||||||
@ -124,37 +119,37 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously wait until the pin sees a rising edge.
|
/// Asynchronously wait until the pin sees a rising edge.
|
||||||
pub async fn wait_for_rising_edge(&mut self, channel: TimerChannel) -> u32 {
|
pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 {
|
||||||
self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal)
|
self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously wait until the pin sees a falling edge.
|
/// Asynchronously wait until the pin sees a falling edge.
|
||||||
pub async fn wait_for_falling_edge(&mut self, channel: TimerChannel) -> u32 {
|
pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 {
|
||||||
self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal)
|
self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously wait until the pin sees any edge.
|
/// Asynchronously wait until the pin sees any edge.
|
||||||
pub async fn wait_for_any_edge(&mut self, channel: TimerChannel) -> u32 {
|
pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 {
|
||||||
self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal)
|
self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously wait until the (alternate) pin sees a rising edge.
|
/// Asynchronously wait until the (alternate) pin sees a rising edge.
|
||||||
pub async fn wait_for_rising_edge_alternate(&mut self, channel: TimerChannel) -> u32 {
|
pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 {
|
||||||
self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate)
|
self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously wait until the (alternate) pin sees a falling edge.
|
/// Asynchronously wait until the (alternate) pin sees a falling edge.
|
||||||
pub async fn wait_for_falling_edge_alternate(&mut self, channel: TimerChannel) -> u32 {
|
pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 {
|
||||||
self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate)
|
self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously wait until the (alternate) pin sees any edge.
|
/// Asynchronously wait until the (alternate) pin sees any edge.
|
||||||
pub async fn wait_for_any_edge_alternate(&mut self, channel: TimerChannel) -> u32 {
|
pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 {
|
||||||
self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate)
|
self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -162,7 +157,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
|
|||||||
|
|
||||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||||
struct InputCaptureFuture<T: GeneralInstance4Channel> {
|
struct InputCaptureFuture<T: GeneralInstance4Channel> {
|
||||||
channel: TimerChannel,
|
channel: Channel,
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set input capture filter.
|
/// Set input capture filter.
|
||||||
pub fn set_input_capture_filter(&self, channel: TimerChannel, icf: vals::FilterValue) {
|
pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) {
|
||||||
let raw_channel = channel.index();
|
let raw_channel = channel.index();
|
||||||
self.regs_gp16()
|
self.regs_gp16()
|
||||||
.ccmr_input(raw_channel / 2)
|
.ccmr_input(raw_channel / 2)
|
||||||
@ -511,22 +511,22 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Clear input interrupt.
|
/// Clear input interrupt.
|
||||||
pub fn clear_input_interrupt(&self, channel: TimerChannel) {
|
pub fn clear_input_interrupt(&self, channel: Channel) {
|
||||||
self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
|
self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get input interrupt.
|
/// Get input interrupt.
|
||||||
pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool {
|
pub fn get_input_interrupt(&self, channel: Channel) -> bool {
|
||||||
self.regs_gp16().sr().read().ccif(channel.index())
|
self.regs_gp16().sr().read().ccif(channel.index())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable input interrupt.
|
/// Enable input interrupt.
|
||||||
pub fn enable_input_interrupt(&self, channel: TimerChannel, enable: bool) {
|
pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) {
|
||||||
self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
|
self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set input capture prescaler.
|
/// Set input capture prescaler.
|
||||||
pub fn set_input_capture_prescaler(&self, channel: TimerChannel, factor: u8) {
|
pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) {
|
||||||
let raw_channel = channel.index();
|
let raw_channel = channel.index();
|
||||||
self.regs_gp16()
|
self.regs_gp16()
|
||||||
.ccmr_input(raw_channel / 2)
|
.ccmr_input(raw_channel / 2)
|
||||||
@ -534,7 +534,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set input TI selection.
|
/// Set input TI selection.
|
||||||
pub fn set_input_ti_selection(&self, channel: TimerChannel, tisel: InputTISelection) {
|
pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) {
|
||||||
let raw_channel = channel.index();
|
let raw_channel = channel.index();
|
||||||
self.regs_gp16()
|
self.regs_gp16()
|
||||||
.ccmr_input(raw_channel / 2)
|
.ccmr_input(raw_channel / 2)
|
||||||
@ -542,7 +542,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set input capture mode.
|
/// Set input capture mode.
|
||||||
pub fn set_input_capture_mode(&self, channel: TimerChannel, mode: InputCaptureMode) {
|
pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) {
|
||||||
self.regs_gp16().ccer().modify(|r| match mode {
|
self.regs_gp16().ccer().modify(|r| match mode {
|
||||||
InputCaptureMode::Rising => {
|
InputCaptureMode::Rising => {
|
||||||
r.set_ccnp(channel.index(), false);
|
r.set_ccnp(channel.index(), false);
|
||||||
@ -560,7 +560,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set output compare mode.
|
/// Set output compare mode.
|
||||||
pub fn set_output_compare_mode(&self, channel: TimerChannel, mode: OutputCompareMode) {
|
pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) {
|
||||||
let raw_channel: usize = channel.index();
|
let raw_channel: usize = channel.index();
|
||||||
self.regs_gp16()
|
self.regs_gp16()
|
||||||
.ccmr_output(raw_channel / 2)
|
.ccmr_output(raw_channel / 2)
|
||||||
@ -568,24 +568,24 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set output polarity.
|
/// Set output polarity.
|
||||||
pub fn set_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) {
|
pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
|
||||||
self.regs_gp16()
|
self.regs_gp16()
|
||||||
.ccer()
|
.ccer()
|
||||||
.modify(|w| w.set_ccp(channel.index(), polarity.into()));
|
.modify(|w| w.set_ccp(channel.index(), polarity.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable/disable a channel.
|
/// Enable/disable a channel.
|
||||||
pub fn enable_channel(&self, channel: TimerChannel, enable: bool) {
|
pub fn enable_channel(&self, channel: Channel, enable: bool) {
|
||||||
self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
|
self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get enable/disable state of a channel
|
/// Get enable/disable state of a channel
|
||||||
pub fn get_channel_enable_state(&self, channel: TimerChannel) -> bool {
|
pub fn get_channel_enable_state(&self, channel: Channel) -> bool {
|
||||||
self.regs_gp16().ccer().read().cce(channel.index())
|
self.regs_gp16().ccer().read().cce(channel.index())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set compare value for a channel.
|
/// Set compare value for a channel.
|
||||||
pub fn set_compare_value(&self, channel: TimerChannel, value: u32) {
|
pub fn set_compare_value(&self, channel: Channel, value: u32) {
|
||||||
match T::BITS {
|
match T::BITS {
|
||||||
TimerBits::Bits16 => {
|
TimerBits::Bits16 => {
|
||||||
let value = unwrap!(u16::try_from(value));
|
let value = unwrap!(u16::try_from(value));
|
||||||
@ -599,7 +599,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get compare value for a channel.
|
/// Get compare value for a channel.
|
||||||
pub fn get_compare_value(&self, channel: TimerChannel) -> u32 {
|
pub fn get_compare_value(&self, channel: Channel) -> u32 {
|
||||||
match T::BITS {
|
match T::BITS {
|
||||||
TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32,
|
TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32,
|
||||||
#[cfg(not(stm32l0))]
|
#[cfg(not(stm32l0))]
|
||||||
@ -608,12 +608,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get capture value for a channel.
|
/// Get capture value for a channel.
|
||||||
pub fn get_capture_value(&self, channel: TimerChannel) -> u32 {
|
pub fn get_capture_value(&self, channel: Channel) -> u32 {
|
||||||
self.get_compare_value(channel)
|
self.get_compare_value(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set output compare preload.
|
/// Set output compare preload.
|
||||||
pub fn set_output_compare_preload(&self, channel: TimerChannel, preload: bool) {
|
pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) {
|
||||||
let channel_index = channel.index();
|
let channel_index = channel.index();
|
||||||
self.regs_gp16()
|
self.regs_gp16()
|
||||||
.ccmr_output(channel_index / 2)
|
.ccmr_output(channel_index / 2)
|
||||||
@ -631,12 +631,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get capture compare DMA enable state
|
/// Get capture compare DMA enable state
|
||||||
pub fn get_cc_dma_enable_state(&self, channel: TimerChannel) -> bool {
|
pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
|
||||||
self.regs_gp16().dier().read().ccde(channel.index())
|
self.regs_gp16().dier().read().ccde(channel.index())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set capture compare DMA enable state
|
/// Set capture compare DMA enable state
|
||||||
pub fn set_cc_dma_enable_state(&self, channel: TimerChannel, ccde: bool) {
|
pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) {
|
||||||
self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
|
self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,14 +713,14 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set complementary output polarity.
|
/// Set complementary output polarity.
|
||||||
pub fn set_complementary_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) {
|
pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
|
||||||
self.regs_advanced()
|
self.regs_advanced()
|
||||||
.ccer()
|
.ccer()
|
||||||
.modify(|w| w.set_ccnp(channel.index(), polarity.into()));
|
.modify(|w| w.set_ccnp(channel.index(), polarity.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable/disable a complementary channel.
|
/// Enable/disable a complementary channel.
|
||||||
pub fn enable_complementary_channel(&self, channel: TimerChannel, enable: bool) {
|
pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) {
|
||||||
self.regs_advanced()
|
self.regs_advanced()
|
||||||
.ccer()
|
.ccer()
|
||||||
.modify(|w| w.set_ccne(channel.index(), enable));
|
.modify(|w| w.set_ccne(channel.index(), enable));
|
||||||
|
@ -19,7 +19,7 @@ use crate::rcc::RccPeripheral;
|
|||||||
|
|
||||||
/// Timer channel.
|
/// Timer channel.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum TimerChannel {
|
pub enum Channel {
|
||||||
/// Channel 1.
|
/// Channel 1.
|
||||||
Ch1,
|
Ch1,
|
||||||
/// Channel 2.
|
/// Channel 2.
|
||||||
@ -30,14 +30,14 @@ pub enum TimerChannel {
|
|||||||
Ch4,
|
Ch4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimerChannel {
|
impl Channel {
|
||||||
/// Get the channel index (0..3)
|
/// Get the channel index (0..3)
|
||||||
pub fn index(&self) -> usize {
|
pub fn index(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
TimerChannel::Ch1 => 0,
|
Channel::Ch1 => 0,
|
||||||
TimerChannel::Ch2 => 1,
|
Channel::Ch2 => 1,
|
||||||
TimerChannel::Ch3 => 2,
|
Channel::Ch3 => 2,
|
||||||
TimerChannel::Ch4 => 3,
|
Channel::Ch4 => 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,33 +53,33 @@ pub enum Ch4 {}
|
|||||||
|
|
||||||
/// Timer channel trait.
|
/// Timer channel trait.
|
||||||
#[allow(private_bounds)]
|
#[allow(private_bounds)]
|
||||||
pub trait Channel: SealedChannel {
|
pub trait TimerChannel: SealedTimerChannel {
|
||||||
/// The runtime channel.
|
/// The runtime channel.
|
||||||
const CHANNEL: TimerChannel;
|
const CHANNEL: Channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SealedChannel {}
|
trait SealedTimerChannel {}
|
||||||
|
|
||||||
impl Channel for Ch1 {
|
impl TimerChannel for Ch1 {
|
||||||
const CHANNEL: TimerChannel = TimerChannel::Ch1;
|
const CHANNEL: Channel = Channel::Ch1;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel for Ch2 {
|
impl TimerChannel for Ch2 {
|
||||||
const CHANNEL: TimerChannel = TimerChannel::Ch2;
|
const CHANNEL: Channel = Channel::Ch2;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel for Ch3 {
|
impl TimerChannel for Ch3 {
|
||||||
const CHANNEL: TimerChannel = TimerChannel::Ch3;
|
const CHANNEL: Channel = Channel::Ch3;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel for Ch4 {
|
impl TimerChannel for Ch4 {
|
||||||
const CHANNEL: TimerChannel = TimerChannel::Ch4;
|
const CHANNEL: Channel = Channel::Ch4;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SealedChannel for Ch1 {}
|
impl SealedTimerChannel for Ch1 {}
|
||||||
impl SealedChannel for Ch2 {}
|
impl SealedTimerChannel for Ch2 {}
|
||||||
impl SealedChannel for Ch3 {}
|
impl SealedTimerChannel for Ch3 {}
|
||||||
impl SealedChannel for Ch4 {}
|
impl SealedTimerChannel for Ch4 {}
|
||||||
|
|
||||||
/// Timer break input.
|
/// Timer break input.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -223,10 +223,10 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad
|
|||||||
/// Advanced 16-bit timer with 4 channels instance.
|
/// Advanced 16-bit timer with 4 channels instance.
|
||||||
pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
|
pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
|
||||||
|
|
||||||
pin_trait!(TimerPin, GeneralInstance4Channel, Channel);
|
pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel);
|
||||||
pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
|
pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
|
||||||
|
|
||||||
pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, Channel);
|
pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel);
|
||||||
|
|
||||||
pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
|
pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput);
|
|||||||
// Update Event trigger DMA for every timer
|
// Update Event trigger DMA for every timer
|
||||||
dma_trait!(UpDma, BasicInstance);
|
dma_trait!(UpDma, BasicInstance);
|
||||||
|
|
||||||
dma_trait!(Dma, GeneralInstance4Channel, Channel);
|
dma_trait!(Dma, GeneralInstance4Channel, TimerChannel);
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
macro_rules! impl_core_timer {
|
macro_rules! impl_core_timer {
|
||||||
|
@ -9,7 +9,7 @@ use core::task::{Context, Poll};
|
|||||||
use super::low_level::{
|
use super::low_level::{
|
||||||
CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
|
CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
|
||||||
};
|
};
|
||||||
use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin};
|
use super::{CaptureCompareInterruptHandler, Channel, ExternalTriggerPin, GeneralInstance4Channel, TimerPin};
|
||||||
pub use super::{Ch1, Ch2};
|
pub use super::{Ch1, Ch2};
|
||||||
use crate::gpio::{AfType, AnyPin, Pull};
|
use crate::gpio::{AfType, AnyPin, Pull};
|
||||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||||
@ -76,7 +76,7 @@ impl<T, P, C> TimerTriggerPin<T, C> for P
|
|||||||
where
|
where
|
||||||
T: GeneralInstance4Channel,
|
T: GeneralInstance4Channel,
|
||||||
P: TimerPin<T, C>,
|
P: TimerPin<T, C>,
|
||||||
C: super::Channel + TriggerSource,
|
C: super::TimerChannel + TriggerSource,
|
||||||
{
|
{
|
||||||
fn af_num(&self) -> u8 {
|
fn af_num(&self) -> u8 {
|
||||||
TimerPin::af_num(self)
|
TimerPin::af_num(self)
|
||||||
@ -97,7 +97,7 @@ impl<T, P, C> SealedTimerTriggerPin<T, C> for P
|
|||||||
where
|
where
|
||||||
T: GeneralInstance4Channel,
|
T: GeneralInstance4Channel,
|
||||||
P: TimerPin<T, C>,
|
P: TimerPin<T, C>,
|
||||||
C: super::Channel + TriggerSource,
|
C: super::TimerChannel + TriggerSource,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,9 +143,9 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
|
|
||||||
this.inner.set_trigger_source(Ts::TI1F_ED);
|
this.inner.set_trigger_source(Ts::TI1F_ED);
|
||||||
this.inner
|
this.inner
|
||||||
.set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
|
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||||
this.inner
|
this.inner
|
||||||
.set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER);
|
.set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
|
||||||
this.new_inner(freq, pulse_end, counting_mode);
|
this.new_inner(freq, pulse_end, counting_mode);
|
||||||
|
|
||||||
this
|
this
|
||||||
@ -168,10 +168,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
|
|
||||||
this.inner.set_trigger_source(Ts::TI1FP1);
|
this.inner.set_trigger_source(Ts::TI1FP1);
|
||||||
this.inner
|
this.inner
|
||||||
.set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
|
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||||
this.inner
|
this.inner
|
||||||
.set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER);
|
.set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
|
||||||
this.inner.set_input_capture_mode(TimerChannel::Ch1, capture_mode);
|
this.inner.set_input_capture_mode(Channel::Ch1, capture_mode);
|
||||||
this.new_inner(freq, pulse_end, counting_mode);
|
this.new_inner(freq, pulse_end, counting_mode);
|
||||||
|
|
||||||
this
|
this
|
||||||
@ -194,10 +194,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
|
|
||||||
this.inner.set_trigger_source(Ts::TI2FP2);
|
this.inner.set_trigger_source(Ts::TI2FP2);
|
||||||
this.inner
|
this.inner
|
||||||
.set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal);
|
.set_input_ti_selection(Channel::Ch2, InputTISelection::Normal);
|
||||||
this.inner
|
this.inner
|
||||||
.set_input_capture_filter(TimerChannel::Ch2, FilterValue::NO_FILTER);
|
.set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER);
|
||||||
this.inner.set_input_capture_mode(TimerChannel::Ch2, capture_mode);
|
this.inner.set_input_capture_mode(Channel::Ch2, capture_mode);
|
||||||
this.new_inner(freq, pulse_end, counting_mode);
|
this.new_inner(freq, pulse_end, counting_mode);
|
||||||
|
|
||||||
this
|
this
|
||||||
@ -269,7 +269,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
/// Get a single channel
|
/// Get a single channel
|
||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn channel(&mut self, channel: TimerChannel) -> OnePulseChannel<'_, T> {
|
pub fn channel(&mut self, channel: Channel) -> OnePulseChannel<'_, T> {
|
||||||
OnePulseChannel {
|
OnePulseChannel {
|
||||||
inner: unsafe { self.inner.clone_unchecked() },
|
inner: unsafe { self.inner.clone_unchecked() },
|
||||||
channel,
|
channel,
|
||||||
@ -282,7 +282,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch1(&mut self) -> OnePulseChannel<'_, T> {
|
pub fn ch1(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch1)
|
self.channel(Channel::Ch1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 2
|
/// Channel 2
|
||||||
@ -291,7 +291,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch2(&mut self) -> OnePulseChannel<'_, T> {
|
pub fn ch2(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch2)
|
self.channel(Channel::Ch2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 3
|
/// Channel 3
|
||||||
@ -300,7 +300,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch3(&mut self) -> OnePulseChannel<'_, T> {
|
pub fn ch3(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch3)
|
self.channel(Channel::Ch3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 4
|
/// Channel 4
|
||||||
@ -309,7 +309,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch4(&mut self) -> OnePulseChannel<'_, T> {
|
pub fn ch4(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch4)
|
self.channel(Channel::Ch4)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Splits a [`OnePulse`] into four output channels.
|
/// Splits a [`OnePulse`] into four output channels.
|
||||||
@ -328,10 +328,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
OnePulseChannels {
|
OnePulseChannels {
|
||||||
ch1: ch(TimerChannel::Ch1),
|
ch1: ch(Channel::Ch1),
|
||||||
ch2: ch(TimerChannel::Ch2),
|
ch2: ch(Channel::Ch2),
|
||||||
ch3: ch(TimerChannel::Ch3),
|
ch3: ch(Channel::Ch3),
|
||||||
ch4: ch(TimerChannel::Ch4),
|
ch4: ch(Channel::Ch4),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,7 +355,7 @@ pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> {
|
|||||||
/// configuration is shared with all four channels.
|
/// configuration is shared with all four channels.
|
||||||
pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> {
|
pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> {
|
||||||
inner: ManuallyDrop<Timer<'d, T>>,
|
inner: ManuallyDrop<Timer<'d, T>>,
|
||||||
channel: TimerChannel,
|
channel: Channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
|
impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
|
||||||
@ -402,7 +402,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
|
|||||||
|
|
||||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||||
struct OnePulseFuture<T: GeneralInstance4Channel> {
|
struct OnePulseFuture<T: GeneralInstance4Channel> {
|
||||||
channel: TimerChannel,
|
channel: Channel,
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
//! PWM Input driver.
|
//! PWM Input driver.
|
||||||
|
|
||||||
use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource};
|
use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource};
|
||||||
use super::{Ch1, Ch2, GeneralInstance4Channel, TimerChannel, TimerPin};
|
use super::{Ch1, Ch2, GeneralInstance4Channel, Channel, TimerPin};
|
||||||
use crate::gpio::{AfType, Pull};
|
use crate::gpio::{AfType, Pull};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peri;
|
use crate::Peri;
|
||||||
|
|
||||||
/// PWM Input driver.
|
/// PWM Input driver.
|
||||||
pub struct PwmInput<'d, T: GeneralInstance4Channel> {
|
pub struct PwmInput<'d, T: GeneralInstance4Channel> {
|
||||||
channel: TimerChannel,
|
channel: Channel,
|
||||||
inner: Timer<'d, T>,
|
inner: Timer<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,17 +17,17 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
|
|||||||
pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self {
|
pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self {
|
||||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||||
|
|
||||||
Self::new_inner(tim, freq, TimerChannel::Ch1, TimerChannel::Ch2)
|
Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new PWM input driver.
|
/// Create a new PWM input driver.
|
||||||
pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
|
pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
|
||||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||||
|
|
||||||
Self::new_inner(tim, freq, TimerChannel::Ch2, TimerChannel::Ch1)
|
Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: TimerChannel, ch2: TimerChannel) -> Self {
|
fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: Channel, ch2: Channel) -> Self {
|
||||||
let mut inner = Timer::new(tim);
|
let mut inner = Timer::new(tim);
|
||||||
|
|
||||||
inner.set_counting_mode(CountingMode::EdgeAlignedUp);
|
inner.set_counting_mode(CountingMode::EdgeAlignedUp);
|
||||||
@ -44,8 +44,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
|
|||||||
inner.set_input_capture_mode(ch2, InputCaptureMode::Falling);
|
inner.set_input_capture_mode(ch2, InputCaptureMode::Falling);
|
||||||
|
|
||||||
inner.set_trigger_source(match ch1 {
|
inner.set_trigger_source(match ch1 {
|
||||||
TimerChannel::Ch1 => TriggerSource::TI1FP1,
|
Channel::Ch1 => TriggerSource::TI1FP1,
|
||||||
TimerChannel::Ch2 => TriggerSource::TI2FP2,
|
Channel::Ch2 => TriggerSource::TI2FP2,
|
||||||
_ => panic!("Invalid channel for PWM input"),
|
_ => panic!("Invalid channel for PWM input"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -58,19 +58,19 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
|
|||||||
|
|
||||||
/// Enable the given channel.
|
/// Enable the given channel.
|
||||||
pub fn enable(&mut self) {
|
pub fn enable(&mut self) {
|
||||||
self.inner.enable_channel(TimerChannel::Ch1, true);
|
self.inner.enable_channel(Channel::Ch1, true);
|
||||||
self.inner.enable_channel(TimerChannel::Ch2, true);
|
self.inner.enable_channel(Channel::Ch2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable the given channel.
|
/// Disable the given channel.
|
||||||
pub fn disable(&mut self) {
|
pub fn disable(&mut self) {
|
||||||
self.inner.enable_channel(TimerChannel::Ch1, false);
|
self.inner.enable_channel(Channel::Ch1, false);
|
||||||
self.inner.enable_channel(TimerChannel::Ch2, false);
|
self.inner.enable_channel(Channel::Ch2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether given channel is enabled
|
/// Check whether given channel is enabled
|
||||||
pub fn is_enabled(&self) -> bool {
|
pub fn is_enabled(&self) -> bool {
|
||||||
self.inner.get_channel_enable_state(TimerChannel::Ch1)
|
self.inner.get_channel_enable_state(Channel::Ch1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the period tick count
|
/// Get the period tick count
|
||||||
@ -81,8 +81,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
|
|||||||
/// Get the pulse width tick count
|
/// Get the pulse width tick count
|
||||||
pub fn get_width_ticks(&self) -> u32 {
|
pub fn get_width_ticks(&self) -> u32 {
|
||||||
self.inner.get_capture_value(match self.channel {
|
self.inner.get_capture_value(match self.channel {
|
||||||
TimerChannel::Ch1 => TimerChannel::Ch2,
|
Channel::Ch1 => Channel::Ch2,
|
||||||
TimerChannel::Ch2 => TimerChannel::Ch1,
|
Channel::Ch2 => Channel::Ch1,
|
||||||
_ => panic!("Invalid channel for PWM input"),
|
_ => panic!("Invalid channel for PWM input"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use super::low_level::Timer;
|
|||||||
pub use super::{Ch1, Ch2};
|
pub use super::{Ch1, Ch2};
|
||||||
use super::{GeneralInstance4Channel, TimerPin};
|
use super::{GeneralInstance4Channel, TimerPin};
|
||||||
use crate::gpio::{AfType, AnyPin, Pull};
|
use crate::gpio::{AfType, AnyPin, Pull};
|
||||||
use crate::timer::Channel;
|
use crate::timer::TimerChannel;
|
||||||
use crate::Peri;
|
use crate::Peri;
|
||||||
|
|
||||||
/// Counting direction
|
/// Counting direction
|
||||||
@ -39,7 +39,7 @@ impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SealedQeiChannel: Channel {}
|
trait SealedQeiChannel: TimerChannel {}
|
||||||
|
|
||||||
/// Marker trait for a timer channel eligible for use with QEI.
|
/// Marker trait for a timer channel eligible for use with QEI.
|
||||||
#[expect(private_bounds)]
|
#[expect(private_bounds)]
|
||||||
|
@ -4,7 +4,7 @@ use core::marker::PhantomData;
|
|||||||
use core::mem::ManuallyDrop;
|
use core::mem::ManuallyDrop;
|
||||||
|
|
||||||
use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
|
use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
|
||||||
use super::{Ch1, Ch2, Ch3, Ch4, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin};
|
use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin};
|
||||||
#[cfg(gpio_v2)]
|
#[cfg(gpio_v2)]
|
||||||
use crate::gpio::Pull;
|
use crate::gpio::Pull;
|
||||||
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
|
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
|
||||||
@ -34,46 +34,37 @@ pub struct PwmPinConfig {
|
|||||||
pub pull: Pull,
|
pub pull: Pull,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! channel_impl {
|
impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
|
||||||
($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => {
|
/// Create a new PWM pin instance.
|
||||||
impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> {
|
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self {
|
||||||
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
|
critical_section::with(|_| {
|
||||||
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T, $channel>>, output_type: OutputType) -> Self {
|
pin.set_low();
|
||||||
critical_section::with(|_| {
|
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
|
||||||
pin.set_low();
|
});
|
||||||
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
|
PwmPin {
|
||||||
});
|
_pin: pin.into(),
|
||||||
PwmPin {
|
phantom: PhantomData,
|
||||||
_pin: pin.into(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with config.")]
|
|
||||||
pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait<T, $channel>>, pin_config: PwmPinConfig) -> Self {
|
|
||||||
critical_section::with(|_| {
|
|
||||||
pin.set_low();
|
|
||||||
pin.set_as_af(
|
|
||||||
pin.af_num(),
|
|
||||||
#[cfg(gpio_v1)]
|
|
||||||
AfType::output(pin_config.output_type, pin_config.speed),
|
|
||||||
#[cfg(gpio_v2)]
|
|
||||||
AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
PwmPin {
|
|
||||||
_pin: pin.into(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
channel_impl!(new_ch1, new_ch1_with_config, Ch1, TimerPin);
|
/// Create a new PWM pin instance with config.
|
||||||
channel_impl!(new_ch2, new_ch2_with_config, Ch2, TimerPin);
|
pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, pin_config: PwmPinConfig) -> Self {
|
||||||
channel_impl!(new_ch3, new_ch3_with_config, Ch3, TimerPin);
|
critical_section::with(|_| {
|
||||||
channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin);
|
pin.set_low();
|
||||||
|
pin.set_as_af(
|
||||||
|
pin.af_num(),
|
||||||
|
#[cfg(gpio_v1)]
|
||||||
|
AfType::output(pin_config.output_type, pin_config.speed),
|
||||||
|
#[cfg(gpio_v2)]
|
||||||
|
AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
PwmPin {
|
||||||
|
_pin: pin.into(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A single channel of a pwm, obtained from [`SimplePwm::split`],
|
/// A single channel of a pwm, obtained from [`SimplePwm::split`],
|
||||||
/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc.
|
/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc.
|
||||||
@ -82,7 +73,7 @@ channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin);
|
|||||||
/// the frequency configuration is shared with all four channels.
|
/// the frequency configuration is shared with all four channels.
|
||||||
pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> {
|
pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> {
|
||||||
timer: ManuallyDrop<Timer<'d, T>>,
|
timer: ManuallyDrop<Timer<'d, T>>,
|
||||||
channel: TimerChannel,
|
channel: Channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for RMW races
|
// TODO: check for RMW races
|
||||||
@ -207,18 +198,13 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
|
this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
|
||||||
this.inner.start();
|
this.inner.start();
|
||||||
|
|
||||||
[
|
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
|
||||||
TimerChannel::Ch1,
|
.iter()
|
||||||
TimerChannel::Ch2,
|
.for_each(|&channel| {
|
||||||
TimerChannel::Ch3,
|
this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
|
||||||
TimerChannel::Ch4,
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.for_each(|&channel| {
|
|
||||||
this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
|
|
||||||
|
|
||||||
this.inner.set_output_compare_preload(channel, true);
|
this.inner.set_output_compare_preload(channel, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
@ -226,7 +212,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
/// Get a single channel
|
/// Get a single channel
|
||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn channel(&mut self, channel: TimerChannel) -> SimplePwmChannel<'_, T> {
|
pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> {
|
||||||
SimplePwmChannel {
|
SimplePwmChannel {
|
||||||
timer: unsafe { self.inner.clone_unchecked() },
|
timer: unsafe { self.inner.clone_unchecked() },
|
||||||
channel,
|
channel,
|
||||||
@ -239,7 +225,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> {
|
pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch1)
|
self.channel(Channel::Ch1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 2
|
/// Channel 2
|
||||||
@ -248,7 +234,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> {
|
pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch2)
|
self.channel(Channel::Ch2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 3
|
/// Channel 3
|
||||||
@ -257,7 +243,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> {
|
pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch3)
|
self.channel(Channel::Ch3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 4
|
/// Channel 4
|
||||||
@ -266,7 +252,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
///
|
///
|
||||||
/// If you need to use multiple channels, use [`Self::split`].
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> {
|
pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> {
|
||||||
self.channel(TimerChannel::Ch4)
|
self.channel(Channel::Ch4)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Splits a [`SimplePwm`] into four pwm channels.
|
/// Splits a [`SimplePwm`] into four pwm channels.
|
||||||
@ -288,10 +274,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SimplePwmChannels {
|
SimplePwmChannels {
|
||||||
ch1: ch(TimerChannel::Ch1),
|
ch1: ch(Channel::Ch1),
|
||||||
ch2: ch(TimerChannel::Ch2),
|
ch2: ch(Channel::Ch2),
|
||||||
ch3: ch(TimerChannel::Ch3),
|
ch3: ch(Channel::Ch3),
|
||||||
ch4: ch(TimerChannel::Ch4),
|
ch4: ch(Channel::Ch4),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,7 +308,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
///
|
///
|
||||||
/// Note:
|
/// Note:
|
||||||
/// you will need to provide corresponding TIMx_UP DMA channel to use this method.
|
/// you will need to provide corresponding TIMx_UP DMA channel to use this method.
|
||||||
pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: TimerChannel, duty: &[u16]) {
|
pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) {
|
||||||
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
||||||
let req = dma.request();
|
let req = dma.request();
|
||||||
|
|
||||||
@ -405,8 +391,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
pub async fn waveform_up_multi_channel(
|
pub async fn waveform_up_multi_channel(
|
||||||
&mut self,
|
&mut self,
|
||||||
dma: Peri<'_, impl super::UpDma<T>>,
|
dma: Peri<'_, impl super::UpDma<T>>,
|
||||||
starting_channel: TimerChannel,
|
starting_channel: Channel,
|
||||||
ending_channel: TimerChannel,
|
ending_channel: Channel,
|
||||||
duty: &[u16],
|
duty: &[u16],
|
||||||
) {
|
) {
|
||||||
let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32;
|
let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32;
|
||||||
@ -462,106 +448,97 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_waveform_chx {
|
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||||
($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => {
|
/// Generate a sequence of PWM waveform
|
||||||
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
|
||||||
/// Generate a sequence of PWM waveform
|
use crate::pac::timer::vals::Ccds;
|
||||||
pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch<T, $cc_ch>>, duty: &[u16]) {
|
|
||||||
use crate::pac::timer::vals::Ccds;
|
|
||||||
|
|
||||||
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
||||||
let req = dma.request();
|
let req = dma.request();
|
||||||
|
|
||||||
let cc_channel = TimerChannel::$cc_ch;
|
let cc_channel = C::CHANNEL;
|
||||||
|
|
||||||
let original_duty_state = self.channel(cc_channel).current_duty_cycle();
|
let original_duty_state = self.channel(cc_channel).current_duty_cycle();
|
||||||
let original_enable_state = self.channel(cc_channel).is_enabled();
|
let original_enable_state = self.channel(cc_channel).is_enabled();
|
||||||
let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE;
|
let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE;
|
||||||
let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
|
let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
|
||||||
|
|
||||||
// redirect CC DMA request onto Update Event
|
// redirect CC DMA request onto Update Event
|
||||||
if !original_cc_dma_on_update {
|
if !original_cc_dma_on_update {
|
||||||
self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
|
self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
|
||||||
}
|
|
||||||
|
|
||||||
if !original_cc_dma_enabled {
|
|
||||||
self.inner.set_cc_dma_enable_state(cc_channel, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !original_enable_state {
|
|
||||||
self.channel(cc_channel).enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
#[cfg(not(any(bdma, gpdma)))]
|
|
||||||
use crate::dma::{Burst, FifoThreshold};
|
|
||||||
use crate::dma::{Transfer, TransferOptions};
|
|
||||||
|
|
||||||
let dma_transfer_option = TransferOptions {
|
|
||||||
#[cfg(not(any(bdma, gpdma)))]
|
|
||||||
fifo_threshold: Some(FifoThreshold::Full),
|
|
||||||
#[cfg(not(any(bdma, gpdma)))]
|
|
||||||
mburst: Burst::Incr8,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.inner.bits() {
|
|
||||||
TimerBits::Bits16 => {
|
|
||||||
Transfer::new_write(
|
|
||||||
dma,
|
|
||||||
req,
|
|
||||||
duty,
|
|
||||||
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
|
|
||||||
dma_transfer_option,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
#[cfg(not(any(stm32l0)))]
|
|
||||||
TimerBits::Bits32 => {
|
|
||||||
#[cfg(not(any(bdma, gpdma)))]
|
|
||||||
panic!("unsupported timer bits");
|
|
||||||
|
|
||||||
#[cfg(any(bdma, gpdma))]
|
|
||||||
Transfer::new_write(
|
|
||||||
dma,
|
|
||||||
req,
|
|
||||||
duty,
|
|
||||||
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
|
|
||||||
dma_transfer_option,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// restore output compare state
|
|
||||||
if !original_enable_state {
|
|
||||||
self.channel(cc_channel).disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.channel(cc_channel).set_duty_cycle(original_duty_state);
|
|
||||||
|
|
||||||
// Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
|
|
||||||
// this can almost always trigger a DMA FIFO error.
|
|
||||||
//
|
|
||||||
// optional TODO:
|
|
||||||
// clean FEIF after disable UDE
|
|
||||||
if !original_cc_dma_enabled {
|
|
||||||
self.inner.set_cc_dma_enable_state(cc_channel, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !original_cc_dma_on_update {
|
|
||||||
self.inner.set_cc_dma_selection(Ccds::ON_COMPARE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_waveform_chx!(waveform_ch1, Dma, Ch1);
|
if !original_cc_dma_enabled {
|
||||||
impl_waveform_chx!(waveform_ch2, Dma, Ch2);
|
self.inner.set_cc_dma_enable_state(cc_channel, true);
|
||||||
impl_waveform_chx!(waveform_ch3, Dma, Ch3);
|
}
|
||||||
impl_waveform_chx!(waveform_ch4, Dma, Ch4);
|
|
||||||
|
if !original_enable_state {
|
||||||
|
self.channel(cc_channel).enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
#[cfg(not(any(bdma, gpdma)))]
|
||||||
|
use crate::dma::{Burst, FifoThreshold};
|
||||||
|
use crate::dma::{Transfer, TransferOptions};
|
||||||
|
|
||||||
|
let dma_transfer_option = TransferOptions {
|
||||||
|
#[cfg(not(any(bdma, gpdma)))]
|
||||||
|
fifo_threshold: Some(FifoThreshold::Full),
|
||||||
|
#[cfg(not(any(bdma, gpdma)))]
|
||||||
|
mburst: Burst::Incr8,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.inner.bits() {
|
||||||
|
TimerBits::Bits16 => {
|
||||||
|
Transfer::new_write(
|
||||||
|
dma,
|
||||||
|
req,
|
||||||
|
duty,
|
||||||
|
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
|
||||||
|
dma_transfer_option,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
#[cfg(not(any(stm32l0)))]
|
||||||
|
TimerBits::Bits32 => {
|
||||||
|
#[cfg(not(any(bdma, gpdma)))]
|
||||||
|
panic!("unsupported timer bits");
|
||||||
|
|
||||||
|
#[cfg(any(bdma, gpdma))]
|
||||||
|
Transfer::new_write(
|
||||||
|
dma,
|
||||||
|
req,
|
||||||
|
duty,
|
||||||
|
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
|
||||||
|
dma_transfer_option,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// restore output compare state
|
||||||
|
if !original_enable_state {
|
||||||
|
self.channel(cc_channel).disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.channel(cc_channel).set_duty_cycle(original_duty_state);
|
||||||
|
|
||||||
|
// Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
|
||||||
|
// this can almost always trigger a DMA FIFO error.
|
||||||
|
//
|
||||||
|
// optional TODO:
|
||||||
|
// clean FEIF after disable UDE
|
||||||
|
if !original_cc_dma_enabled {
|
||||||
|
self.inner.set_cc_dma_enable_state(cc_channel, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !original_cc_dma_on_update {
|
||||||
|
self.inner.set_cc_dma_selection(Ccds::ON_COMPARE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
|
impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
|
||||||
type Error = core::convert::Infallible;
|
type Error = core::convert::Infallible;
|
||||||
@ -599,7 +576,7 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for Simpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
|
impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
|
||||||
type Channel = TimerChannel;
|
type Channel = Channel;
|
||||||
type Time = Hertz;
|
type Time = Hertz;
|
||||||
type Duty = u32;
|
type Duty = u32;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user