mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-27 04:10:25 +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::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::time::Hertz;
|
||||
use crate::timer::low_level::OutputCompareMode;
|
||||
use crate::timer::Channel;
|
||||
use crate::timer::TimerChannel;
|
||||
use crate::Peri;
|
||||
|
||||
/// Complementary PWM pin wrapper.
|
||||
@ -21,7 +21,7 @@ pub struct ComplementaryPwmPin<'d, 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.
|
||||
pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self {
|
||||
critical_section::with(|_| {
|
||||
@ -71,29 +71,24 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
|
||||
|
||||
this.inner.enable_outputs();
|
||||
|
||||
[
|
||||
TimerChannel::Ch1,
|
||||
TimerChannel::Ch2,
|
||||
TimerChannel::Ch3,
|
||||
TimerChannel::Ch4,
|
||||
]
|
||||
.iter()
|
||||
.for_each(|&channel| {
|
||||
this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
|
||||
this.inner.set_output_compare_preload(channel, true);
|
||||
});
|
||||
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
|
||||
.iter()
|
||||
.for_each(|&channel| {
|
||||
this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
|
||||
this.inner.set_output_compare_preload(channel, true);
|
||||
});
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
/// 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_complementary_channel(channel, true);
|
||||
}
|
||||
|
||||
/// 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_channel(channel, false);
|
||||
}
|
||||
@ -121,13 +116,13 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
|
||||
/// 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.
|
||||
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());
|
||||
self.inner.set_compare_value(channel, duty as _)
|
||||
}
|
||||
|
||||
/// 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_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> {
|
||||
type Channel = TimerChannel;
|
||||
type Channel = Channel;
|
||||
type Time = Hertz;
|
||||
type Duty = u16;
|
||||
|
||||
|
@ -6,12 +6,12 @@ use core::pin::Pin;
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
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};
|
||||
use crate::gpio::{AfType, AnyPin, Pull};
|
||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||
use crate::time::Hertz;
|
||||
use crate::timer::Channel;
|
||||
use crate::timer::TimerChannel;
|
||||
use crate::Peri;
|
||||
|
||||
/// Capture pin wrapper.
|
||||
@ -21,7 +21,7 @@ pub struct CapturePin<'d, T, C> {
|
||||
_pin: Peri<'d, AnyPin>,
|
||||
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.
|
||||
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
|
||||
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.
|
||||
pub fn enable(&mut self, channel: TimerChannel) {
|
||||
pub fn enable(&mut self, channel: Channel) {
|
||||
self.inner.enable_channel(channel, true);
|
||||
}
|
||||
|
||||
/// Disable the given channel.
|
||||
pub fn disable(&mut self, channel: TimerChannel) {
|
||||
pub fn disable(&mut self, channel: Channel) {
|
||||
self.inner.enable_channel(channel, false);
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
fn new_future(
|
||||
&self,
|
||||
channel: TimerChannel,
|
||||
mode: InputCaptureMode,
|
||||
tisel: InputTISelection,
|
||||
) -> InputCaptureFuture<T> {
|
||||
fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> {
|
||||
// Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5
|
||||
// or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode
|
||||
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.
|
||||
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)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 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)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 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)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 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)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 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)
|
||||
.await
|
||||
}
|
||||
|
||||
/// 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)
|
||||
.await
|
||||
}
|
||||
@ -162,7 +157,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
|
||||
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
struct InputCaptureFuture<T: GeneralInstance4Channel> {
|
||||
channel: TimerChannel,
|
||||
channel: Channel,
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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();
|
||||
self.regs_gp16()
|
||||
.ccmr_input(raw_channel / 2)
|
||||
@ -511,22 +511,22 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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));
|
||||
}
|
||||
|
||||
/// 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())
|
||||
}
|
||||
|
||||
/// 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));
|
||||
}
|
||||
|
||||
/// 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();
|
||||
self.regs_gp16()
|
||||
.ccmr_input(raw_channel / 2)
|
||||
@ -534,7 +534,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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();
|
||||
self.regs_gp16()
|
||||
.ccmr_input(raw_channel / 2)
|
||||
@ -542,7 +542,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
InputCaptureMode::Rising => {
|
||||
r.set_ccnp(channel.index(), false);
|
||||
@ -560,7 +560,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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();
|
||||
self.regs_gp16()
|
||||
.ccmr_output(raw_channel / 2)
|
||||
@ -568,24 +568,24 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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()
|
||||
.ccer()
|
||||
.modify(|w| w.set_ccp(channel.index(), polarity.into()));
|
||||
}
|
||||
|
||||
/// 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));
|
||||
}
|
||||
|
||||
/// 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())
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
TimerBits::Bits16 => {
|
||||
let value = unwrap!(u16::try_from(value));
|
||||
@ -599,7 +599,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32,
|
||||
#[cfg(not(stm32l0))]
|
||||
@ -608,12 +608,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// 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();
|
||||
self.regs_gp16()
|
||||
.ccmr_output(channel_index / 2)
|
||||
@ -631,12 +631,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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())
|
||||
}
|
||||
|
||||
/// 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))
|
||||
}
|
||||
|
||||
@ -713,14 +713,14 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> {
|
||||
}
|
||||
|
||||
/// 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()
|
||||
.ccer()
|
||||
.modify(|w| w.set_ccnp(channel.index(), polarity.into()));
|
||||
}
|
||||
|
||||
/// 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()
|
||||
.ccer()
|
||||
.modify(|w| w.set_ccne(channel.index(), enable));
|
||||
|
@ -19,7 +19,7 @@ use crate::rcc::RccPeripheral;
|
||||
|
||||
/// Timer channel.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum TimerChannel {
|
||||
pub enum Channel {
|
||||
/// Channel 1.
|
||||
Ch1,
|
||||
/// Channel 2.
|
||||
@ -30,14 +30,14 @@ pub enum TimerChannel {
|
||||
Ch4,
|
||||
}
|
||||
|
||||
impl TimerChannel {
|
||||
impl Channel {
|
||||
/// Get the channel index (0..3)
|
||||
pub fn index(&self) -> usize {
|
||||
match self {
|
||||
TimerChannel::Ch1 => 0,
|
||||
TimerChannel::Ch2 => 1,
|
||||
TimerChannel::Ch3 => 2,
|
||||
TimerChannel::Ch4 => 3,
|
||||
Channel::Ch1 => 0,
|
||||
Channel::Ch2 => 1,
|
||||
Channel::Ch3 => 2,
|
||||
Channel::Ch4 => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,33 +53,33 @@ pub enum Ch4 {}
|
||||
|
||||
/// Timer channel trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait Channel: SealedChannel {
|
||||
pub trait TimerChannel: SealedTimerChannel {
|
||||
/// The runtime channel.
|
||||
const CHANNEL: TimerChannel;
|
||||
const CHANNEL: Channel;
|
||||
}
|
||||
|
||||
trait SealedChannel {}
|
||||
trait SealedTimerChannel {}
|
||||
|
||||
impl Channel for Ch1 {
|
||||
const CHANNEL: TimerChannel = TimerChannel::Ch1;
|
||||
impl TimerChannel for Ch1 {
|
||||
const CHANNEL: Channel = Channel::Ch1;
|
||||
}
|
||||
|
||||
impl Channel for Ch2 {
|
||||
const CHANNEL: TimerChannel = TimerChannel::Ch2;
|
||||
impl TimerChannel for Ch2 {
|
||||
const CHANNEL: Channel = Channel::Ch2;
|
||||
}
|
||||
|
||||
impl Channel for Ch3 {
|
||||
const CHANNEL: TimerChannel = TimerChannel::Ch3;
|
||||
impl TimerChannel for Ch3 {
|
||||
const CHANNEL: Channel = Channel::Ch3;
|
||||
}
|
||||
|
||||
impl Channel for Ch4 {
|
||||
const CHANNEL: TimerChannel = TimerChannel::Ch4;
|
||||
impl TimerChannel for Ch4 {
|
||||
const CHANNEL: Channel = Channel::Ch4;
|
||||
}
|
||||
|
||||
impl SealedChannel for Ch1 {}
|
||||
impl SealedChannel for Ch2 {}
|
||||
impl SealedChannel for Ch3 {}
|
||||
impl SealedChannel for Ch4 {}
|
||||
impl SealedTimerChannel for Ch1 {}
|
||||
impl SealedTimerChannel for Ch2 {}
|
||||
impl SealedTimerChannel for Ch3 {}
|
||||
impl SealedTimerChannel for Ch4 {}
|
||||
|
||||
/// Timer break input.
|
||||
#[derive(Clone, Copy)]
|
||||
@ -223,10 +223,10 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad
|
||||
/// Advanced 16-bit timer with 4 channels instance.
|
||||
pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
|
||||
|
||||
pin_trait!(TimerPin, GeneralInstance4Channel, Channel);
|
||||
pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel);
|
||||
pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
|
||||
|
||||
pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, Channel);
|
||||
pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel);
|
||||
|
||||
pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
|
||||
|
||||
@ -236,7 +236,7 @@ pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput);
|
||||
// Update Event trigger DMA for every timer
|
||||
dma_trait!(UpDma, BasicInstance);
|
||||
|
||||
dma_trait!(Dma, GeneralInstance4Channel, Channel);
|
||||
dma_trait!(Dma, GeneralInstance4Channel, TimerChannel);
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_core_timer {
|
||||
|
@ -9,7 +9,7 @@ use core::task::{Context, Poll};
|
||||
use super::low_level::{
|
||||
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};
|
||||
use crate::gpio::{AfType, AnyPin, Pull};
|
||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||
@ -76,7 +76,7 @@ impl<T, P, C> TimerTriggerPin<T, C> for P
|
||||
where
|
||||
T: GeneralInstance4Channel,
|
||||
P: TimerPin<T, C>,
|
||||
C: super::Channel + TriggerSource,
|
||||
C: super::TimerChannel + TriggerSource,
|
||||
{
|
||||
fn af_num(&self) -> u8 {
|
||||
TimerPin::af_num(self)
|
||||
@ -97,7 +97,7 @@ impl<T, P, C> SealedTimerTriggerPin<T, C> for P
|
||||
where
|
||||
T: GeneralInstance4Channel,
|
||||
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_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
|
||||
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||
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
|
||||
@ -168,10 +168,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
|
||||
this.inner.set_trigger_source(Ts::TI1FP1);
|
||||
this.inner
|
||||
.set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
|
||||
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||
this.inner
|
||||
.set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER);
|
||||
this.inner.set_input_capture_mode(TimerChannel::Ch1, capture_mode);
|
||||
.set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
|
||||
this.inner.set_input_capture_mode(Channel::Ch1, capture_mode);
|
||||
this.new_inner(freq, pulse_end, counting_mode);
|
||||
|
||||
this
|
||||
@ -194,10 +194,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
|
||||
this.inner.set_trigger_source(Ts::TI2FP2);
|
||||
this.inner
|
||||
.set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal);
|
||||
.set_input_ti_selection(Channel::Ch2, InputTISelection::Normal);
|
||||
this.inner
|
||||
.set_input_capture_filter(TimerChannel::Ch2, FilterValue::NO_FILTER);
|
||||
this.inner.set_input_capture_mode(TimerChannel::Ch2, capture_mode);
|
||||
.set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER);
|
||||
this.inner.set_input_capture_mode(Channel::Ch2, capture_mode);
|
||||
this.new_inner(freq, pulse_end, counting_mode);
|
||||
|
||||
this
|
||||
@ -269,7 +269,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
/// Get a single channel
|
||||
///
|
||||
/// 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 {
|
||||
inner: unsafe { self.inner.clone_unchecked() },
|
||||
channel,
|
||||
@ -282,7 +282,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch1(&mut self) -> OnePulseChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch1)
|
||||
self.channel(Channel::Ch1)
|
||||
}
|
||||
|
||||
/// Channel 2
|
||||
@ -291,7 +291,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch2(&mut self) -> OnePulseChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch2)
|
||||
self.channel(Channel::Ch2)
|
||||
}
|
||||
|
||||
/// Channel 3
|
||||
@ -300,7 +300,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch3(&mut self) -> OnePulseChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch3)
|
||||
self.channel(Channel::Ch3)
|
||||
}
|
||||
|
||||
/// Channel 4
|
||||
@ -309,7 +309,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch4(&mut self) -> OnePulseChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch4)
|
||||
self.channel(Channel::Ch4)
|
||||
}
|
||||
|
||||
/// Splits a [`OnePulse`] into four output channels.
|
||||
@ -328,10 +328,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
};
|
||||
|
||||
OnePulseChannels {
|
||||
ch1: ch(TimerChannel::Ch1),
|
||||
ch2: ch(TimerChannel::Ch2),
|
||||
ch3: ch(TimerChannel::Ch3),
|
||||
ch4: ch(TimerChannel::Ch4),
|
||||
ch1: ch(Channel::Ch1),
|
||||
ch2: ch(Channel::Ch2),
|
||||
ch3: ch(Channel::Ch3),
|
||||
ch4: ch(Channel::Ch4),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -355,7 +355,7 @@ pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> {
|
||||
/// configuration is shared with all four channels.
|
||||
pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> {
|
||||
inner: ManuallyDrop<Timer<'d, T>>,
|
||||
channel: TimerChannel,
|
||||
channel: Channel,
|
||||
}
|
||||
|
||||
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"]
|
||||
struct OnePulseFuture<T: GeneralInstance4Channel> {
|
||||
channel: TimerChannel,
|
||||
channel: Channel,
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
//! PWM Input driver.
|
||||
|
||||
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::time::Hertz;
|
||||
use crate::Peri;
|
||||
|
||||
/// PWM Input driver.
|
||||
pub struct PwmInput<'d, T: GeneralInstance4Channel> {
|
||||
channel: TimerChannel,
|
||||
channel: Channel,
|
||||
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 {
|
||||
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.
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
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_trigger_source(match ch1 {
|
||||
TimerChannel::Ch1 => TriggerSource::TI1FP1,
|
||||
TimerChannel::Ch2 => TriggerSource::TI2FP2,
|
||||
Channel::Ch1 => TriggerSource::TI1FP1,
|
||||
Channel::Ch2 => TriggerSource::TI2FP2,
|
||||
_ => panic!("Invalid channel for PWM input"),
|
||||
});
|
||||
|
||||
@ -58,19 +58,19 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
|
||||
|
||||
/// Enable the given channel.
|
||||
pub fn enable(&mut self) {
|
||||
self.inner.enable_channel(TimerChannel::Ch1, true);
|
||||
self.inner.enable_channel(TimerChannel::Ch2, true);
|
||||
self.inner.enable_channel(Channel::Ch1, true);
|
||||
self.inner.enable_channel(Channel::Ch2, true);
|
||||
}
|
||||
|
||||
/// Disable the given channel.
|
||||
pub fn disable(&mut self) {
|
||||
self.inner.enable_channel(TimerChannel::Ch1, false);
|
||||
self.inner.enable_channel(TimerChannel::Ch2, false);
|
||||
self.inner.enable_channel(Channel::Ch1, false);
|
||||
self.inner.enable_channel(Channel::Ch2, false);
|
||||
}
|
||||
|
||||
/// Check whether given channel is enabled
|
||||
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
|
||||
@ -81,8 +81,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
|
||||
/// Get the pulse width tick count
|
||||
pub fn get_width_ticks(&self) -> u32 {
|
||||
self.inner.get_capture_value(match self.channel {
|
||||
TimerChannel::Ch1 => TimerChannel::Ch2,
|
||||
TimerChannel::Ch2 => TimerChannel::Ch1,
|
||||
Channel::Ch1 => Channel::Ch2,
|
||||
Channel::Ch2 => Channel::Ch1,
|
||||
_ => panic!("Invalid channel for PWM input"),
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use super::low_level::Timer;
|
||||
pub use super::{Ch1, Ch2};
|
||||
use super::{GeneralInstance4Channel, TimerPin};
|
||||
use crate::gpio::{AfType, AnyPin, Pull};
|
||||
use crate::timer::Channel;
|
||||
use crate::timer::TimerChannel;
|
||||
use crate::Peri;
|
||||
|
||||
/// 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.
|
||||
#[expect(private_bounds)]
|
||||
|
@ -4,7 +4,7 @@ use core::marker::PhantomData;
|
||||
use core::mem::ManuallyDrop;
|
||||
|
||||
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)]
|
||||
use crate::gpio::Pull;
|
||||
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
|
||||
@ -34,46 +34,37 @@ pub struct PwmPinConfig {
|
||||
pub pull: Pull,
|
||||
}
|
||||
|
||||
macro_rules! channel_impl {
|
||||
($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => {
|
||||
impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> {
|
||||
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
|
||||
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T, $channel>>, output_type: OutputType) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
|
||||
});
|
||||
PwmPin {
|
||||
_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,
|
||||
}
|
||||
}
|
||||
impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
|
||||
/// Create a new PWM pin instance.
|
||||
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
|
||||
});
|
||||
PwmPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
channel_impl!(new_ch1, new_ch1_with_config, Ch1, TimerPin);
|
||||
channel_impl!(new_ch2, new_ch2_with_config, Ch2, TimerPin);
|
||||
channel_impl!(new_ch3, new_ch3_with_config, Ch3, TimerPin);
|
||||
channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin);
|
||||
/// Create a new PWM pin instance with config.
|
||||
pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A single channel of a pwm, obtained from [`SimplePwm::split`],
|
||||
/// [`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.
|
||||
pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> {
|
||||
timer: ManuallyDrop<Timer<'d, T>>,
|
||||
channel: TimerChannel,
|
||||
channel: Channel,
|
||||
}
|
||||
|
||||
// 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.start();
|
||||
|
||||
[
|
||||
TimerChannel::Ch1,
|
||||
TimerChannel::Ch2,
|
||||
TimerChannel::Ch3,
|
||||
TimerChannel::Ch4,
|
||||
]
|
||||
.iter()
|
||||
.for_each(|&channel| {
|
||||
this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
|
||||
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::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
|
||||
}
|
||||
@ -226,7 +212,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
/// Get a single channel
|
||||
///
|
||||
/// 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 {
|
||||
timer: unsafe { self.inner.clone_unchecked() },
|
||||
channel,
|
||||
@ -239,7 +225,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch1)
|
||||
self.channel(Channel::Ch1)
|
||||
}
|
||||
|
||||
/// Channel 2
|
||||
@ -248,7 +234,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch2)
|
||||
self.channel(Channel::Ch2)
|
||||
}
|
||||
|
||||
/// Channel 3
|
||||
@ -257,7 +243,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch3)
|
||||
self.channel(Channel::Ch3)
|
||||
}
|
||||
|
||||
/// Channel 4
|
||||
@ -266,7 +252,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
///
|
||||
/// If you need to use multiple channels, use [`Self::split`].
|
||||
pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> {
|
||||
self.channel(TimerChannel::Ch4)
|
||||
self.channel(Channel::Ch4)
|
||||
}
|
||||
|
||||
/// Splits a [`SimplePwm`] into four pwm channels.
|
||||
@ -288,10 +274,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
};
|
||||
|
||||
SimplePwmChannels {
|
||||
ch1: ch(TimerChannel::Ch1),
|
||||
ch2: ch(TimerChannel::Ch2),
|
||||
ch3: ch(TimerChannel::Ch3),
|
||||
ch4: ch(TimerChannel::Ch4),
|
||||
ch1: ch(Channel::Ch1),
|
||||
ch2: ch(Channel::Ch2),
|
||||
ch3: ch(Channel::Ch3),
|
||||
ch4: ch(Channel::Ch4),
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,7 +308,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
///
|
||||
/// Note:
|
||||
/// 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
|
||||
let req = dma.request();
|
||||
|
||||
@ -405,8 +391,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
pub async fn waveform_up_multi_channel(
|
||||
&mut self,
|
||||
dma: Peri<'_, impl super::UpDma<T>>,
|
||||
starting_channel: TimerChannel,
|
||||
ending_channel: TimerChannel,
|
||||
starting_channel: Channel,
|
||||
ending_channel: Channel,
|
||||
duty: &[u16],
|
||||
) {
|
||||
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 {
|
||||
($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => {
|
||||
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
/// Generate a sequence of PWM waveform
|
||||
pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch<T, $cc_ch>>, duty: &[u16]) {
|
||||
use crate::pac::timer::vals::Ccds;
|
||||
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
/// Generate a sequence of PWM waveform
|
||||
pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
|
||||
use crate::pac::timer::vals::Ccds;
|
||||
|
||||
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
||||
let req = dma.request();
|
||||
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
||||
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_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_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
|
||||
let original_duty_state = self.channel(cc_channel).current_duty_cycle();
|
||||
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_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
|
||||
|
||||
// redirect CC DMA request onto Update Event
|
||||
if !original_cc_dma_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)
|
||||
}
|
||||
}
|
||||
// redirect CC DMA request onto Update Event
|
||||
if !original_cc_dma_on_update {
|
||||
self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_waveform_chx!(waveform_ch1, Dma, Ch1);
|
||||
impl_waveform_chx!(waveform_ch2, Dma, Ch2);
|
||||
impl_waveform_chx!(waveform_ch3, Dma, Ch3);
|
||||
impl_waveform_chx!(waveform_ch4, Dma, Ch4);
|
||||
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<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
|
||||
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> {
|
||||
type Channel = TimerChannel;
|
||||
type Channel = Channel;
|
||||
type Time = Hertz;
|
||||
type Duty = u32;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user