add methods with macro

This commit is contained in:
eZio Pan 2024-02-01 17:10:47 +08:00 committed by Dario Nieuwenhuis
parent 53bf0332e9
commit d538829f2f
5 changed files with 298 additions and 324 deletions

View File

@ -1,6 +1,7 @@
//! PWM driver with complementary output support.
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use embassy_hal_internal::{into_ref, PeripheralRef};
use stm32_metapac::timer::vals::Ckd;
@ -23,7 +24,7 @@ pub struct ComplementaryPwmPin<'d, T, C> {
macro_rules! complementary_channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
impl<'d, T: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> {
impl<'d, T: AdvancedControlInstance> ComplementaryPwmPin<'d, T, $channel> {
#[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
into_ref!(pin);
@ -52,7 +53,7 @@ pub struct ComplementaryPwm<'d, T> {
inner: PeripheralRef<'d, T>,
}
impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
impl<'d, T: AdvancedControlInstance> ComplementaryPwm<'d, T> {
/// Create a new complementary PWM driver.
#[allow(clippy::too_many_arguments)]
pub fn new(
@ -84,27 +85,30 @@ impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstan
this.inner.enable_outputs();
this.inner
.set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1);
this.inner
.set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1);
this.inner
.set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1);
this.inner
.set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1);
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
.iter()
.for_each(|&channel| {
sealed::GeneralPurpose16bitInstance::set_output_compare_mode(
this.inner.deref_mut(),
channel,
OutputCompareMode::PwmMode1,
);
sealed::GeneralPurpose16bitInstance::set_output_compare_preload(this.inner.deref_mut(), channel, true);
});
this
}
/// Enable the given channel.
pub fn enable(&mut self, channel: Channel) {
self.inner.enable_channel(channel, true);
self.inner.enable_complementary_channel(channel, true);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, true);
}
/// Disable the given channel.
pub fn disable(&mut self, channel: Channel) {
self.inner.enable_complementary_channel(channel, false);
self.inner.enable_channel(channel, false);
sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, false);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
}
/// Set PWM frequency.
@ -132,13 +136,13 @@ impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstan
/// 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: Channel, duty: u16) {
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
}
/// Set the output polarity for a given channel.
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);
sealed::GeneralPurpose16bitInstance::set_output_polarity(self.inner.deref_mut(), channel, polarity);
sealed::AdvancedControlInstance::set_complementary_output_polarity(self.inner.deref_mut(), channel, polarity);
}
/// Set the dead time as a proportion of max_duty
@ -150,19 +154,19 @@ impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstan
}
}
impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
impl<'d, T: AdvancedControlInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
type Channel = Channel;
type Time = Hertz;
type Duty = u16;
fn disable(&mut self, channel: Self::Channel) {
self.inner.enable_complementary_channel(channel, false);
self.inner.enable_channel(channel, false);
sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, false);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
}
fn enable(&mut self, channel: Self::Channel) {
self.inner.enable_channel(channel, true);
self.inner.enable_complementary_channel(channel, true);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, true);
}
fn get_period(&self) -> Self::Time {
@ -170,7 +174,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C
}
fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
self.inner.get_compare_value(channel)
sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
}
fn get_max_duty(&self) -> Self::Duty {
@ -179,7 +183,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C
fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
}
fn set_period<P>(&mut self, period: P)

View File

@ -2,8 +2,6 @@
// Timer inheritance
//
// CaptureCompare16bitInstance ComplementaryCaptureCompare16bitInstance
// v v
// Core -------------------------> 1CH -------------------------> 1CH_CMP
// | | ^ |
// +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV
@ -33,6 +31,156 @@ pub mod low_level {
pub(crate) mod sealed {
use super::*;
macro_rules! add_capture_compare_common_methods {
($regs:ident) => {
/// Set input capture filter.
fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) {
let raw_channel = channel.index();
Self::$regs()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_icf(raw_channel % 2, icf));
}
/// Clear input interrupt.
fn clear_input_interrupt(&mut self, channel: Channel) {
Self::$regs().sr().modify(|r| r.set_ccif(channel.index(), false));
}
/// Enable input interrupt.
fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
Self::$regs()
.dier()
.modify(|r| r.set_ccie(channel.index(), enable));
}
/// Set input capture prescaler.
fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
let raw_channel = channel.index();
Self::$regs()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_icpsc(raw_channel % 2, factor));
}
/// Set input TI selection.
fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
let raw_channel = channel.index();
Self::$regs()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
}
/// Set input capture mode.
fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
Self::$regs().ccer().modify(|r| match mode {
InputCaptureMode::Rising => {
r.set_ccnp(channel.index(), false);
r.set_ccp(channel.index(), false);
}
InputCaptureMode::Falling => {
r.set_ccnp(channel.index(), false);
r.set_ccp(channel.index(), true);
}
InputCaptureMode::BothEdges => {
r.set_ccnp(channel.index(), true);
r.set_ccp(channel.index(), true);
}
});
}
/// Set output compare mode.
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
let r = Self::$regs();
let raw_channel: usize = channel.index();
r.ccmr_output(raw_channel / 2)
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
/// Set output polarity.
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
Self::$regs()
.ccer()
.modify(|w| w.set_ccp(channel.index(), polarity.into()));
}
/// Enable/disable a channel.
fn enable_channel(&mut self, channel: Channel, enable: bool) {
Self::$regs()
.ccer()
.modify(|w| w.set_cce(channel.index(), enable));
}
/// Get enable/disable state of a channel
fn get_channel_enable_state(&self, channel: Channel) -> bool {
Self::$regs().ccer().read().cce(channel.index())
}
/// Set compare value for a channel.
fn set_compare_value(&mut self, channel: Channel, value: u16) {
Self::$regs().ccr(channel.index()).modify(|w| w.set_ccr(value));
}
/// Get capture value for a channel.
fn get_capture_value(&mut self, channel: Channel) -> u16 {
Self::$regs().ccr(channel.index()).read().ccr()
}
/// Get compare value for a channel.
fn get_compare_value(&self, channel: Channel) -> u16 {
Self::$regs().ccr(channel.index()).read().ccr()
}
/// Set output compare preload.
fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
let channel_index = channel.index();
Self::regs_1ch()
.ccmr_output(channel_index / 2)
.modify(|w| w.set_ocpe(channel_index % 2, preload));
}
};
}
macro_rules! add_capture_compare_dma_methods {
($regs:ident) => {
/// Get capture compare DMA selection
fn get_cc_dma_selection(&self) -> super::vals::Ccds {
Self::$regs().cr2().read().ccds()
}
/// Set capture compare DMA selection
fn set_cc_dma_selection(&mut self, ccds: super::vals::Ccds) {
Self::$regs().cr2().modify(|w| w.set_ccds(ccds))
}
/// Get capture compare DMA enable state
fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
Self::$regs().dier().read().ccde(channel.index())
}
/// Set capture compare DMA enable state
fn set_cc_dma_enable_state(&mut self, channel: Channel, ccde: bool) {
Self::$regs().dier().modify(|w| w.set_ccde(channel.index(), ccde))
}
};
}
macro_rules! add_complementary_capture_compare_methods {
($regs:ident) => {
/// Set complementary output polarity.
fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
Self::$regs()
.ccer()
.modify(|w| w.set_ccnp(channel.index(), polarity.into()));
}
/// Enable/disable a complementary channel.
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
Self::$regs()
.ccer()
.modify(|w| w.set_ccne(channel.index(), enable));
}
};
}
/// Virtual Core 16-bit timer instance.
pub trait CoreInstance: RccPeripheral {
/// Interrupt for this timer.
@ -171,6 +319,13 @@ pub(crate) mod sealed {
fn set_clock_division(&mut self, ckd: vals::Ckd) {
Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd));
}
/// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
fn get_max_compare_value(&self) -> u16 {
Self::regs_1ch().arr().read().arr()
}
add_capture_compare_common_methods!(regs_1ch);
}
/// Gneral-purpose 1 channel 16-bit timer instance.
@ -182,6 +337,8 @@ pub(crate) mod sealed {
/// for a given set of capabilities, and having it transparently work with
/// more capable timers.
fn regs_2ch() -> crate::pac::timer::Tim2ch;
add_capture_compare_common_methods!(regs_2ch);
}
/// Gneral-purpose 16-bit timer instance.
@ -212,6 +369,9 @@ pub(crate) mod sealed {
let cr1 = Self::regs_gp16().cr1().read();
(cr1.cms(), cr1.dir()).into()
}
add_capture_compare_common_methods!(regs_gp16);
add_capture_compare_dma_methods!(regs_gp16);
}
/// Gneral-purpose 32-bit timer instance.
@ -252,204 +412,7 @@ pub(crate) mod sealed {
timer_f / arr / (psc + 1)
}
}
/// Gneral-purpose 1 channel with one complementary 16-bit timer instance.
pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance {
/// Get access to the general purpose 1 channel with one complementary 16bit timer registers.
///
/// Note: This works even if the timer is more capable, because registers
/// for the less capable timers are a subset. This allows writing a driver
/// for a given set of capabilities, and having it transparently work with
/// more capable timers.
fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp;
/// Enable timer outputs.
fn enable_outputs(&mut self) {
Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true));
}
}
/// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
pub trait GeneralPurpose2ChannelComplementaryInstance:
BasicInstance + GeneralPurpose1ChannelComplementaryInstance
{
/// Get access to the general purpose 2 channel with one complementary 16bit timer registers.
///
/// Note: This works even if the timer is more capable, because registers
/// for the less capable timers are a subset. This allows writing a driver
/// for a given set of capabilities, and having it transparently work with
/// more capable timers.
fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp;
}
/// Advanced control timer instance.
pub trait AdvancedControlInstance:
GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
{
/// Get access to the advanced timer registers.
fn regs_advanced() -> crate::pac::timer::TimAdv;
}
/// Capture/Compare 16-bit timer instance.
pub trait CaptureCompare16bitInstance: GeneralPurpose1ChannelInstance {
/// Set input capture filter.
fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) {
let raw_channel = channel.index();
Self::regs_1ch()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_icf(raw_channel % 2, icf));
}
/// Clear input interrupt.
fn clear_input_interrupt(&mut self, channel: Channel) {
Self::regs_1ch().sr().modify(|r| r.set_ccif(channel.index(), false));
}
/// Enable input interrupt.
fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
Self::regs_1ch().dier().modify(|r| r.set_ccie(channel.index(), enable));
}
/// Set input capture prescaler.
fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
let raw_channel = channel.index();
Self::regs_1ch()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_icpsc(raw_channel % 2, factor));
}
/// Set input TI selection.
fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
let raw_channel = channel.index();
Self::regs_1ch()
.ccmr_input(raw_channel / 2)
.modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
}
/// Set input capture mode.
fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
Self::regs_1ch().ccer().modify(|r| match mode {
InputCaptureMode::Rising => {
r.set_ccnp(channel.index(), false);
r.set_ccp(channel.index(), false);
}
InputCaptureMode::Falling => {
r.set_ccnp(channel.index(), false);
r.set_ccp(channel.index(), true);
}
InputCaptureMode::BothEdges => {
r.set_ccnp(channel.index(), true);
r.set_ccp(channel.index(), true);
}
});
}
/// Set output compare mode.
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
let r = Self::regs_1ch();
let raw_channel: usize = channel.index();
r.ccmr_output(raw_channel / 2)
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
/// Set output polarity.
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
Self::regs_1ch()
.ccer()
.modify(|w| w.set_ccp(channel.index(), polarity.into()));
}
/// Enable/disable a channel.
fn enable_channel(&mut self, channel: Channel, enable: bool) {
Self::regs_1ch().ccer().modify(|w| w.set_cce(channel.index(), enable));
}
/// Get enable/disable state of a channel
fn get_channel_enable_state(&self, channel: Channel) -> bool {
Self::regs_1ch().ccer().read().cce(channel.index())
}
/// Set compare value for a channel.
fn set_compare_value(&mut self, channel: Channel, value: u16) {
Self::regs_1ch().ccr(channel.index()).modify(|w| w.set_ccr(value));
}
/// Get capture value for a channel.
fn get_capture_value(&mut self, channel: Channel) -> u16 {
Self::regs_1ch().ccr(channel.index()).read().ccr()
}
/// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
fn get_max_compare_value(&self) -> u16 {
Self::regs_1ch().arr().read().arr()
}
/// Get compare value for a channel.
fn get_compare_value(&self, channel: Channel) -> u16 {
Self::regs_1ch().ccr(channel.index()).read().ccr()
}
/// Set output compare preload.
fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
let channel_index = channel.index();
Self::regs_1ch()
.ccmr_output(channel_index / 2)
.modify(|w| w.set_ocpe(channel_index % 2, preload));
}
/// Get capture compare DMA selection
fn get_cc_dma_selection(&self) -> super::vals::Ccds {
Self::regs_gp16().cr2().read().ccds()
}
/// Set capture compare DMA selection
fn set_cc_dma_selection(&mut self, ccds: super::vals::Ccds) {
Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds))
}
/// Get capture compare DMA enable state
fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
Self::regs_gp16().dier().read().ccde(channel.index())
}
/// Set capture compare DMA enable state
fn set_cc_dma_enable_state(&mut self, channel: Channel, ccde: bool) {
Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
}
}
/// Capture/Compare 16-bit timer instance with complementary pin support.
pub trait ComplementaryCaptureCompare16bitInstance:
CaptureCompare16bitInstance + GeneralPurpose1ChannelComplementaryInstance
{
/// Set complementary output polarity.
fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
Self::regs_1ch_cmp()
.ccer()
.modify(|w| w.set_ccnp(channel.index(), polarity.into()));
}
/// Set clock divider for the dead time.
fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value));
}
/// Set dead time, as a fraction of the max duty value.
fn set_dead_time_value(&mut self, value: u8) {
Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value));
}
/// Enable/disable a complementary channel.
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
Self::regs_1ch_cmp()
.ccer()
.modify(|w| w.set_ccne(channel.index(), enable));
}
}
/// Capture/Compare 32-bit timer instance.
pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance {
/// Set comapre value for a channel.
fn set_compare_value(&mut self, channel: Channel, value: u32) {
Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value));
@ -470,6 +433,59 @@ pub(crate) mod sealed {
Self::regs_gp32().ccr(channel.index()).read().ccr()
}
}
/// Gneral-purpose 1 channel with one complementary 16-bit timer instance.
pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance {
/// Get access to the general purpose 1 channel with one complementary 16bit timer registers.
///
/// Note: This works even if the timer is more capable, because registers
/// for the less capable timers are a subset. This allows writing a driver
/// for a given set of capabilities, and having it transparently work with
/// more capable timers.
fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp;
/// Set clock divider for the dead time.
fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value));
}
/// Set dead time, as a fraction of the max duty value.
fn set_dead_time_value(&mut self, value: u8) {
Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value));
}
/// Enable timer outputs.
fn enable_outputs(&mut self) {
Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true));
}
add_complementary_capture_compare_methods!(regs_1ch_cmp);
}
/// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
pub trait GeneralPurpose2ChannelComplementaryInstance:
BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance
{
/// Get access to the general purpose 2 channel with one complementary 16bit timer registers.
///
/// Note: This works even if the timer is more capable, because registers
/// for the less capable timers are a subset. This allows writing a driver
/// for a given set of capabilities, and having it transparently work with
/// more capable timers.
fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp;
add_complementary_capture_compare_methods!(regs_2ch_cmp);
}
/// Advanced control timer instance.
pub trait AdvancedControlInstance:
GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
{
/// Get access to the advanced timer registers.
fn regs_advanced() -> crate::pac::timer::TimAdv;
add_complementary_capture_compare_methods!(regs_advanced);
}
}
/// Timer channel.
@ -699,6 +715,7 @@ pub trait GeneralPurpose1ChannelComplementaryInstance:
pub trait GeneralPurpose2ChannelComplementaryInstance:
sealed::GeneralPurpose2ChannelComplementaryInstance
+ BasicInstance
+ GeneralPurpose2ChannelInstance
+ GeneralPurpose1ChannelComplementaryInstance
+ 'static
{
@ -710,42 +727,30 @@ pub trait AdvancedControlInstance:
{
}
/// Capture/Compare 16-bit timer instance.
pub trait CaptureCompare16bitInstance:
sealed::CaptureCompare16bitInstance + GeneralPurpose1ChannelInstance + 'static
{
}
pin_trait!(Channel1Pin, GeneralPurpose1ChannelInstance);
pin_trait!(Channel2Pin, GeneralPurpose2ChannelInstance);
pin_trait!(Channel3Pin, GeneralPurpose16bitInstance);
pin_trait!(Channel4Pin, GeneralPurpose16bitInstance);
/// Capture/Compare 16-bit timer instance with complementary pin support.
pub trait ComplementaryCaptureCompare16bitInstance:
sealed::ComplementaryCaptureCompare16bitInstance
+ CaptureCompare16bitInstance
+ GeneralPurpose1ChannelComplementaryInstance
+ 'static
{
}
#[cfg(not(stm32l0))]
pin_trait!(ExternalTriggerPin, GeneralPurpose16bitInstance);
/// Capture/Compare 32-bit timer instance.
pub trait CaptureCompare32bitInstance:
sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
{
}
#[cfg(stm32l0)]
pin_trait!(ExternalTriggerPin, GeneralPurpose2ChannelInstance);
pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance);
pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
pin_trait!(BreakInputPin, CaptureCompare16bitInstance);
pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance);
pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance);
pin_trait!(Channel1ComplementaryPin, GeneralPurpose1ChannelComplementaryInstance);
pin_trait!(Channel2ComplementaryPin, GeneralPurpose2ChannelComplementaryInstance);
pin_trait!(Channel3ComplementaryPin, AdvancedControlInstance);
pin_trait!(Channel4ComplementaryPin, AdvancedControlInstance);
pin_trait!(BreakInputPin, GeneralPurpose1ChannelComplementaryInstance);
pin_trait!(BreakInput2Pin, GeneralPurpose2ChannelComplementaryInstance);
pin_trait!(BreakInputComparator1Pin, GeneralPurpose1ChannelComplementaryInstance);
pin_trait!(BreakInputComparator2Pin, AdvancedControlInstance);
pin_trait!(BreakInput2Comparator1Pin, AdvancedControlInstance);
pin_trait!(BreakInput2Comparator2Pin, AdvancedControlInstance);
#[allow(unused)]
macro_rules! impl_core_timer {
@ -859,27 +864,6 @@ macro_rules! impl_adv_timer {
};
}
#[allow(unused)]
macro_rules! impl_compare_capable_16bit {
($inst:ident) => {
impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {}
};
}
#[allow(unused)]
macro_rules! impl_compare_capable_32bit {
($inst:ident) => {
impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {}
};
}
#[allow(unused)]
macro_rules! impl_compare_capable_complementary_16bit {
($inst:ident) => {
impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
};
}
foreach_interrupt! {
($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
@ -894,21 +878,17 @@ foreach_interrupt! {
($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
impl_core_timer!($inst, $irq);
impl_1ch_timer!($inst);
impl_compare_capable_16bit!($inst);
impl CoreInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
impl_core_timer!($inst, $irq);
impl_1ch_timer!($inst);
impl_compare_capable_16bit!($inst);
impl_2ch_timer!($inst);
impl CoreInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
};
@ -917,14 +897,12 @@ foreach_interrupt! {
impl_basic_no_cr2_timer!($inst);
impl_basic_timer!($inst);
impl_1ch_timer!($inst);
impl_compare_capable_16bit!($inst);
impl_2ch_timer!($inst);
impl_gp_16bit_timer!($inst);
impl CoreInstance for crate::peripherals::$inst {}
impl BasicNoCr2Instance for crate::peripherals::$inst{}
impl BasicInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
};
@ -934,8 +912,6 @@ foreach_interrupt! {
impl_basic_no_cr2_timer!($inst);
impl_basic_timer!($inst);
impl_1ch_timer!($inst);
impl_compare_capable_16bit!($inst);
impl_compare_capable_32bit!($inst);
impl_2ch_timer!($inst);
impl_gp_16bit_timer!($inst);
impl_gp_32bit_timer!($inst);
@ -943,8 +919,6 @@ foreach_interrupt! {
impl BasicNoCr2Instance for crate::peripherals::$inst{}
impl BasicInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
@ -954,15 +928,11 @@ foreach_interrupt! {
impl_core_timer!($inst, $irq);
impl_basic_no_cr2_timer!($inst);
impl_1ch_timer!($inst);
impl_compare_capable_16bit!($inst);
impl_1ch_cmp_timer!($inst);
impl_compare_capable_complementary_16bit!($inst);
impl CoreInstance for crate::peripherals::$inst {}
impl BasicNoCr2Instance for crate::peripherals::$inst{}
impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
};
@ -971,17 +941,15 @@ foreach_interrupt! {
impl_basic_no_cr2_timer!($inst);
impl_basic_timer!($inst);
impl_1ch_timer!($inst);
impl_compare_capable_16bit!($inst);
impl_2ch_timer!($inst);
impl_1ch_cmp_timer!($inst);
impl_compare_capable_complementary_16bit!($inst);
impl_2ch_cmp_timer!($inst);
impl CoreInstance for crate::peripherals::$inst {}
impl BasicNoCr2Instance for crate::peripherals::$inst{}
impl BasicInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst {}
};
@ -992,10 +960,8 @@ foreach_interrupt! {
impl_basic_timer!($inst);
impl_1ch_timer!($inst);
impl_2ch_timer!($inst);
impl_compare_capable_16bit!($inst);
impl_1ch_cmp_timer!($inst);
impl_gp_16bit_timer!($inst);
impl_compare_capable_complementary_16bit!($inst);
impl_2ch_cmp_timer!($inst);
impl_adv_timer!($inst);
impl CoreInstance for crate::peripherals::$inst {}
@ -1004,9 +970,7 @@ foreach_interrupt! {
impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
impl GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst {}
impl AdvancedControlInstance for crate::peripherals::$inst {}
};
@ -1015,7 +979,7 @@ foreach_interrupt! {
// Update Event trigger DMA for every timer
dma_trait!(UpDma, BasicNoCr2Instance);
dma_trait!(Ch1Dma, CaptureCompare16bitInstance);
dma_trait!(Ch2Dma, CaptureCompare16bitInstance);
dma_trait!(Ch3Dma, CaptureCompare16bitInstance);
dma_trait!(Ch4Dma, CaptureCompare16bitInstance);
dma_trait!(Ch1Dma, GeneralPurpose1ChannelInstance);
dma_trait!(Ch2Dma, GeneralPurpose2ChannelInstance);
dma_trait!(Ch3Dma, GeneralPurpose16bitInstance);
dma_trait!(Ch4Dma, GeneralPurpose16bitInstance);

View File

@ -30,7 +30,7 @@ pub struct QeiPin<'d, T, Channel> {
macro_rules! channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> {
impl<'d, T: GeneralPurpose16bitInstance> QeiPin<'d, T, $channel> {
#[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
into_ref!(pin);
@ -57,7 +57,7 @@ pub struct Qei<'d, T> {
_inner: PeripheralRef<'d, T>,
}
impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> Qei<'d, T> {
impl<'d, T: GeneralPurpose16bitInstance> Qei<'d, T> {
/// Create a new quadrature decoder driver.
pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
Self::new_inner(tim)

View File

@ -1,6 +1,7 @@
//! Simple PWM driver.
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use embassy_hal_internal::{into_ref, PeripheralRef};
@ -30,7 +31,7 @@ pub struct PwmPin<'d, T, C> {
macro_rules! channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> {
impl<'d, T: GeneralPurpose16bitInstance> PwmPin<'d, T, $channel> {
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
into_ref!(pin);
@ -59,7 +60,7 @@ pub struct SimplePwm<'d, T> {
inner: PeripheralRef<'d, T>,
}
impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm<'d, T> {
impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
/// Create a new simple PWM driver.
pub fn new(
tim: impl Peripheral<P = T> + 'd,
@ -87,8 +88,13 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
[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)
sealed::GeneralPurpose16bitInstance::set_output_compare_mode(
this.inner.deref_mut(),
channel,
OutputCompareMode::PwmMode1,
);
sealed::GeneralPurpose16bitInstance::set_output_compare_preload(this.inner.deref_mut(), channel, true);
});
this
@ -96,17 +102,17 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
/// Enable the given channel.
pub fn enable(&mut self, channel: Channel) {
self.inner.enable_channel(channel, true);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
}
/// Disable the given channel.
pub fn disable(&mut self, channel: Channel) {
self.inner.enable_channel(channel, false);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
}
/// Check whether given channel is enabled
pub fn is_enabled(&self, channel: Channel) -> bool {
self.inner.get_channel_enable_state(channel)
sealed::GeneralPurpose16bitInstance::get_channel_enable_state(self.inner.deref(), channel)
}
/// Set PWM frequency.
@ -134,24 +140,24 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
/// 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: Channel, duty: u16) {
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
}
/// Get 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 get_duty(&self, channel: Channel) -> u16 {
self.inner.get_compare_value(channel)
sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
}
/// Set the output polarity for a given channel.
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
self.inner.set_output_polarity(channel, polarity);
sealed::GeneralPurpose16bitInstance::set_output_polarity(self.inner.deref_mut(), channel, polarity);
}
/// Set the output compare mode for a given channel.
pub fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
self.inner.set_output_compare_mode(channel, mode);
sealed::GeneralPurpose16bitInstance::set_output_compare_mode(self.inner.deref_mut(), channel, mode);
}
/// Generate a sequence of PWM waveform
@ -226,7 +232,7 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
macro_rules! impl_waveform_chx {
($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => {
impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
/// Generate a sequence of PWM waveform
///
/// Note:
@ -313,17 +319,17 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2);
impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
impl<'d, T: GeneralPurpose16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
type Channel = Channel;
type Time = Hertz;
type Duty = u16;
fn disable(&mut self, channel: Self::Channel) {
self.inner.enable_channel(channel, false);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
}
fn enable(&mut self, channel: Self::Channel) {
self.inner.enable_channel(channel, true);
sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
}
fn get_period(&self) -> Self::Time {
@ -331,7 +337,7 @@ impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d,
}
fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
self.inner.get_compare_value(channel)
sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
}
fn get_max_duty(&self) -> Self::Duty {
@ -340,7 +346,7 @@ impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d,
fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
}
fn set_period<P>(&mut self, period: P)

View File

@ -56,11 +56,11 @@ async fn main(_spawner: Spawner) {
Timer::after_millis(300).await;
}
}
pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> {
pub struct SimplePwm32<'d, T: GeneralPurpose32bitInstance> {
inner: PeripheralRef<'d, T>,
}
impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
impl<'d, T: GeneralPurpose32bitInstance> SimplePwm32<'d, T> {
pub fn new(
tim: impl Peripheral<P = T> + 'd,
ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd,