Merge #605
605: stm32: Remove OptionalPin r=Dirbaio a=Dirbaio 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. Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
commit
9d682aa1fa
@ -62,11 +62,11 @@ fn calc_prescs(freq: u32) -> (u8, u8) {
|
|||||||
|
|
||||||
impl<'d, T: Instance> Spi<'d, T> {
|
impl<'d, T: Instance> Spi<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
inner: impl Unborrow<Target = T>,
|
inner: impl Unborrow<Target = T> + 'd,
|
||||||
clk: impl Unborrow<Target = impl ClkPin<T>>,
|
clk: impl Unborrow<Target = impl ClkPin<T>> + 'd,
|
||||||
mosi: impl Unborrow<Target = impl MosiPin<T>>,
|
mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
|
||||||
miso: impl Unborrow<Target = impl MisoPin<T>>,
|
miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
|
||||||
cs: impl Unborrow<Target = impl CsPin<T>>,
|
cs: impl Unborrow<Target = impl CsPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(inner, clk, mosi, miso, cs);
|
unborrow!(inner, clk, mosi, miso, cs);
|
||||||
|
@ -30,11 +30,11 @@ pub struct Uart<'d, T: Instance> {
|
|||||||
|
|
||||||
impl<'d, T: Instance> Uart<'d, T> {
|
impl<'d, T: Instance> Uart<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
inner: impl Unborrow<Target = T>,
|
inner: impl Unborrow<Target = T> + 'd,
|
||||||
tx: impl Unborrow<Target = impl TxPin<T>>,
|
tx: impl Unborrow<Target = impl TxPin<T>> + 'd,
|
||||||
rx: impl Unborrow<Target = impl RxPin<T>>,
|
rx: impl Unborrow<Target = impl RxPin<T>> + 'd,
|
||||||
cts: impl Unborrow<Target = impl CtsPin<T>>,
|
cts: impl Unborrow<Target = impl CtsPin<T>> + 'd,
|
||||||
rts: impl Unborrow<Target = impl RtsPin<T>>,
|
rts: impl Unborrow<Target = impl RtsPin<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(inner, tx, rx, cts, rts);
|
unborrow!(inner, tx, rx, cts, rts);
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::pac::CRC as PAC_CRC;
|
use crate::pac::CRC as PAC_CRC;
|
||||||
use crate::peripherals::CRC;
|
use crate::peripherals::CRC;
|
||||||
use crate::rcc::sealed::RccPeripheral;
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
|
|
||||||
pub struct Crc {
|
pub struct Crc<'d> {
|
||||||
_peripheral: CRC,
|
_peripheral: CRC,
|
||||||
|
_phantom: PhantomData<&'d mut CRC>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crc {
|
impl<'d> Crc<'d> {
|
||||||
/// Instantiates the CRC32 peripheral and initializes it to default values.
|
/// Instantiates the CRC32 peripheral and initializes it to default values.
|
||||||
pub fn new(peripheral: impl Unborrow<Target = CRC>) -> Self {
|
pub fn new(peripheral: impl Unborrow<Target = CRC> + 'd) -> Self {
|
||||||
// Note: enable and reset come from RccPeripheral.
|
// Note: enable and reset come from RccPeripheral.
|
||||||
// enable CRC clock in RCC.
|
// enable CRC clock in RCC.
|
||||||
CRC::enable();
|
CRC::enable();
|
||||||
@ -20,6 +23,7 @@ impl Crc {
|
|||||||
unborrow!(peripheral);
|
unborrow!(peripheral);
|
||||||
let mut instance = Self {
|
let mut instance = Self {
|
||||||
_peripheral: peripheral,
|
_peripheral: peripheral,
|
||||||
|
_phantom: PhantomData,
|
||||||
};
|
};
|
||||||
instance.reset();
|
instance.reset();
|
||||||
instance
|
instance
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::pac::crc::vals;
|
use crate::pac::crc::vals;
|
||||||
use crate::pac::CRC as PAC_CRC;
|
use crate::pac::CRC as PAC_CRC;
|
||||||
use crate::peripherals::CRC;
|
use crate::peripherals::CRC;
|
||||||
@ -5,8 +7,9 @@ use crate::rcc::sealed::RccPeripheral;
|
|||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
|
|
||||||
pub struct Crc {
|
pub struct Crc<'d> {
|
||||||
_peripheral: CRC,
|
_peripheral: CRC,
|
||||||
|
_phantom: PhantomData<&'d mut CRC>,
|
||||||
_config: Config,
|
_config: Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,9 +67,9 @@ pub enum PolySize {
|
|||||||
Width32,
|
Width32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crc {
|
impl<'d> Crc<'d> {
|
||||||
/// Instantiates the CRC32 peripheral and initializes it to default values.
|
/// Instantiates the CRC32 peripheral and initializes it to default values.
|
||||||
pub fn new(peripheral: impl Unborrow<Target = CRC>, config: Config) -> Self {
|
pub fn new(peripheral: impl Unborrow<Target = CRC> + 'd, config: Config) -> Self {
|
||||||
// Note: enable and reset come from RccPeripheral.
|
// Note: enable and reset come from RccPeripheral.
|
||||||
// enable CRC clock in RCC.
|
// enable CRC clock in RCC.
|
||||||
CRC::enable();
|
CRC::enable();
|
||||||
@ -75,6 +78,7 @@ impl Crc {
|
|||||||
unborrow!(peripheral);
|
unborrow!(peripheral);
|
||||||
let mut instance = Self {
|
let mut instance = Self {
|
||||||
_peripheral: peripheral,
|
_peripheral: peripheral,
|
||||||
|
_phantom: PhantomData,
|
||||||
_config: config,
|
_config: config,
|
||||||
};
|
};
|
||||||
CRC::reset();
|
CRC::reset();
|
||||||
|
@ -3,27 +3,21 @@
|
|||||||
#[cfg_attr(dac_v1, path = "v1.rs")]
|
#[cfg_attr(dac_v1, path = "v1.rs")]
|
||||||
#[cfg_attr(dac_v2, path = "v2.rs")]
|
#[cfg_attr(dac_v2, path = "v2.rs")]
|
||||||
mod _version;
|
mod _version;
|
||||||
use crate::gpio::NoPin;
|
|
||||||
use crate::peripherals;
|
use crate::peripherals;
|
||||||
pub use _version::*;
|
pub use _version::*;
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use crate::gpio::OptionalPin;
|
|
||||||
|
|
||||||
pub trait Instance {
|
pub trait Instance {
|
||||||
fn regs() -> &'static crate::pac::dac::Dac;
|
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 Instance: sealed::Instance + 'static {}
|
||||||
|
|
||||||
pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + '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!(
|
crate::pac::peripherals!(
|
||||||
(dac, $inst:ident) => {
|
(dac, $inst:ident) => {
|
||||||
impl crate::dac::sealed::Instance for peripherals::$inst {
|
impl crate::dac::sealed::Instance for peripherals::$inst {
|
||||||
|
@ -1,33 +1,25 @@
|
|||||||
use crate::dac::{DacPin, Instance};
|
use crate::dac::{DacPin, Instance};
|
||||||
use crate::gpio::AnyPin;
|
|
||||||
use crate::pac::dac;
|
use crate::pac::dac;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
|
|
||||||
/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
/// 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)]
|
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
UnconfiguredChannel,
|
UnconfiguredChannel,
|
||||||
InvalidValue,
|
InvalidValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Channel {
|
pub enum Channel {
|
||||||
Ch1,
|
Ch1,
|
||||||
Ch2,
|
Ch2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Ch1Trigger {
|
pub enum Ch1Trigger {
|
||||||
Tim6,
|
Tim6,
|
||||||
Tim3,
|
Tim3,
|
||||||
@ -52,6 +44,8 @@ impl Ch1Trigger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Ch2Trigger {
|
pub enum Ch2Trigger {
|
||||||
Tim6,
|
Tim6,
|
||||||
Tim8,
|
Tim8,
|
||||||
@ -78,46 +72,61 @@ impl Ch2Trigger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Alignment {
|
pub enum Alignment {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Bit8(u8),
|
Bit8(u8),
|
||||||
Bit12(u16, Alignment),
|
Bit12(u16, Alignment),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Dac<'d, T: Instance> {
|
pub struct Dac<'d, T: Instance> {
|
||||||
ch1: Option<AnyPin>,
|
channels: u8,
|
||||||
ch2: Option<AnyPin>,
|
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Dac<'d, T> {
|
impl<'d, T: Instance> Dac<'d, T> {
|
||||||
pub fn new(
|
pub fn new_1ch(
|
||||||
_peri: impl Unborrow<Target = T> + 'd,
|
peri: impl Unborrow<Target = T> + 'd,
|
||||||
ch1: impl Unborrow<Target = impl DacPin<T, 1>>,
|
_ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd,
|
||||||
ch2: impl Unborrow<Target = impl DacPin<T, 2>>,
|
|
||||||
) -> Self {
|
) -> 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 {
|
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 channels >= 1 {
|
||||||
if ch1.is_some() {
|
|
||||||
unsafe {
|
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_en1(true);
|
reg.set_en1(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let ch2 = ch2.degrade_optional();
|
if channels >= 2 {
|
||||||
if ch2.is_some() {
|
|
||||||
unsafe {
|
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_en2(true);
|
reg.set_en2(true);
|
||||||
});
|
});
|
||||||
@ -125,41 +134,37 @@ impl<'d, T: Instance> Dac<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
ch1,
|
channels,
|
||||||
ch2,
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
|
/// Check the channel is configured
|
||||||
match ch {
|
fn check_channel_exists(&self, ch: Channel) -> Result<(), Error> {
|
||||||
Channel::Ch1 => {
|
if ch == Channel::Ch2 && self.channels < 2 {
|
||||||
if self.ch1.is_none() {
|
Err(Error::UnconfiguredChannel)
|
||||||
Err(Error::UnconfiguredChannel)
|
} else {
|
||||||
} else {
|
Ok(())
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
pub fn enable_channel(&mut self, ch: Channel) -> Result<(), Error> {
|
||||||
self.set_channel_enable(ch, true)
|
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> {
|
pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> {
|
||||||
if self.ch1.is_none() {
|
self.check_channel_exists(Channel::Ch1)?;
|
||||||
return Err(Error::UnconfiguredChannel);
|
|
||||||
}
|
|
||||||
unwrap!(self.disable_channel(Channel::Ch1));
|
unwrap!(self.disable_channel(Channel::Ch1));
|
||||||
unsafe {
|
unsafe {
|
||||||
T::regs().cr().modify(|reg| {
|
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> {
|
pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> {
|
||||||
if self.ch2.is_none() {
|
self.check_channel_exists(Channel::Ch2)?;
|
||||||
return Err(Error::UnconfiguredChannel);
|
|
||||||
}
|
|
||||||
unwrap!(self.disable_channel(Channel::Ch2));
|
unwrap!(self.disable_channel(Channel::Ch2));
|
||||||
unsafe {
|
unsafe {
|
||||||
T::regs().cr().modify(|reg| {
|
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> {
|
pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> {
|
||||||
|
self.check_channel_exists(ch)?;
|
||||||
match ch {
|
match ch {
|
||||||
Channel::Ch1 => {
|
Channel::Ch1 => unsafe {
|
||||||
if self.ch1.is_none() {
|
T::regs().swtrigr().write(|reg| {
|
||||||
Err(Error::UnconfiguredChannel)
|
reg.set_swtrig1(true);
|
||||||
} else {
|
});
|
||||||
unsafe {
|
},
|
||||||
T::regs().swtrigr().write(|reg| {
|
Channel::Ch2 => unsafe {
|
||||||
reg.set_swtrig1(true);
|
T::regs().swtrigr().write(|reg| {
|
||||||
});
|
reg.set_swtrig2(true);
|
||||||
}
|
})
|
||||||
Ok(())
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
Channel::Ch2 => {
|
|
||||||
if self.ch2.is_none() {
|
|
||||||
Err(Error::UnconfiguredChannel)
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
T::regs().swtrigr().write(|reg| {
|
|
||||||
reg.set_swtrig2(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trigger_all(&mut self) {
|
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> {
|
pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> {
|
||||||
|
self.check_channel_exists(Channel::Ch2)?;
|
||||||
match ch {
|
match ch {
|
||||||
Channel::Ch1 => {
|
Channel::Ch1 => match value {
|
||||||
if self.ch1.is_none() {
|
Value::Bit8(v) => unsafe {
|
||||||
Err(Error::UnconfiguredChannel)
|
T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v));
|
||||||
} else {
|
},
|
||||||
match value {
|
Value::Bit12(v, Alignment::Left) => unsafe {
|
||||||
Value::Bit8(v) => unsafe {
|
T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
|
||||||
T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v));
|
},
|
||||||
},
|
Value::Bit12(v, Alignment::Right) => unsafe {
|
||||||
Value::Bit12(v, Alignment::Left) => unsafe {
|
T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
|
||||||
T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
|
},
|
||||||
},
|
},
|
||||||
Value::Bit12(v, Alignment::Right) => unsafe {
|
Channel::Ch2 => match value {
|
||||||
T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
|
Value::Bit8(v) => unsafe {
|
||||||
},
|
T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
|
||||||
}
|
},
|
||||||
Ok(())
|
Value::Bit12(v, Alignment::Left) => unsafe {
|
||||||
}
|
T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
|
||||||
}
|
},
|
||||||
Channel::Ch2 => {
|
Value::Bit12(v, Alignment::Right) => unsafe {
|
||||||
if self.ch2.is_none() {
|
T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,15 @@ use embassy::waitqueue::AtomicWaker;
|
|||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
use futures::future::poll_fn;
|
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.
|
/// The level on the VSync pin when the data is not valid on the parallel interface.
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum VSyncDataInvalidLevel {
|
pub enum VSyncDataInvalidLevel {
|
||||||
@ -50,6 +59,23 @@ pub enum Error {
|
|||||||
PeripheralError,
|
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> {
|
pub struct Dcmi<'d, T: Instance, Dma: FrameDma> {
|
||||||
inner: T,
|
inner: T,
|
||||||
dma: Dma,
|
dma: Dma,
|
||||||
@ -61,13 +87,85 @@ where
|
|||||||
T: Instance,
|
T: Instance,
|
||||||
Dma: FrameDma,
|
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,
|
peri: impl Unborrow<Target = T> + 'd,
|
||||||
dma: impl Unborrow<Target = Dma> + '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,
|
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||||
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
d0: impl Unborrow<Target = impl D0Pin> + 'd,
|
||||||
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
d1: impl Unborrow<Target = impl D1Pin> + 'd,
|
||||||
@ -86,58 +184,132 @@ where
|
|||||||
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
|
v_sync: impl Unborrow<Target = impl VSyncPin> + 'd,
|
||||||
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
|
h_sync: impl Unborrow<Target = impl HSyncPin> + 'd,
|
||||||
pixclk: impl Unborrow<Target = impl PixClkPin> + '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 {
|
) -> Self {
|
||||||
T::reset();
|
T::reset();
|
||||||
T::enable();
|
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 {
|
unsafe {
|
||||||
peri.regs().cr().modify(|r| {
|
peri.regs().cr().modify(|r| {
|
||||||
r.set_cm(true); // disable continuous mode (snapshot mode)
|
r.set_cm(true); // disable continuous mode (snapshot mode)
|
||||||
r.set_ess(use_embedded_synchronization);
|
r.set_ess(use_embedded_synchronization);
|
||||||
r.set_pckpol(pixclk_polarity == PixelClockPolarity::RisingEdge);
|
r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge);
|
||||||
r.set_vspol(vsync_level == VSyncDataInvalidLevel::High);
|
r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High);
|
||||||
r.set_hspol(hsync_level == HSyncDataInvalidLevel::High);
|
r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High);
|
||||||
r.set_fcrc(0x00); // capture every frame
|
r.set_fcrc(0x00); // capture every frame
|
||||||
r.set_edm(edm); // extended data mode
|
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!(D0Pin);
|
||||||
pin!(D1Pin);
|
pin!(D1Pin);
|
||||||
pin!(D2Pin);
|
pin!(D2Pin);
|
||||||
@ -287,15 +451,15 @@ mod sealed {
|
|||||||
pin!(D5Pin);
|
pin!(D5Pin);
|
||||||
pin!(D6Pin);
|
pin!(D6Pin);
|
||||||
pin!(D7Pin);
|
pin!(D7Pin);
|
||||||
optional_pin!(D8Pin);
|
pin!(D8Pin);
|
||||||
optional_pin!(D9Pin);
|
pin!(D9Pin);
|
||||||
optional_pin!(D10Pin);
|
pin!(D10Pin);
|
||||||
optional_pin!(D11Pin);
|
pin!(D11Pin);
|
||||||
optional_pin!(D12Pin);
|
pin!(D12Pin);
|
||||||
optional_pin!(D13Pin);
|
pin!(D13Pin);
|
||||||
|
|
||||||
optional_pin!(HSyncPin);
|
pin!(HSyncPin);
|
||||||
optional_pin!(VSyncPin);
|
pin!(VSyncPin);
|
||||||
pin!(PixClkPin);
|
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!(
|
crate::pac::peripheral_pins!(
|
||||||
($inst:ident, dcmi, DCMI, $pin:ident, D0, $af:expr) => {
|
($inst:ident, dcmi, DCMI, $pin:ident, D0, $af:expr) => {
|
||||||
impl_pin!($pin, D0Pin, $af);
|
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!(
|
crate::pac::pins!(
|
||||||
($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
|
($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
|
||||||
impl Pin for peripherals::$pin_name {
|
impl Pin for peripherals::$pin_name {
|
||||||
|
@ -15,8 +15,8 @@ pub struct I2c<'d, T: Instance> {
|
|||||||
impl<'d, T: Instance> I2c<'d, T> {
|
impl<'d, T: Instance> I2c<'d, T> {
|
||||||
pub fn new<F>(
|
pub fn new<F>(
|
||||||
_peri: impl Unborrow<Target = T> + 'd,
|
_peri: impl Unborrow<Target = T> + 'd,
|
||||||
scl: impl Unborrow<Target = impl SclPin<T>>,
|
scl: impl Unborrow<Target = impl SclPin<T>> + 'd,
|
||||||
sda: impl Unborrow<Target = impl SdaPin<T>>,
|
sda: impl Unborrow<Target = impl SdaPin<T>> + 'd,
|
||||||
freq: F,
|
freq: F,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
|
@ -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!(
|
crate::pac::peripheral_pins!(
|
||||||
($inst:ident, timer, $block:ident, $pin:ident, CH1, $af:expr) => {
|
($inst:ident, timer, $block:ident, $pin:ident, CH1, $af:expr) => {
|
||||||
impl_pin!($inst, Channel1Pin, $pin, $af);
|
impl_pin!($inst, Channel1Pin, $pin, $af);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::gpio::OptionalPin;
|
use crate::gpio::Pin;
|
||||||
|
|
||||||
#[cfg(feature = "unstable-pac")]
|
#[cfg(feature = "unstable-pac")]
|
||||||
pub mod low_level {
|
pub mod low_level {
|
||||||
@ -6,118 +6,106 @@ pub mod low_level {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
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);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait Channel1ComplementaryPin<Timer>: OptionalPin {
|
pub trait Channel1ComplementaryPin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Channel2Pin<Timer>: OptionalPin {
|
pub trait Channel2Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait Channel2ComplementaryPin<Timer>: OptionalPin {
|
pub trait Channel2ComplementaryPin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Channel3Pin<Timer>: OptionalPin {
|
pub trait Channel3Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait Channel3ComplementaryPin<Timer>: OptionalPin {
|
pub trait Channel3ComplementaryPin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Channel4Pin<Timer>: OptionalPin {
|
pub trait Channel4Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait Channel4ComplementaryPin<Timer>: OptionalPin {
|
pub trait Channel4ComplementaryPin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExternalTriggerPin<Timer>: OptionalPin {
|
pub trait ExternalTriggerPin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BreakInputPin<Timer>: OptionalPin {
|
pub trait BreakInputPin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait BreakInputComparator1Pin<Timer>: OptionalPin {
|
pub trait BreakInputComparator1Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait BreakInputComparator2Pin<Timer>: OptionalPin {
|
pub trait BreakInputComparator2Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BreakInput2Pin<Timer>: OptionalPin {
|
pub trait BreakInput2Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait BreakInput2Comparator1Pin<Timer>: OptionalPin {
|
pub trait BreakInput2Comparator1Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
unsafe fn configure(&mut self);
|
||||||
}
|
}
|
||||||
pub trait BreakInput2Comparator2Pin<Timer>: OptionalPin {
|
pub trait BreakInput2Comparator2Pin<Timer>: Pin {
|
||||||
unsafe fn configure(&mut self);
|
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>:
|
pub trait Channel1ComplementaryPin<Timer>:
|
||||||
sealed::Channel1ComplementaryPin<Timer> + OptionalPin + 'static
|
sealed::Channel1ComplementaryPin<Timer> + Pin + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {}
|
pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {}
|
||||||
pub trait Channel2ComplementaryPin<Timer>:
|
pub trait Channel2ComplementaryPin<Timer>:
|
||||||
sealed::Channel2ComplementaryPin<Timer> + OptionalPin + 'static
|
sealed::Channel2ComplementaryPin<Timer> + Pin + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {}
|
pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {}
|
||||||
pub trait Channel3ComplementaryPin<Timer>:
|
pub trait Channel3ComplementaryPin<Timer>:
|
||||||
sealed::Channel3ComplementaryPin<Timer> + OptionalPin + 'static
|
sealed::Channel3ComplementaryPin<Timer> + Pin + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {}
|
pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {}
|
||||||
pub trait Channel4ComplementaryPin<Timer>:
|
pub trait Channel4ComplementaryPin<Timer>:
|
||||||
sealed::Channel4ComplementaryPin<Timer> + OptionalPin + 'static
|
sealed::Channel4ComplementaryPin<Timer> + Pin + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExternalTriggerPin<Timer>:
|
pub trait ExternalTriggerPin<Timer>: sealed::ExternalTriggerPin<Timer> + Pin + 'static {}
|
||||||
sealed::ExternalTriggerPin<Timer> + OptionalPin + 'static
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + OptionalPin + 'static {}
|
pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + Pin + 'static {}
|
||||||
pub trait BreakInputComparator1Pin<Timer>:
|
pub trait BreakInputComparator1Pin<Timer>:
|
||||||
sealed::BreakInputComparator1Pin<Timer> + OptionalPin + 'static
|
sealed::BreakInputComparator1Pin<Timer> + Pin + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
pub trait BreakInputComparator2Pin<Timer>:
|
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>:
|
pub trait BreakInput2Comparator1Pin<Timer>:
|
||||||
sealed::BreakInput2Comparator1Pin<Timer> + OptionalPin + 'static
|
sealed::BreakInput2Comparator1Pin<Timer> + Pin + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
pub trait BreakInput2Comparator2Pin<Timer>:
|
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)]
|
#[allow(unused)]
|
||||||
macro_rules! impl_pin {
|
macro_rules! impl_pin {
|
||||||
($timer:ident, $signal:ident, $pin:ident, $af:expr) => {
|
($timer:ident, $signal:ident, $pin:ident, $af:expr) => {
|
||||||
|
@ -12,7 +12,46 @@ pub struct SimplePwm<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: CaptureCompareCapable16bitInstance> 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,
|
tim: impl Unborrow<Target = T> + 'd,
|
||||||
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
|
ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
|
||||||
ch2: impl Unborrow<Target = impl Channel2Pin<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,
|
ch4: impl Unborrow<Target = impl Channel4Pin<T>> + 'd,
|
||||||
freq: F,
|
freq: F,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(tim, ch1, ch2, ch3, ch4);
|
unborrow!(ch1, ch2, ch3, ch4);
|
||||||
|
Self::new_inner(tim, freq, move || unsafe {
|
||||||
T::enable();
|
|
||||||
<T as crate::rcc::sealed::RccPeripheral>::reset();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
ch1.configure();
|
ch1.configure();
|
||||||
ch2.configure();
|
ch2.configure();
|
||||||
ch3.configure();
|
ch3.configure();
|
||||||
ch4.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 {
|
let mut this = Self {
|
||||||
inner: tim,
|
inner: tim,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy::waitqueue::AtomicWaker;
|
use embassy::waitqueue::AtomicWaker;
|
||||||
@ -18,16 +19,20 @@ pub enum Error {
|
|||||||
ClockError,
|
ClockError,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Rng<T: Instance> {
|
pub struct Rng<'d, T: Instance> {
|
||||||
_inner: T,
|
_inner: T,
|
||||||
|
_phantom: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance> Rng<T> {
|
impl<'d, T: Instance> Rng<'d, T> {
|
||||||
pub fn new(inner: impl Unborrow<Target = T>) -> Self {
|
pub fn new(inner: impl Unborrow<Target = T> + 'd) -> Self {
|
||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
unborrow!(inner);
|
unborrow!(inner);
|
||||||
let mut random = Self { _inner: inner };
|
let mut random = Self {
|
||||||
|
_inner: inner,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
random.reset();
|
random.reset();
|
||||||
random
|
random
|
||||||
}
|
}
|
||||||
@ -88,7 +93,7 @@ impl<T: Instance> Rng<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance> RngCore for Rng<T> {
|
impl<'d, T: Instance> RngCore for Rng<'d, T> {
|
||||||
fn next_u32(&mut self) -> u32 {
|
fn next_u32(&mut self) -> u32 {
|
||||||
loop {
|
loop {
|
||||||
let bits = unsafe { T::regs().sr().read() };
|
let bits = unsafe { T::regs().sr().read() };
|
||||||
@ -119,7 +124,7 @@ impl<T: Instance> RngCore for Rng<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance> CryptoRng for Rng<T> {}
|
impl<'d, T: Instance> CryptoRng for Rng<'d, T> {}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -189,7 +189,7 @@ impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> {
|
|||||||
pub unsafe fn new(
|
pub unsafe fn new(
|
||||||
_peripheral: impl Unborrow<Target = T> + 'd,
|
_peripheral: impl Unborrow<Target = T> + 'd,
|
||||||
pins: impl Unborrow<Target = P> + 'd,
|
pins: impl Unborrow<Target = P> + 'd,
|
||||||
irq: impl Unborrow<Target = T::Interrupt>,
|
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(irq, pins);
|
unborrow!(irq, pins);
|
||||||
|
@ -8,8 +8,8 @@ use embassy_hal_common::unborrow;
|
|||||||
use self::sealed::WordSize;
|
use self::sealed::WordSize;
|
||||||
use crate::dma;
|
use crate::dma;
|
||||||
use crate::dma::NoDma;
|
use crate::dma::NoDma;
|
||||||
use crate::gpio::sealed::{AFType, Pin};
|
use crate::gpio::sealed::{AFType, Pin as _};
|
||||||
use crate::gpio::{AnyPin, NoPin, OptionalPin};
|
use crate::gpio::{AnyPin, Pin};
|
||||||
use crate::pac::spi::{regs, vals};
|
use crate::pac::spi::{regs, vals};
|
||||||
use crate::peripherals;
|
use crate::peripherals;
|
||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
@ -92,45 +92,126 @@ pub struct Spi<'d, T: Instance, Tx, Rx> {
|
|||||||
|
|
||||||
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||||
pub fn new<F>(
|
pub fn new<F>(
|
||||||
_peri: impl Unborrow<Target = T> + 'd,
|
peri: impl Unborrow<Target = T> + 'd,
|
||||||
sck: impl Unborrow<Target = impl SckPin<T>>,
|
sck: impl Unborrow<Target = impl SckPin<T>> + 'd,
|
||||||
mosi: impl Unborrow<Target = impl MosiPin<T>>,
|
mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd,
|
||||||
miso: impl Unborrow<Target = impl MisoPin<T>>,
|
miso: impl Unborrow<Target = impl MisoPin<T>> + 'd,
|
||||||
txdma: impl Unborrow<Target = Tx>,
|
txdma: impl Unborrow<Target = Tx> + 'd,
|
||||||
rxdma: impl Unborrow<Target = Rx>,
|
rxdma: impl Unborrow<Target = Rx> + 'd,
|
||||||
freq: F,
|
freq: F,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
F: Into<Hertz>,
|
F: Into<Hertz>,
|
||||||
{
|
{
|
||||||
unborrow!(sck, mosi, miso, txdma, rxdma);
|
unborrow!(sck, mosi, miso);
|
||||||
|
|
||||||
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 {
|
unsafe {
|
||||||
sck.as_ref().map(|x| {
|
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||||
x.set_as_af(sck_af, AFType::OutputPushPull);
|
#[cfg(any(spi_v2, spi_v3))]
|
||||||
#[cfg(any(spi_v2, spi_v3))]
|
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
x.set_speed(crate::gpio::Speed::VeryHigh);
|
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
|
||||||
});
|
#[cfg(any(spi_v2, spi_v3))]
|
||||||
mosi.as_ref().map(|x| {
|
mosi.set_speed(crate::gpio::Speed::VeryHigh);
|
||||||
x.set_as_af(mosi_af, AFType::OutputPushPull);
|
miso.set_as_af(miso.af_num(), AFType::Input);
|
||||||
#[cfg(any(spi_v2, spi_v3))]
|
#[cfg(any(spi_v2, spi_v3))]
|
||||||
x.set_speed(crate::gpio::Speed::VeryHigh);
|
miso.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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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: Option<AnyPin>,
|
||||||
|
mosi: Option<AnyPin>,
|
||||||
|
miso: Option<AnyPin>,
|
||||||
|
txdma: impl Unborrow<Target = Tx> + 'd,
|
||||||
|
rxdma: impl Unborrow<Target = Rx> + 'd,
|
||||||
|
freq: F,
|
||||||
|
config: Config,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
F: Into<Hertz>,
|
||||||
|
{
|
||||||
|
unborrow!(txdma, rxdma);
|
||||||
|
|
||||||
let pclk = T::frequency();
|
let pclk = T::frequency();
|
||||||
let br = compute_baud_rate(pclk, freq.into());
|
let br = compute_baud_rate(pclk, freq.into());
|
||||||
|
|
||||||
@ -719,15 +800,15 @@ pub(crate) mod sealed {
|
|||||||
fn regs() -> &'static crate::pac::spi::Spi;
|
fn regs() -> &'static crate::pac::spi::Spi;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SckPin<T: Instance>: OptionalPin {
|
pub trait SckPin<T: Instance>: Pin {
|
||||||
fn af_num(&self) -> u8;
|
fn af_num(&self) -> u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MosiPin<T: Instance>: OptionalPin {
|
pub trait MosiPin<T: Instance>: Pin {
|
||||||
fn af_num(&self) -> u8;
|
fn af_num(&self) -> u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MisoPin<T: Instance>: OptionalPin {
|
pub trait MisoPin<T: Instance>: Pin {
|
||||||
fn af_num(&self) -> u8;
|
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 {
|
macro_rules! impl_dma {
|
||||||
($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => {
|
($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => {
|
||||||
impl<T> sealed::$signal<peripherals::$inst> for T
|
impl<T> sealed::$signal<peripherals::$inst> for T
|
||||||
|
@ -215,11 +215,11 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> {
|
|||||||
/// clock.
|
/// clock.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Unborrow<Target = SUBGHZSPI> + 'd,
|
peri: impl Unborrow<Target = SUBGHZSPI> + 'd,
|
||||||
sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>>,
|
sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>> + 'd,
|
||||||
mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>>,
|
mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>> + 'd,
|
||||||
miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>>,
|
miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>> + 'd,
|
||||||
txdma: impl Unborrow<Target = Tx>,
|
txdma: impl Unborrow<Target = Tx> + 'd,
|
||||||
rxdma: impl Unborrow<Target = Rx>,
|
rxdma: impl Unborrow<Target = Rx> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::pulse_radio_reset();
|
Self::pulse_radio_reset();
|
||||||
|
|
||||||
|
@ -81,11 +81,11 @@ pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
|
|||||||
|
|
||||||
impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
inner: impl Unborrow<Target = T>,
|
inner: impl Unborrow<Target = T> + 'd,
|
||||||
rx: impl Unborrow<Target = impl RxPin<T>>,
|
rx: impl Unborrow<Target = impl RxPin<T>> + 'd,
|
||||||
tx: impl Unborrow<Target = impl TxPin<T>>,
|
tx: impl Unborrow<Target = impl TxPin<T>> + 'd,
|
||||||
tx_dma: impl Unborrow<Target = TxDma>,
|
tx_dma: impl Unborrow<Target = TxDma> + 'd,
|
||||||
rx_dma: impl Unborrow<Target = RxDma>,
|
rx_dma: impl Unborrow<Target = RxDma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(inner, rx, tx, tx_dma, rx_dma);
|
unborrow!(inner, rx, tx, tx_dma, rx_dma);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
mod example_common;
|
mod example_common;
|
||||||
use embassy::executor::Spawner;
|
use embassy::executor::Spawner;
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy_stm32::gpio::NoPin;
|
|
||||||
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
|
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
|
||||||
use embassy_stm32::time::U32Ext;
|
use embassy_stm32::time::U32Ext;
|
||||||
use embassy_stm32::Peripherals;
|
use embassy_stm32::Peripherals;
|
||||||
@ -16,7 +15,7 @@ use example_common::*;
|
|||||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||||
info!("Hello World!");
|
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();
|
let max = pwm.get_max_duty();
|
||||||
pwm.enable(Channel::Ch1);
|
pwm.enable(Channel::Ch1);
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
use embassy::executor::Spawner;
|
use embassy::executor::Spawner;
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy_stm32::dcmi::*;
|
use embassy_stm32::dcmi::{self, *};
|
||||||
use embassy_stm32::gpio::{Level, NoPin, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::interrupt;
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
|
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 dcmi_irq = interrupt::take!(DCMI);
|
||||||
let mut dcmi = Dcmi::new(
|
let config = dcmi::Config::default();
|
||||||
p.DCMI,
|
let mut dcmi = Dcmi::new_8bit(
|
||||||
p.DMA1_CH0,
|
p.DCMI, p.DMA1_CH0, dcmi_irq, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6,
|
||||||
VSyncDataInvalidLevel::High,
|
p.PB7, p.PA4, p.PA6, config,
|
||||||
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,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
defmt::info!("attempting capture");
|
defmt::info!("attempting capture");
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#[path = "../example_common.rs"]
|
#[path = "../example_common.rs"]
|
||||||
mod example_common;
|
mod example_common;
|
||||||
|
|
||||||
use embassy_stm32::gpio::NoPin;
|
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
@ -17,7 +16,7 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let p = embassy_stm32::init(config());
|
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 {
|
loop {
|
||||||
for v in 0..=255 {
|
for v in 0..=255 {
|
||||||
|
@ -10,7 +10,6 @@ use embassy::executor::Spawner;
|
|||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
use embassy_stm32::gpio::NoPin;
|
|
||||||
use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode};
|
use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode};
|
||||||
use embassy_stm32::time::{Hertz, U32Ext};
|
use embassy_stm32::time::{Hertz, U32Ext};
|
||||||
use embassy_stm32::timer::GeneralPurpose32bitInstance;
|
use embassy_stm32::timer::GeneralPurpose32bitInstance;
|
||||||
@ -33,7 +32,7 @@ pub fn config() -> Config {
|
|||||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||||
info!("Hello World!");
|
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();
|
let max = pwm.get_max_duty();
|
||||||
pwm.enable(Channel::Ch1);
|
pwm.enable(Channel::Ch1);
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
mod example_common;
|
mod example_common;
|
||||||
use embassy::executor::Spawner;
|
use embassy::executor::Spawner;
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy_stm32::gpio::NoPin;
|
|
||||||
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
|
use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel};
|
||||||
use embassy_stm32::time::U32Ext;
|
use embassy_stm32::time::U32Ext;
|
||||||
use embassy_stm32::{Config, Peripherals};
|
use embassy_stm32::{Config, Peripherals};
|
||||||
@ -28,7 +27,7 @@ pub fn config() -> Config {
|
|||||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||||
info!("Hello World!");
|
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();
|
let max = pwm.get_max_duty();
|
||||||
pwm.enable(Channel::Ch1);
|
pwm.enable(Channel::Ch1);
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
mod example_common;
|
mod example_common;
|
||||||
|
|
||||||
use embassy_stm32::dac::{Channel, Dac, Value};
|
use embassy_stm32::dac::{Channel, Dac, Value};
|
||||||
use embassy_stm32::gpio::NoPin;
|
|
||||||
use embassy_stm32::pac;
|
use embassy_stm32::pac;
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let p = embassy_stm32::init(Default::default());
|
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 {
|
loop {
|
||||||
for v in 0..=255 {
|
for v in 0..=255 {
|
||||||
|
Loading…
Reference in New Issue
Block a user