mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-22 06:42:32 +00:00
stm32: Remove OptionalPin
The idea behind OptionalPin has a few problems: - you need to impl the signal traits for NoPin which is a bit weird https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L413-L416 - you can pass any combination of set/unset pins, which needs checking at runtime https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L130 The replacement is to do multiple `new` constructors for each combination of pins you want to take.
This commit is contained in:
parent
1d265b73b2
commit
550da471be
@ -3,27 +3,21 @@
|
||||
#[cfg_attr(dac_v1, path = "v1.rs")]
|
||||
#[cfg_attr(dac_v2, path = "v2.rs")]
|
||||
mod _version;
|
||||
use crate::gpio::NoPin;
|
||||
use crate::peripherals;
|
||||
pub use _version::*;
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use crate::gpio::OptionalPin;
|
||||
|
||||
pub trait Instance {
|
||||
fn regs() -> &'static crate::pac::dac::Dac;
|
||||
}
|
||||
|
||||
pub trait DacPin<T: Instance, const C: u8>: OptionalPin {}
|
||||
pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin {}
|
||||
}
|
||||
|
||||
pub trait Instance: sealed::Instance + 'static {}
|
||||
|
||||
pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + 'static {}
|
||||
|
||||
impl<T: Instance, const C: u8> DacPin<T, C> for NoPin {}
|
||||
impl<T: Instance, const C: u8> sealed::DacPin<T, C> for NoPin {}
|
||||
|
||||
crate::pac::peripherals!(
|
||||
(dac, $inst:ident) => {
|
||||
impl crate::dac::sealed::Instance for peripherals::$inst {
|
||||
|
@ -1,33 +1,25 @@
|
||||
use crate::dac::{DacPin, Instance};
|
||||
use crate::gpio::AnyPin;
|
||||
use crate::pac::dac;
|
||||
use core::marker::PhantomData;
|
||||
use embassy::util::Unborrow;
|
||||
use embassy_hal_common::unborrow;
|
||||
|
||||
/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock
|
||||
/// configuration.
|
||||
unsafe fn enable() {
|
||||
#[cfg(rcc_h7)]
|
||||
crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
|
||||
#[cfg(rcc_g0)]
|
||||
crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true));
|
||||
#[cfg(rcc_l4)]
|
||||
crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true));
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
UnconfiguredChannel,
|
||||
InvalidValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Channel {
|
||||
Ch1,
|
||||
Ch2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Ch1Trigger {
|
||||
Tim6,
|
||||
Tim3,
|
||||
@ -52,6 +44,8 @@ impl Ch1Trigger {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Ch2Trigger {
|
||||
Tim6,
|
||||
Tim8,
|
||||
@ -78,46 +72,61 @@ impl Ch2Trigger {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Alignment {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Value {
|
||||
Bit8(u8),
|
||||
Bit12(u16, Alignment),
|
||||
}
|
||||
|
||||
pub struct Dac<'d, T: Instance> {
|
||||
ch1: Option<AnyPin>,
|
||||
ch2: Option<AnyPin>,
|
||||
channels: u8,
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Dac<'d, T> {
|
||||
pub fn new(
|
||||
_peri: impl Unborrow<Target = T> + 'd,
|
||||
ch1: impl Unborrow<Target = impl DacPin<T, 1>>,
|
||||
ch2: impl Unborrow<Target = impl DacPin<T, 2>>,
|
||||
pub fn new_1ch(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
_ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd,
|
||||
) -> Self {
|
||||
unborrow!(ch1, ch2);
|
||||
unborrow!(peri);
|
||||
Self::new_inner(peri, 1)
|
||||
}
|
||||
|
||||
pub fn new_2ch(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
_ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd,
|
||||
_ch2: impl Unborrow<Target = impl DacPin<T, 2>> + 'd,
|
||||
) -> Self {
|
||||
unborrow!(peri);
|
||||
Self::new_inner(peri, 2)
|
||||
}
|
||||
|
||||
fn new_inner(_peri: T, channels: u8) -> Self {
|
||||
unsafe {
|
||||
enable();
|
||||
}
|
||||
// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock
|
||||
// configuration.
|
||||
#[cfg(rcc_h7)]
|
||||
crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
|
||||
#[cfg(rcc_g0)]
|
||||
crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true));
|
||||
#[cfg(rcc_l4)]
|
||||
crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true));
|
||||
|
||||
let ch1 = ch1.degrade_optional();
|
||||
if ch1.is_some() {
|
||||
unsafe {
|
||||
if channels >= 1 {
|
||||
T::regs().cr().modify(|reg| {
|
||||
reg.set_en1(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let ch2 = ch2.degrade_optional();
|
||||
if ch2.is_some() {
|
||||
unsafe {
|
||||
if channels >= 2 {
|
||||
T::regs().cr().modify(|reg| {
|
||||
reg.set_en2(true);
|
||||
});
|
||||
@ -125,41 +134,37 @@ impl<'d, T: Instance> Dac<'d, T> {
|
||||
}
|
||||
|
||||
Self {
|
||||
ch1,
|
||||
ch2,
|
||||
channels,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
|
||||
match ch {
|
||||
Channel::Ch1 => {
|
||||
if self.ch1.is_none() {
|
||||
Err(Error::UnconfiguredChannel)
|
||||
} else {
|
||||
unsafe {
|
||||
T::regs().cr().modify(|reg| {
|
||||
reg.set_en1(on);
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Channel::Ch2 => {
|
||||
if self.ch2.is_none() {
|
||||
Err(Error::UnconfiguredChannel)
|
||||
} else {
|
||||
unsafe {
|
||||
T::regs().cr().modify(|reg| {
|
||||
reg.set_en2(on);
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
/// Check the channel is configured
|
||||
fn check_channel_exists(&self, ch: Channel) -> Result<(), Error> {
|
||||
if ch == Channel::Ch2 && self.channels < 2 {
|
||||
Err(Error::UnconfiguredChannel)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
|
||||
self.check_channel_exists(ch)?;
|
||||
match ch {
|
||||
Channel::Ch1 => unsafe {
|
||||
T::regs().cr().modify(|reg| {
|
||||
reg.set_en1(on);
|
||||
})
|
||||
},
|
||||
Channel::Ch2 => unsafe {
|
||||
T::regs().cr().modify(|reg| {
|
||||
reg.set_en2(on);
|
||||
});
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn enable_channel(&mut self, ch: Channel) -> Result<(), Error> {
|
||||
self.set_channel_enable(ch, true)
|
||||
}
|
||||
@ -169,9 +174,7 @@ impl<'d, T: Instance> Dac<'d, T> {
|
||||
}
|
||||
|
||||
pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> {
|
||||
if self.ch1.is_none() {
|
||||
return Err(Error::UnconfiguredChannel);
|
||||
}
|
||||
self.check_channel_exists(Channel::Ch1)?;
|
||||
unwrap!(self.disable_channel(Channel::Ch1));
|
||||
unsafe {
|
||||
T::regs().cr().modify(|reg| {
|
||||
@ -182,9 +185,7 @@ impl<'d, T: Instance> Dac<'d, T> {
|
||||
}
|
||||
|
||||
pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> {
|
||||
if self.ch2.is_none() {
|
||||
return Err(Error::UnconfiguredChannel);
|
||||
}
|
||||
self.check_channel_exists(Channel::Ch2)?;
|
||||
unwrap!(self.disable_channel(Channel::Ch2));
|
||||
unsafe {
|
||||
T::regs().cr().modify(|reg| {
|
||||
@ -195,32 +196,20 @@ impl<'d, T: Instance> Dac<'d, T> {
|
||||
}
|
||||
|
||||
pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> {
|
||||
self.check_channel_exists(ch)?;
|
||||
match ch {
|
||||
Channel::Ch1 => {
|
||||
if self.ch1.is_none() {
|
||||
Err(Error::UnconfiguredChannel)
|
||||
} else {
|
||||
unsafe {
|
||||
T::regs().swtrigr().write(|reg| {
|
||||
reg.set_swtrig1(true);
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Channel::Ch2 => {
|
||||
if self.ch2.is_none() {
|
||||
Err(Error::UnconfiguredChannel)
|
||||
} else {
|
||||
unsafe {
|
||||
T::regs().swtrigr().write(|reg| {
|
||||
reg.set_swtrig2(true);
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Channel::Ch1 => unsafe {
|
||||
T::regs().swtrigr().write(|reg| {
|
||||
reg.set_swtrig1(true);
|
||||
});
|
||||
},
|
||||
Channel::Ch2 => unsafe {
|
||||
T::regs().swtrigr().write(|reg| {
|
||||
reg.set_swtrig2(true);
|
||||
})
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn trigger_all(&mut self) {
|
||||
@ -233,43 +222,31 @@ impl<'d, T: Instance> Dac<'d, T> {
|
||||
}
|
||||
|
||||
pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> {
|
||||
self.check_channel_exists(Channel::Ch2)?;
|
||||
match ch {
|
||||
Channel::Ch1 => {
|
||||
if self.ch1.is_none() {
|
||||
Err(Error::UnconfiguredChannel)
|
||||
} else {
|
||||
match value {
|
||||
Value::Bit8(v) => unsafe {
|
||||
T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Left) => unsafe {
|
||||
T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Right) => unsafe {
|
||||
T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Channel::Ch2 => {
|
||||
if self.ch2.is_none() {
|
||||
Err(Error::UnconfiguredChannel)
|
||||
} else {
|
||||
match value {
|
||||
Value::Bit8(v) => unsafe {
|
||||
T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Left) => unsafe {
|
||||
T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Right) => unsafe {
|
||||
T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Channel::Ch1 => match value {
|
||||
Value::Bit8(v) => unsafe {
|
||||
T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Left) => unsafe {
|
||||
T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Right) => unsafe {
|
||||
T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
|
||||
},
|
||||
},
|
||||
Channel::Ch2 => match value {
|
||||
Value::Bit8(v) => unsafe {
|
||||
T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Left) => unsafe {
|
||||
T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
|
||||
},
|
||||
Value::Bit12(v, Alignment::Right) => unsafe {
|
||||
T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
|
||||
},
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,15 @@ use embassy::waitqueue::AtomicWaker;
|
||||
use embassy_hal_common::unborrow;
|
||||
use futures::future::poll_fn;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! configure {
|
||||
($($name:ident),*) => {
|
||||
$(
|
||||
unsafe { $name.unborrow() }.configure();
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
/// The level on the VSync pin when the data is not valid on the parallel interface.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum VSyncDataInvalidLevel {
|
||||
@ -50,6 +59,23 @@ pub enum Error {
|
||||
PeripheralError,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Config {
|
||||
pub vsync_level: VSyncDataInvalidLevel,
|
||||
pub hsync_level: HSyncDataInvalidLevel,
|
||||
pub pixclk_polarity: PixelClockPolarity,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
vsync_level: VSyncDataInvalidLevel::High,
|
||||
hsync_level: HSyncDataInvalidLevel::Low,
|
||||
pixclk_polarity: PixelClockPolarity::RisingEdge,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Dcmi<'d, T: Instance, Dma: FrameDma> {
|
||||
inner: T,
|
||||
dma: Dma,
|
||||
@ -61,13 +87,85 @@ where
|
||||
T: Instance,
|
||||
Dma: FrameDma,
|
||||
{
|
||||
pub fn new(
|
||||
pub fn new_8bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
d2: impl Unborrow<Target = impl D2Pin> + 'd,
|
||||
d3: impl Unborrow<Target = impl D3Pin> + 'd,
|
||||
d4: impl Unborrow<Target = impl D4Pin> + 'd,
|
||||
d5: impl Unborrow<Target = impl D5Pin> + 'd,
|
||||
d6: impl Unborrow<Target = impl D6Pin> + 'd,
|
||||
d7: impl Unborrow<Target = impl D7Pin> + 'd,
|
||||
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
|
||||
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7);
|
||||
configure!(v_sync, h_sync, pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, false, 0b00)
|
||||
}
|
||||
pub fn new_10bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
d2: impl Unborrow<Target = impl D2Pin> + 'd,
|
||||
d3: impl Unborrow<Target = impl D3Pin> + 'd,
|
||||
d4: impl Unborrow<Target = impl D4Pin> + 'd,
|
||||
d5: impl Unborrow<Target = impl D5Pin> + 'd,
|
||||
d6: impl Unborrow<Target = impl D6Pin> + 'd,
|
||||
d7: impl Unborrow<Target = impl D7Pin> + 'd,
|
||||
d8: impl Unborrow<Target = impl D8Pin> + 'd,
|
||||
d9: impl Unborrow<Target = impl D9Pin> + 'd,
|
||||
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
|
||||
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
|
||||
configure!(v_sync, h_sync, pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, false, 0b01)
|
||||
}
|
||||
|
||||
pub fn new_12bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
d2: impl Unborrow<Target = impl D2Pin> + 'd,
|
||||
d3: impl Unborrow<Target = impl D3Pin> + 'd,
|
||||
d4: impl Unborrow<Target = impl D4Pin> + 'd,
|
||||
d5: impl Unborrow<Target = impl D5Pin> + 'd,
|
||||
d6: impl Unborrow<Target = impl D6Pin> + 'd,
|
||||
d7: impl Unborrow<Target = impl D7Pin> + 'd,
|
||||
d8: impl Unborrow<Target = impl D8Pin> + 'd,
|
||||
d9: impl Unborrow<Target = impl D9Pin> + 'd,
|
||||
d10: impl Unborrow<Target = impl D10Pin> + 'd,
|
||||
d11: impl Unborrow<Target = impl D11Pin> + 'd,
|
||||
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
|
||||
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
|
||||
configure!(v_sync, h_sync, pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, false, 0b10)
|
||||
}
|
||||
pub fn new_14bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
vsync_level: VSyncDataInvalidLevel,
|
||||
hsync_level: HSyncDataInvalidLevel,
|
||||
pixclk_polarity: PixelClockPolarity,
|
||||
use_embedded_synchronization: bool,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
@ -86,58 +184,132 @@ where
|
||||
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
|
||||
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
|
||||
configure!(v_sync, h_sync, pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, false, 0b11)
|
||||
}
|
||||
|
||||
pub fn new_es_8bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
d2: impl Unborrow<Target = impl D2Pin> + 'd,
|
||||
d3: impl Unborrow<Target = impl D3Pin> + 'd,
|
||||
d4: impl Unborrow<Target = impl D4Pin> + 'd,
|
||||
d5: impl Unborrow<Target = impl D5Pin> + 'd,
|
||||
d6: impl Unborrow<Target = impl D6Pin> + 'd,
|
||||
d7: impl Unborrow<Target = impl D7Pin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7);
|
||||
configure!(pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, true, 0b00)
|
||||
}
|
||||
|
||||
pub fn new_es_10bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
d2: impl Unborrow<Target = impl D2Pin> + 'd,
|
||||
d3: impl Unborrow<Target = impl D3Pin> + 'd,
|
||||
d4: impl Unborrow<Target = impl D4Pin> + 'd,
|
||||
d5: impl Unborrow<Target = impl D5Pin> + 'd,
|
||||
d6: impl Unborrow<Target = impl D6Pin> + 'd,
|
||||
d7: impl Unborrow<Target = impl D7Pin> + 'd,
|
||||
d8: impl Unborrow<Target = impl D8Pin> + 'd,
|
||||
d9: impl Unborrow<Target = impl D9Pin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
|
||||
configure!(pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, true, 0b01)
|
||||
}
|
||||
|
||||
pub fn new_es_12bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
d2: impl Unborrow<Target = impl D2Pin> + 'd,
|
||||
d3: impl Unborrow<Target = impl D3Pin> + 'd,
|
||||
d4: impl Unborrow<Target = impl D4Pin> + 'd,
|
||||
d5: impl Unborrow<Target = impl D5Pin> + 'd,
|
||||
d6: impl Unborrow<Target = impl D6Pin> + 'd,
|
||||
d7: impl Unborrow<Target = impl D7Pin> + 'd,
|
||||
d8: impl Unborrow<Target = impl D8Pin> + 'd,
|
||||
d9: impl Unborrow<Target = impl D9Pin> + 'd,
|
||||
d10: impl Unborrow<Target = impl D10Pin> + 'd,
|
||||
d11: impl Unborrow<Target = impl D11Pin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
|
||||
configure!(pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, true, 0b10)
|
||||
}
|
||||
pub fn new_es_14bit(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
dma: impl Unborrow<Target = Dma> + 'd,
|
||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||
d2: impl Unborrow<Target = impl D2Pin> + 'd,
|
||||
d3: impl Unborrow<Target = impl D3Pin> + 'd,
|
||||
d4: impl Unborrow<Target = impl D4Pin> + 'd,
|
||||
d5: impl Unborrow<Target = impl D5Pin> + 'd,
|
||||
d6: impl Unborrow<Target = impl D6Pin> + 'd,
|
||||
d7: impl Unborrow<Target = impl D7Pin> + 'd,
|
||||
d8: impl Unborrow<Target = impl D8Pin> + 'd,
|
||||
d9: impl Unborrow<Target = impl D9Pin> + 'd,
|
||||
d10: impl Unborrow<Target = impl D10Pin> + 'd,
|
||||
d11: impl Unborrow<Target = impl D11Pin> + 'd,
|
||||
d12: impl Unborrow<Target = impl D12Pin> + 'd,
|
||||
d13: impl Unborrow<Target = impl D13Pin> + 'd,
|
||||
pixclk: impl Unborrow<Target = impl PixClkPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
unborrow!(peri, dma, irq);
|
||||
configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
|
||||
configure!(pixclk);
|
||||
|
||||
Self::new_inner(peri, dma, irq, config, true, 0b11)
|
||||
}
|
||||
|
||||
fn new_inner(
|
||||
peri: T,
|
||||
dma: Dma,
|
||||
irq: T::Interrupt,
|
||||
config: Config,
|
||||
use_embedded_synchronization: bool,
|
||||
edm: u8,
|
||||
) -> Self {
|
||||
T::reset();
|
||||
T::enable();
|
||||
|
||||
unborrow!(
|
||||
peri, dma, irq, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, v_sync,
|
||||
h_sync, pixclk
|
||||
);
|
||||
|
||||
d0.configure();
|
||||
d1.configure();
|
||||
d2.configure();
|
||||
d3.configure();
|
||||
d4.configure();
|
||||
d5.configure();
|
||||
d6.configure();
|
||||
d7.configure();
|
||||
d8.configure();
|
||||
d9.configure();
|
||||
d10.configure();
|
||||
d11.configure();
|
||||
d12.configure();
|
||||
d13.configure();
|
||||
|
||||
v_sync.configure();
|
||||
h_sync.configure();
|
||||
pixclk.configure();
|
||||
|
||||
let edm = match (
|
||||
d8.pin().is_some(),
|
||||
d9.pin().is_some(),
|
||||
d10.pin().is_some(),
|
||||
d11.pin().is_some(),
|
||||
d12.pin().is_some(),
|
||||
d13.pin().is_some(),
|
||||
) {
|
||||
(true, true, true, true, true, true) => 0b11, // 14 bits
|
||||
(true, true, true, true, false, false) => 0b10, // 12 bits
|
||||
(true, true, false, false, false, false) => 0b01, // 10 bits
|
||||
(false, false, false, false, false, false) => 0b00, // 8 bits
|
||||
_ => {
|
||||
panic!("Invalid pin configuration.");
|
||||
}
|
||||
};
|
||||
|
||||
unsafe {
|
||||
peri.regs().cr().modify(|r| {
|
||||
r.set_cm(true); // disable continuous mode (snapshot mode)
|
||||
r.set_ess(use_embedded_synchronization);
|
||||
r.set_pckpol(pixclk_polarity == PixelClockPolarity::RisingEdge);
|
||||
r.set_vspol(vsync_level == VSyncDataInvalidLevel::High);
|
||||
r.set_hspol(hsync_level == HSyncDataInvalidLevel::High);
|
||||
r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge);
|
||||
r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High);
|
||||
r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High);
|
||||
r.set_fcrc(0x00); // capture every frame
|
||||
r.set_edm(edm); // extended data mode
|
||||
});
|
||||
@ -271,14 +443,6 @@ mod sealed {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! optional_pin {
|
||||
($name:ident) => {
|
||||
pub trait $name: crate::gpio::OptionalPin {
|
||||
fn configure(&mut self);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pin!(D0Pin);
|
||||
pin!(D1Pin);
|
||||
pin!(D2Pin);
|
||||
@ -287,15 +451,15 @@ mod sealed {
|
||||
pin!(D5Pin);
|
||||
pin!(D6Pin);
|
||||
pin!(D7Pin);
|
||||
optional_pin!(D8Pin);
|
||||
optional_pin!(D9Pin);
|
||||
optional_pin!(D10Pin);
|
||||
optional_pin!(D11Pin);
|
||||
optional_pin!(D12Pin);
|
||||
optional_pin!(D13Pin);
|
||||
pin!(D8Pin);
|
||||
pin!(D9Pin);
|
||||
pin!(D10Pin);
|
||||
pin!(D11Pin);
|
||||
pin!(D12Pin);
|
||||
pin!(D13Pin);
|
||||
|
||||
optional_pin!(HSyncPin);
|
||||
optional_pin!(VSyncPin);
|
||||
pin!(HSyncPin);
|
||||
pin!(VSyncPin);
|
||||
pin!(PixClkPin);
|
||||
}
|
||||
|
||||
@ -408,24 +572,6 @@ macro_rules! impl_pin {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_no_pin {
|
||||
($signal:ident) => {
|
||||
impl sealed::$signal for crate::gpio::NoPin {
|
||||
fn configure(&mut self) {}
|
||||
}
|
||||
impl $signal for crate::gpio::NoPin {}
|
||||
};
|
||||
}
|
||||
|
||||
impl_no_pin!(D8Pin);
|
||||
impl_no_pin!(D9Pin);
|
||||
impl_no_pin!(D10Pin);
|
||||
impl_no_pin!(D11Pin);
|
||||
impl_no_pin!(D12Pin);
|
||||
impl_no_pin!(D13Pin);
|
||||
impl_no_pin!(HSyncPin);
|
||||
impl_no_pin!(VSyncPin);
|
||||
|
||||
crate::pac::peripheral_pins!(
|
||||
($inst:ident, dcmi, DCMI, $pin:ident, D0, $af:expr) => {
|
||||
impl_pin!($pin, D0Pin, $af);
|
||||
|
@ -544,54 +544,6 @@ impl sealed::Pin for AnyPin {
|
||||
|
||||
// ====================
|
||||
|
||||
pub trait OptionalPin: sealed::OptionalPin + Sized {
|
||||
type Pin: Pin;
|
||||
fn pin(&self) -> Option<&Self::Pin>;
|
||||
fn pin_mut(&mut self) -> Option<&mut Self::Pin>;
|
||||
|
||||
/// Convert from concrete pin type PX_XX to type erased `Option<AnyPin>`.
|
||||
#[inline]
|
||||
fn degrade_optional(mut self) -> Option<AnyPin> {
|
||||
self.pin_mut()
|
||||
.map(|pin| unsafe { core::ptr::read(pin) }.degrade())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Pin> sealed::OptionalPin for T {}
|
||||
impl<T: Pin> OptionalPin for T {
|
||||
type Pin = T;
|
||||
|
||||
#[inline]
|
||||
fn pin(&self) -> Option<&T> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pin_mut(&mut self) -> Option<&mut T> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct NoPin;
|
||||
unsafe_impl_unborrow!(NoPin);
|
||||
impl sealed::OptionalPin for NoPin {}
|
||||
impl OptionalPin for NoPin {
|
||||
type Pin = AnyPin;
|
||||
|
||||
#[inline]
|
||||
fn pin(&self) -> Option<&AnyPin> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pin_mut(&mut self) -> Option<&mut AnyPin> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// ====================
|
||||
|
||||
crate::pac::pins!(
|
||||
($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
|
||||
impl Pin for peripherals::$pin_name {
|
||||
|
@ -248,31 +248,6 @@ crate::pac::interrupts! {
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_pwm_nopin {
|
||||
($inst:ident) => {
|
||||
impl_no_pin!($inst, Channel1Pin);
|
||||
impl_no_pin!($inst, Channel1ComplementaryPin);
|
||||
impl_no_pin!($inst, Channel2Pin);
|
||||
impl_no_pin!($inst, Channel2ComplementaryPin);
|
||||
impl_no_pin!($inst, Channel3Pin);
|
||||
impl_no_pin!($inst, Channel3ComplementaryPin);
|
||||
impl_no_pin!($inst, Channel4Pin);
|
||||
impl_no_pin!($inst, Channel4ComplementaryPin);
|
||||
impl_no_pin!($inst, ExternalTriggerPin);
|
||||
impl_no_pin!($inst, BreakInputPin);
|
||||
impl_no_pin!($inst, BreakInputComparator1Pin);
|
||||
impl_no_pin!($inst, BreakInputComparator2Pin);
|
||||
impl_no_pin!($inst, BreakInput2Pin);
|
||||
impl_no_pin!($inst, BreakInput2Comparator1Pin);
|
||||
impl_no_pin!($inst, BreakInput2Comparator2Pin);
|
||||
};
|
||||
}
|
||||
|
||||
crate::pac::peripherals!(
|
||||
(timer, $inst:ident) => { impl_pwm_nopin!($inst); };
|
||||
);
|
||||
|
||||
crate::pac::peripheral_pins!(
|
||||
($inst:ident, timer, $block:ident, $pin:ident, CH1, $af:expr) => {
|
||||
impl_pin!($inst, Channel1Pin, $pin, $af);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::gpio::OptionalPin;
|
||||
use crate::gpio::Pin;
|
||||
|
||||
#[cfg(feature = "unstable-pac")]
|
||||
pub mod low_level {
|
||||
@ -6,118 +6,106 @@ pub mod low_level {
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use crate::gpio::sealed::OptionalPin;
|
||||
use crate::gpio::sealed::Pin;
|
||||
|
||||
pub trait Channel1Pin<Timer>: OptionalPin {
|
||||
pub trait Channel1Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait Channel1ComplementaryPin<Timer>: OptionalPin {
|
||||
pub trait Channel1ComplementaryPin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
|
||||
pub trait Channel2Pin<Timer>: OptionalPin {
|
||||
pub trait Channel2Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait Channel2ComplementaryPin<Timer>: OptionalPin {
|
||||
pub trait Channel2ComplementaryPin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
|
||||
pub trait Channel3Pin<Timer>: OptionalPin {
|
||||
pub trait Channel3Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait Channel3ComplementaryPin<Timer>: OptionalPin {
|
||||
pub trait Channel3ComplementaryPin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
|
||||
pub trait Channel4Pin<Timer>: OptionalPin {
|
||||
pub trait Channel4Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait Channel4ComplementaryPin<Timer>: OptionalPin {
|
||||
pub trait Channel4ComplementaryPin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
|
||||
pub trait ExternalTriggerPin<Timer>: OptionalPin {
|
||||
pub trait ExternalTriggerPin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
|
||||
pub trait BreakInputPin<Timer>: OptionalPin {
|
||||
pub trait BreakInputPin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait BreakInputComparator1Pin<Timer>: OptionalPin {
|
||||
pub trait BreakInputComparator1Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait BreakInputComparator2Pin<Timer>: OptionalPin {
|
||||
pub trait BreakInputComparator2Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
|
||||
pub trait BreakInput2Pin<Timer>: OptionalPin {
|
||||
pub trait BreakInput2Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait BreakInput2Comparator1Pin<Timer>: OptionalPin {
|
||||
pub trait BreakInput2Comparator1Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
pub trait BreakInput2Comparator2Pin<Timer>: OptionalPin {
|
||||
pub trait BreakInput2Comparator2Pin<Timer>: Pin {
|
||||
unsafe fn configure(&mut self);
|
||||
}
|
||||
}
|
||||
pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + OptionalPin + 'static {}
|
||||
pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + Pin + 'static {}
|
||||
pub trait Channel1ComplementaryPin<Timer>:
|
||||
sealed::Channel1ComplementaryPin<Timer> + OptionalPin + 'static
|
||||
sealed::Channel1ComplementaryPin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
|
||||
pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {}
|
||||
pub trait Channel2ComplementaryPin<Timer>:
|
||||
sealed::Channel2ComplementaryPin<Timer> + OptionalPin + 'static
|
||||
sealed::Channel2ComplementaryPin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
|
||||
pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {}
|
||||
pub trait Channel3ComplementaryPin<Timer>:
|
||||
sealed::Channel3ComplementaryPin<Timer> + OptionalPin + 'static
|
||||
sealed::Channel3ComplementaryPin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
|
||||
pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {}
|
||||
pub trait Channel4ComplementaryPin<Timer>:
|
||||
sealed::Channel4ComplementaryPin<Timer> + OptionalPin + 'static
|
||||
sealed::Channel4ComplementaryPin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
|
||||
pub trait ExternalTriggerPin<Timer>:
|
||||
sealed::ExternalTriggerPin<Timer> + OptionalPin + 'static
|
||||
{
|
||||
}
|
||||
pub trait ExternalTriggerPin<Timer>: sealed::ExternalTriggerPin<Timer> + Pin + 'static {}
|
||||
|
||||
pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + OptionalPin + 'static {}
|
||||
pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + Pin + 'static {}
|
||||
pub trait BreakInputComparator1Pin<Timer>:
|
||||
sealed::BreakInputComparator1Pin<Timer> + OptionalPin + 'static
|
||||
sealed::BreakInputComparator1Pin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
pub trait BreakInputComparator2Pin<Timer>:
|
||||
sealed::BreakInputComparator2Pin<Timer> + OptionalPin + 'static
|
||||
sealed::BreakInputComparator2Pin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
|
||||
pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + OptionalPin + 'static {}
|
||||
pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + Pin + 'static {}
|
||||
pub trait BreakInput2Comparator1Pin<Timer>:
|
||||
sealed::BreakInput2Comparator1Pin<Timer> + OptionalPin + 'static
|
||||
sealed::BreakInput2Comparator1Pin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
pub trait BreakInput2Comparator2Pin<Timer>:
|
||||
sealed::BreakInput2Comparator2Pin<Timer> + OptionalPin + 'static
|
||||
sealed::BreakInput2Comparator2Pin<Timer> + Pin + 'static
|
||||
{
|
||||
}
|
||||
|
||||
macro_rules! impl_no_pin {
|
||||
($timer:ident, $signal:ident) => {
|
||||
impl crate::pwm::pins::sealed::$signal<crate::peripherals::$timer> for crate::gpio::NoPin {
|
||||
unsafe fn configure(&mut self) {}
|
||||
}
|
||||
impl crate::pwm::pins::$signal<crate::peripherals::$timer> for crate::gpio::NoPin {}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_pin {
|
||||
($timer:ident, $signal:ident, $pin:ident, $af:expr) => {
|
||||
|
@ -12,7 +12,46 @@ pub struct SimplePwm<'d, T> {
|
||||
}
|
||||
|
||||
impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> {
|
||||
pub fn new<F: Into<Hertz>>(
|
||||
pub fn new_1ch<F: Into<Hertz>>(
|
||||
tim: impl Unborrow<Target = T> + 'd,
|
||||
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
|
||||
freq: F,
|
||||
) -> Self {
|
||||
unborrow!(ch1);
|
||||
Self::new_inner(tim, freq, move || unsafe {
|
||||
ch1.configure();
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_2ch<F: Into<Hertz>>(
|
||||
tim: impl Unborrow<Target = T> + 'd,
|
||||
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
|
||||
ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
|
||||
freq: F,
|
||||
) -> Self {
|
||||
unborrow!(ch1, ch2);
|
||||
Self::new_inner(tim, freq, move || unsafe {
|
||||
ch1.configure();
|
||||
ch2.configure();
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_3ch<F: Into<Hertz>>(
|
||||
tim: impl Unborrow<Target = T> + 'd,
|
||||
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
|
||||
ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
|
||||
ch3: impl Unborrow<Target = impl Channel3Pin<T>> + 'd,
|
||||
freq: F,
|
||||
) -> Self {
|
||||
unborrow!(ch1, ch2, ch3);
|
||||
Self::new_inner(tim, freq, move || unsafe {
|
||||
ch1.configure();
|
||||
ch2.configure();
|
||||
ch3.configure();
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_4ch<F: Into<Hertz>>(
|
||||
tim: impl Unborrow<Target = T> + 'd,
|
||||
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
|
||||
ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
|
||||
@ -20,17 +59,26 @@ impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> {
|
||||
ch4: impl Unborrow<Target = impl Channel4Pin<T>> + 'd,
|
||||
freq: F,
|
||||
) -> Self {
|
||||
unborrow!(tim, ch1, ch2, ch3, ch4);
|
||||
|
||||
T::enable();
|
||||
<T as crate::rcc::sealed::RccPeripheral>::reset();
|
||||
|
||||
unsafe {
|
||||
unborrow!(ch1, ch2, ch3, ch4);
|
||||
Self::new_inner(tim, freq, move || unsafe {
|
||||
ch1.configure();
|
||||
ch2.configure();
|
||||
ch3.configure();
|
||||
ch4.configure();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn new_inner<F: Into<Hertz>>(
|
||||
tim: impl Unborrow<Target = T> + 'd,
|
||||
freq: F,
|
||||
configure_pins: impl FnOnce(),
|
||||
) -> Self {
|
||||
unborrow!(tim);
|
||||
|
||||
T::enable();
|
||||
<T as crate::rcc::sealed::RccPeripheral>::reset();
|
||||
|
||||
configure_pins();
|
||||
|
||||
let mut this = Self {
|
||||
inner: tim,
|
||||
|
@ -8,8 +8,8 @@ use embassy_hal_common::unborrow;
|
||||
use self::sealed::WordSize;
|
||||
use crate::dma;
|
||||
use crate::dma::NoDma;
|
||||
use crate::gpio::sealed::{AFType, Pin};
|
||||
use crate::gpio::{AnyPin, NoPin, OptionalPin};
|
||||
use crate::gpio::sealed::{AFType, Pin as _};
|
||||
use crate::gpio::{AnyPin, Pin};
|
||||
use crate::pac::spi::{regs, vals};
|
||||
use crate::peripherals;
|
||||
use crate::rcc::RccPeripheral;
|
||||
@ -92,10 +92,116 @@ pub struct Spi<'d, T: Instance, Tx, Rx> {
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
pub fn new<F>(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
|
||||
mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
|
||||
miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
|
||||
txdma: impl Unborrow<Target = Tx> + 'd,
|
||||
rxdma: impl Unborrow<Target = Rx> + 'd,
|
||||
freq: F,
|
||||
config: Config,
|
||||
) -> Self
|
||||
where
|
||||
F: Into<Hertz>,
|
||||
{
|
||||
unborrow!(sck, mosi, miso);
|
||||
unsafe {
|
||||
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
mosi.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
miso.set_as_af(miso.af_num(), AFType::Input);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
miso.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
}
|
||||
|
||||
Self::new_inner(
|
||||
peri,
|
||||
Some(sck.degrade()),
|
||||
Some(mosi.degrade()),
|
||||
Some(miso.degrade()),
|
||||
txdma,
|
||||
rxdma,
|
||||
freq,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_rxonly<F>(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
|
||||
miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
|
||||
txdma: impl Unborrow<Target = Tx> + 'd, // TODO remove
|
||||
rxdma: impl Unborrow<Target = Rx> + 'd,
|
||||
freq: F,
|
||||
config: Config,
|
||||
) -> Self
|
||||
where
|
||||
F: Into<Hertz>,
|
||||
{
|
||||
unborrow!(sck, miso);
|
||||
unsafe {
|
||||
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
miso.set_as_af(miso.af_num(), AFType::Input);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
miso.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
}
|
||||
|
||||
Self::new_inner(
|
||||
peri,
|
||||
Some(sck.degrade()),
|
||||
None,
|
||||
Some(miso.degrade()),
|
||||
txdma,
|
||||
rxdma,
|
||||
freq,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_txonly<F>(
|
||||
peri: impl Unborrow<Target = T> + 'd,
|
||||
sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
|
||||
mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
|
||||
txdma: impl Unborrow<Target = Tx> + 'd,
|
||||
rxdma: impl Unborrow<Target = Rx> + 'd, // TODO remove
|
||||
freq: F,
|
||||
config: Config,
|
||||
) -> Self
|
||||
where
|
||||
F: Into<Hertz>,
|
||||
{
|
||||
unborrow!(sck, mosi);
|
||||
unsafe {
|
||||
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
mosi.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
}
|
||||
|
||||
Self::new_inner(
|
||||
peri,
|
||||
Some(sck.degrade()),
|
||||
Some(mosi.degrade()),
|
||||
None,
|
||||
txdma,
|
||||
rxdma,
|
||||
freq,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
fn new_inner<F>(
|
||||
_peri: impl Unborrow<Target = T> + 'd,
|
||||
sck: impl Unborrow<Target = impl SckPin<T>>,
|
||||
mosi: impl Unborrow<Target = impl MosiPin<T>>,
|
||||
miso: impl Unborrow<Target = impl MisoPin<T>>,
|
||||
sck: Option<AnyPin>,
|
||||
mosi: Option<AnyPin>,
|
||||
miso: Option<AnyPin>,
|
||||
txdma: impl Unborrow<Target = Tx>,
|
||||
rxdma: impl Unborrow<Target = Rx>,
|
||||
freq: F,
|
||||
@ -104,32 +210,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
where
|
||||
F: Into<Hertz>,
|
||||
{
|
||||
unborrow!(sck, mosi, miso, txdma, rxdma);
|
||||
|
||||
let sck_af = sck.af_num();
|
||||
let mosi_af = mosi.af_num();
|
||||
let miso_af = miso.af_num();
|
||||
let sck = sck.degrade_optional();
|
||||
let mosi = mosi.degrade_optional();
|
||||
let miso = miso.degrade_optional();
|
||||
|
||||
unsafe {
|
||||
sck.as_ref().map(|x| {
|
||||
x.set_as_af(sck_af, AFType::OutputPushPull);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
x.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
});
|
||||
mosi.as_ref().map(|x| {
|
||||
x.set_as_af(mosi_af, AFType::OutputPushPull);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
x.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
});
|
||||
miso.as_ref().map(|x| {
|
||||
x.set_as_af(miso_af, AFType::Input);
|
||||
#[cfg(any(spi_v2, spi_v3))]
|
||||
x.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
});
|
||||
}
|
||||
unborrow!(txdma, rxdma);
|
||||
|
||||
let pclk = T::frequency();
|
||||
let br = compute_baud_rate(pclk, freq.into());
|
||||
@ -719,15 +800,15 @@ pub(crate) mod sealed {
|
||||
fn regs() -> &'static crate::pac::spi::Spi;
|
||||
}
|
||||
|
||||
pub trait SckPin<T: Instance>: OptionalPin {
|
||||
pub trait SckPin<T: Instance>: Pin {
|
||||
fn af_num(&self) -> u8;
|
||||
}
|
||||
|
||||
pub trait MosiPin<T: Instance>: OptionalPin {
|
||||
pub trait MosiPin<T: Instance>: Pin {
|
||||
fn af_num(&self) -> u8;
|
||||
}
|
||||
|
||||
pub trait MisoPin<T: Instance>: OptionalPin {
|
||||
pub trait MisoPin<T: Instance>: Pin {
|
||||
fn af_num(&self) -> u8;
|
||||
}
|
||||
|
||||
@ -865,26 +946,6 @@ crate::pac::peripheral_pins!(
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_nopin {
|
||||
($inst:ident, $signal:ident) => {
|
||||
impl $signal<peripherals::$inst> for NoPin {}
|
||||
|
||||
impl sealed::$signal<peripherals::$inst> for NoPin {
|
||||
fn af_num(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
crate::pac::peripherals!(
|
||||
(spi, $inst:ident) => {
|
||||
impl_nopin!($inst, SckPin);
|
||||
impl_nopin!($inst, MosiPin);
|
||||
impl_nopin!($inst, MisoPin);
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_dma {
|
||||
($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => {
|
||||
impl<T> sealed::$signal<peripherals::$inst> for T
|
||||
|
@ -215,11 +215,11 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> {
|
||||
/// clock.
|
||||
pub fn new(
|
||||
peri: impl Unborrow<Target = SUBGHZSPI> + 'd,
|
||||
sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>>,
|
||||
mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>>,
|
||||
miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>>,
|
||||
txdma: impl Unborrow<Target = Tx>,
|
||||
rxdma: impl Unborrow<Target = Rx>,
|
||||
sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>> + 'd,
|
||||
mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>> + 'd,
|
||||
miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>> + 'd,
|
||||
txdma: impl Unborrow<Target = Tx> + 'd,
|
||||
rxdma: impl Unborrow<Target = Rx> + 'd,
|
||||
) -> Self {
|
||||
Self::pulse_radio_reset();
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
mod example_common;
|
||||
use embassy::executor::Spawner;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embassy_stm32::gpio::NoPin;
|
||||
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
|
||||
use embassy_stm32::time::U32Ext;
|
||||
use embassy_stm32::Peripherals;
|
||||
@ -16,7 +15,7 @@ use example_common::*;
|
||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
info!("Hello World!");
|
||||
|
||||
let mut pwm = SimplePwm::new(p.TIM2, p.PA5, NoPin, NoPin, NoPin, 10000.hz());
|
||||
let mut pwm = SimplePwm::new_1ch(p.TIM2, p.PA5, 10000.hz());
|
||||
let max = pwm.get_max_duty();
|
||||
pwm.enable(Channel::Ch1);
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
use embassy::executor::Spawner;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embassy_stm32::dcmi::*;
|
||||
use embassy_stm32::gpio::{Level, NoPin, Output, Speed};
|
||||
use embassy_stm32::dcmi::{self, *};
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::i2c::I2c;
|
||||
use embassy_stm32::interrupt;
|
||||
use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
|
||||
@ -78,31 +78,10 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
);
|
||||
|
||||
let dcmi_irq = interrupt::take!(DCMI);
|
||||
let mut dcmi = Dcmi::new(
|
||||
p.DCMI,
|
||||
p.DMA1_CH0,
|
||||
VSyncDataInvalidLevel::High,
|
||||
HSyncDataInvalidLevel::Low,
|
||||
PixelClockPolarity::RisingEdge,
|
||||
false,
|
||||
dcmi_irq,
|
||||
p.PC6,
|
||||
p.PC7,
|
||||
p.PE0,
|
||||
p.PE1,
|
||||
p.PE4,
|
||||
p.PD3,
|
||||
p.PE5,
|
||||
p.PE6,
|
||||
NoPin,
|
||||
NoPin,
|
||||
NoPin,
|
||||
NoPin,
|
||||
NoPin,
|
||||
NoPin,
|
||||
p.PB7,
|
||||
p.PA4,
|
||||
p.PA6,
|
||||
let config = dcmi::Config::default();
|
||||
let mut dcmi = Dcmi::new_8bit(
|
||||
p.DCMI, p.DMA1_CH0, dcmi_irq, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6,
|
||||
p.PB7, p.PA4, p.PA6, config,
|
||||
);
|
||||
|
||||
defmt::info!("attempting capture");
|
||||
|
@ -5,7 +5,6 @@
|
||||
#[path = "../example_common.rs"]
|
||||
mod example_common;
|
||||
|
||||
use embassy_stm32::gpio::NoPin;
|
||||
use example_common::*;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
@ -17,7 +16,7 @@ fn main() -> ! {
|
||||
|
||||
let p = embassy_stm32::init(config());
|
||||
|
||||
let mut dac = Dac::new(p.DAC1, p.PA4, NoPin);
|
||||
let mut dac = Dac::new_1ch(p.DAC1, p.PA4);
|
||||
|
||||
loop {
|
||||
for v in 0..=255 {
|
||||
|
@ -10,7 +10,6 @@ use embassy::executor::Spawner;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embassy::util::Unborrow;
|
||||
use embassy_hal_common::unborrow;
|
||||
use embassy_stm32::gpio::NoPin;
|
||||
use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode};
|
||||
use embassy_stm32::time::{Hertz, U32Ext};
|
||||
use embassy_stm32::timer::GeneralPurpose32bitInstance;
|
||||
@ -33,7 +32,7 @@ pub fn config() -> Config {
|
||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
info!("Hello World!");
|
||||
|
||||
let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, NoPin, NoPin, NoPin, 10000.hz());
|
||||
let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, p.PA1, p.PA2, p.PA3, 10000.hz());
|
||||
let max = pwm.get_max_duty();
|
||||
pwm.enable(Channel::Ch1);
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
mod example_common;
|
||||
use embassy::executor::Spawner;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embassy_stm32::gpio::NoPin;
|
||||
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
|
||||
use embassy_stm32::time::U32Ext;
|
||||
use embassy_stm32::{Config, Peripherals};
|
||||
@ -28,7 +27,7 @@ pub fn config() -> Config {
|
||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
info!("Hello World!");
|
||||
|
||||
let mut pwm = SimplePwm::new(p.TIM3, p.PA6, NoPin, NoPin, NoPin, 10000.hz());
|
||||
let mut pwm = SimplePwm::new_1ch(p.TIM3, p.PA6, 10000.hz());
|
||||
let max = pwm.get_max_duty();
|
||||
pwm.enable(Channel::Ch1);
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
mod example_common;
|
||||
|
||||
use embassy_stm32::dac::{Channel, Dac, Value};
|
||||
use embassy_stm32::gpio::NoPin;
|
||||
use embassy_stm32::pac;
|
||||
use example_common::*;
|
||||
|
||||
@ -22,7 +21,7 @@ fn main() -> ! {
|
||||
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
let mut dac = Dac::new(p.DAC1, p.PA4, NoPin);
|
||||
let mut dac = Dac::new_1ch(p.DAC1, p.PA4);
|
||||
|
||||
loop {
|
||||
for v in 0..=255 {
|
||||
|
Loading…
Reference in New Issue
Block a user