Merge pull request from ismet55555/pwm-change

Remove Generics from `embassy-rp` `Pwm` struct
This commit is contained in:
Dario Nieuwenhuis 2024-05-21 21:48:21 +00:00 committed by GitHub
commit 9a4c4fe2c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 51 deletions
embassy-rp/src
examples/rp/src/bin

View file

@ -81,24 +81,22 @@ impl From<InputMode> for Divmode {
} }
/// PWM driver. /// PWM driver.
pub struct Pwm<'d, T: Slice> { pub struct Pwm<'d> {
inner: PeripheralRef<'d, T>,
pin_a: Option<PeripheralRef<'d, AnyPin>>, pin_a: Option<PeripheralRef<'d, AnyPin>>,
pin_b: Option<PeripheralRef<'d, AnyPin>>, pin_b: Option<PeripheralRef<'d, AnyPin>>,
slice: usize,
} }
impl<'d, T: Slice> Pwm<'d, T> { impl<'d> Pwm<'d> {
fn new_inner( fn new_inner(
inner: impl Peripheral<P = T> + 'd, slice: usize,
a: Option<PeripheralRef<'d, AnyPin>>, a: Option<PeripheralRef<'d, AnyPin>>,
b: Option<PeripheralRef<'d, AnyPin>>, b: Option<PeripheralRef<'d, AnyPin>>,
b_pull: Pull, b_pull: Pull,
config: Config, config: Config,
divmode: Divmode, divmode: Divmode,
) -> Self { ) -> Self {
into_ref!(inner); let p = pac::PWM.ch(slice);
let p = inner.regs();
p.csr().modify(|w| { p.csr().modify(|w| {
w.set_divmode(divmode); w.set_divmode(divmode);
w.set_en(false); w.set_en(false);
@ -117,51 +115,67 @@ impl<'d, T: Slice> Pwm<'d, T> {
}); });
} }
Self { Self {
inner, // inner: p.into(),
pin_a: a, pin_a: a,
pin_b: b, pin_b: b,
slice,
} }
} }
/// Create PWM driver without any configured pins. /// Create PWM driver without any configured pins.
#[inline] #[inline]
pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self { pub fn new_free<T: Slice>(slice: impl Peripheral<P = T> + 'd, config: Config) -> Self {
Self::new_inner(inner, None, None, Pull::None, config, Divmode::DIV) into_ref!(slice);
Self::new_inner(slice.number(), None, None, Pull::None, config, Divmode::DIV)
} }
/// Create PWM driver with a single 'a' as output. /// Create PWM driver with a single 'a' as output.
#[inline] #[inline]
pub fn new_output_a( pub fn new_output_a<T: Slice>(
inner: impl Peripheral<P = T> + 'd, slice: impl Peripheral<P = T> + 'd,
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd, a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(a); into_ref!(slice, a);
Self::new_inner(inner, Some(a.map_into()), None, Pull::None, config, Divmode::DIV) Self::new_inner(
slice.number(),
Some(a.map_into()),
None,
Pull::None,
config,
Divmode::DIV,
)
} }
/// Create PWM driver with a single 'b' pin as output. /// Create PWM driver with a single 'b' pin as output.
#[inline] #[inline]
pub fn new_output_b( pub fn new_output_b<T: Slice>(
inner: impl Peripheral<P = T> + 'd, slice: impl Peripheral<P = T> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd, b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(b); into_ref!(slice, b);
Self::new_inner(inner, None, Some(b.map_into()), Pull::None, config, Divmode::DIV) Self::new_inner(
slice.number(),
None,
Some(b.map_into()),
Pull::None,
config,
Divmode::DIV,
)
} }
/// Create PWM driver with a 'a' and 'b' pins as output. /// Create PWM driver with a 'a' and 'b' pins as output.
#[inline] #[inline]
pub fn new_output_ab( pub fn new_output_ab<T: Slice>(
inner: impl Peripheral<P = T> + 'd, slice: impl Peripheral<P = T> + 'd,
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd, a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd, b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(a, b); into_ref!(slice, a, b);
Self::new_inner( Self::new_inner(
inner, slice.number(),
Some(a.map_into()), Some(a.map_into()),
Some(b.map_into()), Some(b.map_into()),
Pull::None, Pull::None,
@ -172,30 +186,30 @@ impl<'d, T: Slice> Pwm<'d, T> {
/// Create PWM driver with a single 'b' as input pin. /// Create PWM driver with a single 'b' as input pin.
#[inline] #[inline]
pub fn new_input( pub fn new_input<T: Slice>(
inner: impl Peripheral<P = T> + 'd, slice: impl Peripheral<P = T> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd, b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
b_pull: Pull, b_pull: Pull,
mode: InputMode, mode: InputMode,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(b); into_ref!(slice, b);
Self::new_inner(inner, None, Some(b.map_into()), b_pull, config, mode.into()) Self::new_inner(slice.number(), None, Some(b.map_into()), b_pull, config, mode.into())
} }
/// Create PWM driver with a 'a' and 'b' pins in the desired input mode. /// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
#[inline] #[inline]
pub fn new_output_input( pub fn new_output_input<T: Slice>(
inner: impl Peripheral<P = T> + 'd, slice: impl Peripheral<P = T> + 'd,
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd, a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd, b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
b_pull: Pull, b_pull: Pull,
mode: InputMode, mode: InputMode,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(a, b); into_ref!(slice, a, b);
Self::new_inner( Self::new_inner(
inner, slice.number(),
Some(a.map_into()), Some(a.map_into()),
Some(b.map_into()), Some(b.map_into()),
b_pull, b_pull,
@ -206,7 +220,7 @@ impl<'d, T: Slice> Pwm<'d, T> {
/// Set the PWM config. /// Set the PWM config.
pub fn set_config(&mut self, config: &Config) { pub fn set_config(&mut self, config: &Config) {
Self::configure(self.inner.regs(), config); Self::configure(pac::PWM.ch(self.slice), config);
} }
fn configure(p: pac::pwm::Channel, config: &Config) { fn configure(p: pac::pwm::Channel, config: &Config) {
@ -228,22 +242,22 @@ impl<'d, T: Slice> Pwm<'d, T> {
}); });
} }
/// Advances a slices output phase by one count while it is running /// Advances a slice's output phase by one count while it is running
/// by inserting a pulse into the clock enable. The counter /// by inserting a pulse into the clock enable. The counter
/// will not count faster than once per cycle. /// will not count faster than once per cycle.
#[inline] #[inline]
pub fn phase_advance(&mut self) { pub fn phase_advance(&mut self) {
let p = self.inner.regs(); let p = pac::PWM.ch(self.slice);
p.csr().write_set(|w| w.set_ph_adv(true)); p.csr().write_set(|w| w.set_ph_adv(true));
while p.csr().read().ph_adv() {} while p.csr().read().ph_adv() {}
} }
/// Retards a slices output phase by one count while it is running /// Retards a slice's output phase by one count while it is running
/// by deleting a pulse from the clock enable. The counter will not /// by deleting a pulse from the clock enable. The counter will not
/// count backward when clock enable is permenantly low. /// count backward when clock enable is permanently low.
#[inline] #[inline]
pub fn phase_retard(&mut self) { pub fn phase_retard(&mut self) {
let p = self.inner.regs(); let p = pac::PWM.ch(self.slice);
p.csr().write_set(|w| w.set_ph_ret(true)); p.csr().write_set(|w| w.set_ph_ret(true));
while p.csr().read().ph_ret() {} while p.csr().read().ph_ret() {}
} }
@ -251,13 +265,13 @@ impl<'d, T: Slice> Pwm<'d, T> {
/// Read PWM counter. /// Read PWM counter.
#[inline] #[inline]
pub fn counter(&self) -> u16 { pub fn counter(&self) -> u16 {
self.inner.regs().ctr().read().ctr() pac::PWM.ch(self.slice).ctr().read().ctr()
} }
/// Write PWM counter. /// Write PWM counter.
#[inline] #[inline]
pub fn set_counter(&self, ctr: u16) { pub fn set_counter(&self, ctr: u16) {
self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) pac::PWM.ch(self.slice).ctr().write(|w| w.set_ctr(ctr))
} }
/// Wait for channel interrupt. /// Wait for channel interrupt.
@ -281,7 +295,7 @@ impl<'d, T: Slice> Pwm<'d, T> {
#[inline] #[inline]
fn bit(&self) -> u32 { fn bit(&self) -> u32 {
1 << self.inner.number() as usize 1 << self.slice as usize
} }
} }
@ -291,7 +305,7 @@ pub struct PwmBatch(u32);
impl PwmBatch { impl PwmBatch {
#[inline] #[inline]
/// Enable a PWM slice in this batch. /// Enable a PWM slice in this batch.
pub fn enable(&mut self, pwm: &Pwm<'_, impl Slice>) { pub fn enable(&mut self, pwm: &Pwm<'_>) {
self.0 |= pwm.bit(); self.0 |= pwm.bit();
} }
@ -308,9 +322,9 @@ impl PwmBatch {
} }
} }
impl<'d, T: Slice> Drop for Pwm<'d, T> { impl<'d> Drop for Pwm<'d> {
fn drop(&mut self) { fn drop(&mut self) {
self.inner.regs().csr().write_clear(|w| w.set_en(false)); pac::PWM.ch(self.slice).csr().write_clear(|w| w.set_en(false));
if let Some(pin) = &self.pin_a { if let Some(pin) = &self.pin_a {
pin.gpio().ctrl().write(|w| w.set_funcsel(31)); pin.gpio().ctrl().write(|w| w.set_funcsel(31));
} }
@ -326,19 +340,14 @@ trait SealedSlice {}
#[allow(private_bounds)] #[allow(private_bounds)]
pub trait Slice: Peripheral<P = Self> + SealedSlice + Sized + 'static { pub trait Slice: Peripheral<P = Self> + SealedSlice + Sized + 'static {
/// Slice number. /// Slice number.
fn number(&self) -> u8; fn number(&self) -> usize;
/// Slice register block.
fn regs(&self) -> pac::pwm::Channel {
pac::PWM.ch(self.number() as _)
}
} }
macro_rules! slice { macro_rules! slice {
($name:ident, $num:expr) => { ($name:ident, $num:expr) => {
impl SealedSlice for peripherals::$name {} impl SealedSlice for peripherals::$name {}
impl Slice for peripherals::$name { impl Slice for peripherals::$name {
fn number(&self) -> u8 { fn number(&self) -> usize {
$num $num
} }
} }

View file

@ -15,7 +15,6 @@ use embassy_executor::Spawner;
use embassy_rp::adc::{self, Adc, Blocking}; use embassy_rp::adc::{self, Adc, Blocking};
use embassy_rp::gpio::Pull; use embassy_rp::gpio::Pull;
use embassy_rp::interrupt; use embassy_rp::interrupt;
use embassy_rp::peripherals::PWM_SLICE4;
use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::pwm::{Config, Pwm};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex; use embassy_sync::blocking_mutex::Mutex;
@ -26,7 +25,7 @@ use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
static COUNTER: AtomicU32 = AtomicU32::new(0); static COUNTER: AtomicU32 = AtomicU32::new(0);
static PWM: Mutex<CriticalSectionRawMutex, RefCell<Option<Pwm<PWM_SLICE4>>>> = Mutex::new(RefCell::new(None)); static PWM: Mutex<CriticalSectionRawMutex, RefCell<Option<Pwm>>> = Mutex::new(RefCell::new(None));
static ADC: Mutex<CriticalSectionRawMutex, RefCell<Option<(Adc<Blocking>, adc::Channel)>>> = static ADC: Mutex<CriticalSectionRawMutex, RefCell<Option<(Adc<Blocking>, adc::Channel)>>> =
Mutex::new(RefCell::new(None)); Mutex::new(RefCell::new(None));
static ADC_VALUES: Channel<CriticalSectionRawMutex, u16, 2048> = Channel::new(); static ADC_VALUES: Channel<CriticalSectionRawMutex, u16, 2048> = Channel::new();