diff options
26 files changed, 291 insertions, 352 deletions
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 9093ad919..e3458e2de 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -354,7 +354,11 @@ unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteRe | |||
| 354 | WriteResult::Written | 354 | WriteResult::Written |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | /// Initialize peripherals with the provided configuration. This should only be called once at startup. | 357 | /// Initialize the `embassy-nrf` HAL with the provided configuration. |
| 358 | /// | ||
| 359 | /// This returns the peripheral singletons that can be used for creating drivers. | ||
| 360 | /// | ||
| 361 | /// This should only be called once at startup, otherwise it panics. | ||
| 358 | pub fn init(config: config::Config) -> Peripherals { | 362 | pub fn init(config: config::Config) -> Peripherals { |
| 359 | // Do this first, so that it panics if user is calling `init` a second time | 363 | // Do this first, so that it panics if user is calling `init` a second time |
| 360 | // before doing anything important. | 364 | // before doing anything important. |
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index bb60d244f..058b8a0fc 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -672,14 +672,14 @@ fn main() { | |||
| 672 | (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), | 672 | (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), |
| 673 | (("lpuart", "CK"), quote!(crate::usart::CkPin)), | 673 | (("lpuart", "CK"), quote!(crate::usart::CkPin)), |
| 674 | (("lpuart", "DE"), quote!(crate::usart::DePin)), | 674 | (("lpuart", "DE"), quote!(crate::usart::DePin)), |
| 675 | (("sai", "SCK_A"), quote!(crate::sai::SckAPin)), | 675 | (("sai", "SCK_A"), quote!(crate::sai::SckPin<A>)), |
| 676 | (("sai", "SCK_B"), quote!(crate::sai::SckBPin)), | 676 | (("sai", "SCK_B"), quote!(crate::sai::SckPin<B>)), |
| 677 | (("sai", "FS_A"), quote!(crate::sai::FsAPin)), | 677 | (("sai", "FS_A"), quote!(crate::sai::FsPin<A>)), |
| 678 | (("sai", "FS_B"), quote!(crate::sai::FsBPin)), | 678 | (("sai", "FS_B"), quote!(crate::sai::FsPin<B>)), |
| 679 | (("sai", "SD_A"), quote!(crate::sai::SdAPin)), | 679 | (("sai", "SD_A"), quote!(crate::sai::SdPin<A>)), |
| 680 | (("sai", "SD_B"), quote!(crate::sai::SdBPin)), | 680 | (("sai", "SD_B"), quote!(crate::sai::SdPin<B>)), |
| 681 | (("sai", "MCLK_A"), quote!(crate::sai::MclkAPin)), | 681 | (("sai", "MCLK_A"), quote!(crate::sai::MclkPin<A>)), |
| 682 | (("sai", "MCLK_B"), quote!(crate::sai::MclkBPin)), | 682 | (("sai", "MCLK_B"), quote!(crate::sai::MclkPin<B>)), |
| 683 | (("sai", "WS"), quote!(crate::sai::WsPin)), | 683 | (("sai", "WS"), quote!(crate::sai::WsPin)), |
| 684 | (("spi", "SCK"), quote!(crate::spi::SckPin)), | 684 | (("spi", "SCK"), quote!(crate::spi::SckPin)), |
| 685 | (("spi", "MOSI"), quote!(crate::spi::MosiPin)), | 685 | (("spi", "MOSI"), quote!(crate::spi::MosiPin)), |
| @@ -995,8 +995,8 @@ fn main() { | |||
| 995 | (("usart", "TX"), quote!(crate::usart::TxDma)), | 995 | (("usart", "TX"), quote!(crate::usart::TxDma)), |
| 996 | (("lpuart", "RX"), quote!(crate::usart::RxDma)), | 996 | (("lpuart", "RX"), quote!(crate::usart::RxDma)), |
| 997 | (("lpuart", "TX"), quote!(crate::usart::TxDma)), | 997 | (("lpuart", "TX"), quote!(crate::usart::TxDma)), |
| 998 | (("sai", "A"), quote!(crate::sai::DmaA)), | 998 | (("sai", "A"), quote!(crate::sai::Dma<A>)), |
| 999 | (("sai", "B"), quote!(crate::sai::DmaB)), | 999 | (("sai", "B"), quote!(crate::sai::Dma<B>)), |
| 1000 | (("spi", "RX"), quote!(crate::spi::RxDma)), | 1000 | (("spi", "RX"), quote!(crate::spi::RxDma)), |
| 1001 | (("spi", "TX"), quote!(crate::spi::TxDma)), | 1001 | (("spi", "TX"), quote!(crate::spi::TxDma)), |
| 1002 | (("i2c", "RX"), quote!(crate::i2c::RxDma)), | 1002 | (("i2c", "RX"), quote!(crate::i2c::RxDma)), |
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index ff523ca3b..e4dd35c34 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | //! Analog to Digital (ADC) converter driver. | 1 | //! Analog to Digital Converter (ADC) |
| 2 | |||
| 2 | #![macro_use] | 3 | #![macro_use] |
| 3 | #![allow(missing_docs)] // TODO | 4 | #![allow(missing_docs)] // TODO |
| 4 | 5 | ||
diff --git a/embassy-stm32/src/can/mod.rs b/embassy-stm32/src/can/mod.rs index 425f9ac2e..915edb3a6 100644 --- a/embassy-stm32/src/can/mod.rs +++ b/embassy-stm32/src/can/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Controller Area Network (CAN) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | #[cfg_attr(can_bxcan, path = "bxcan.rs")] | 4 | #[cfg_attr(can_bxcan, path = "bxcan.rs")] |
diff --git a/embassy-stm32/src/crc/mod.rs b/embassy-stm32/src/crc/mod.rs index 63f7ad9ba..29523b92d 100644 --- a/embassy-stm32/src/crc/mod.rs +++ b/embassy-stm32/src/crc/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Cyclic Redundancy Check (CRC) | ||
| 1 | #[cfg_attr(crc_v1, path = "v1.rs")] | 2 | #[cfg_attr(crc_v1, path = "v1.rs")] |
| 2 | #[cfg_attr(crc_v2, path = "v2v3.rs")] | 3 | #[cfg_attr(crc_v2, path = "v2v3.rs")] |
| 3 | #[cfg_attr(crc_v3, path = "v2v3.rs")] | 4 | #[cfg_attr(crc_v3, path = "v2v3.rs")] |
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 9c670195d..31dedf06e 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | //! Provide access to the STM32 digital-to-analog converter (DAC). | 1 | //! Digital to Analog Converter (DAC) |
| 2 | #![macro_use] | 2 | #![macro_use] |
| 3 | 3 | ||
| 4 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 139d8fd1b..4d02284b2 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Digital Camera Interface (DCMI) | ||
| 1 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index dbf91eedc..448405507 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Ethernet (ETH) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | #[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] | 4 | #[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] |
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 371be913e..f83bae3ff 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! External Interrupts (EXTI) | ||
| 1 | use core::convert::Infallible; | 2 | use core::convert::Infallible; |
| 2 | use core::future::Future; | 3 | use core::future::Future; |
| 3 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 6b6b4d41c..cbf5c25b2 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Flash memory (FLASH) | ||
| 1 | use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; | 2 | use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; |
| 2 | 3 | ||
| 3 | #[cfg(flash_f4)] | 4 | #[cfg(flash_f4)] |
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 23ac82f63..873c8a70c 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Flexible Memory Controller (FMC) / Flexible Static Memory Controller (FSMC) | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | 3 | ||
| 3 | use embassy_hal_internal::into_ref; | 4 | use embassy_hal_internal::into_ref; |
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs index 17096d48c..6539326b4 100644 --- a/embassy-stm32/src/hrtim/mod.rs +++ b/embassy-stm32/src/hrtim/mod.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | //! High Resolution Timer (HRTIM) | ||
| 2 | |||
| 1 | mod traits; | 3 | mod traits; |
| 2 | 4 | ||
| 3 | use core::marker::PhantomData; | 5 | use core::marker::PhantomData; |
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 0af291e9c..9b0b35eca 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Inter-Integrated-Circuit (I2C) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | #[cfg_attr(i2c_v1, path = "v1.rs")] | 4 | #[cfg_attr(i2c_v1, path = "v1.rs")] |
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 372c86db3..1f85c0bc5 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Inter-IC Sound (I2S) | ||
| 1 | use embassy_hal_internal::into_ref; | 2 | use embassy_hal_internal::into_ref; |
| 2 | 3 | ||
| 3 | use crate::gpio::sealed::{AFType, Pin as _}; | 4 | use crate::gpio::sealed::{AFType, Pin as _}; |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 5d9b4e6a0..fd691a732 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -149,15 +149,33 @@ use crate::interrupt::Priority; | |||
| 149 | pub use crate::pac::NVIC_PRIO_BITS; | 149 | pub use crate::pac::NVIC_PRIO_BITS; |
| 150 | use crate::rcc::sealed::RccPeripheral; | 150 | use crate::rcc::sealed::RccPeripheral; |
| 151 | 151 | ||
| 152 | /// `embassy-stm32` global configuration. | ||
| 152 | #[non_exhaustive] | 153 | #[non_exhaustive] |
| 153 | pub struct Config { | 154 | pub struct Config { |
| 155 | /// RCC config. | ||
| 154 | pub rcc: rcc::Config, | 156 | pub rcc: rcc::Config, |
| 157 | |||
| 158 | /// Enable debug during sleep. | ||
| 159 | /// | ||
| 160 | /// May incrase power consumption. Defaults to true. | ||
| 155 | #[cfg(dbgmcu)] | 161 | #[cfg(dbgmcu)] |
| 156 | pub enable_debug_during_sleep: bool, | 162 | pub enable_debug_during_sleep: bool, |
| 163 | |||
| 164 | /// BDMA interrupt priority. | ||
| 165 | /// | ||
| 166 | /// Defaults to P0 (highest). | ||
| 157 | #[cfg(bdma)] | 167 | #[cfg(bdma)] |
| 158 | pub bdma_interrupt_priority: Priority, | 168 | pub bdma_interrupt_priority: Priority, |
| 169 | |||
| 170 | /// DMA interrupt priority. | ||
| 171 | /// | ||
| 172 | /// Defaults to P0 (highest). | ||
| 159 | #[cfg(dma)] | 173 | #[cfg(dma)] |
| 160 | pub dma_interrupt_priority: Priority, | 174 | pub dma_interrupt_priority: Priority, |
| 175 | |||
| 176 | /// GPDMA interrupt priority. | ||
| 177 | /// | ||
| 178 | /// Defaults to P0 (highest). | ||
| 161 | #[cfg(gpdma)] | 179 | #[cfg(gpdma)] |
| 162 | pub gpdma_interrupt_priority: Priority, | 180 | pub gpdma_interrupt_priority: Priority, |
| 163 | } | 181 | } |
| @@ -178,7 +196,11 @@ impl Default for Config { | |||
| 178 | } | 196 | } |
| 179 | } | 197 | } |
| 180 | 198 | ||
| 181 | /// Initialize embassy. | 199 | /// Initialize the `embassy-stm32` HAL with the provided configuration. |
| 200 | /// | ||
| 201 | /// This returns the peripheral singletons that can be used for creating drivers. | ||
| 202 | /// | ||
| 203 | /// This should only be called once at startup, otherwise it panics. | ||
| 182 | pub fn init(config: Config) -> Peripherals { | 204 | pub fn init(config: Config) -> Peripherals { |
| 183 | critical_section::with(|cs| { | 205 | critical_section::with(|cs| { |
| 184 | let p = Peripherals::take_with_cs(cs); | 206 | let p = Peripherals::take_with_cs(cs); |
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index bac91f300..9ea0a726c 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | //! Quad Serial Peripheral Interface (QSPI) | ||
| 2 | |||
| 1 | #![macro_use] | 3 | #![macro_use] |
| 2 | 4 | ||
| 3 | pub mod enums; | 5 | pub mod enums; |
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index b2196b0d5..6ee89a922 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Random Number Generator (RNG) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | use core::future::poll_fn; | 4 | use core::future::poll_fn; |
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index fa359cdae..11b252139 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | //! RTC peripheral abstraction | 1 | //! Real Time Clock (RTC) |
| 2 | mod datetime; | 2 | mod datetime; |
| 3 | 3 | ||
| 4 | #[cfg(feature = "low-power")] | 4 | #[cfg(feature = "low-power")] |
| @@ -163,7 +163,7 @@ impl RtcTimeProvider { | |||
| 163 | } | 163 | } |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | /// RTC Abstraction | 166 | /// RTC driver. |
| 167 | pub struct Rtc { | 167 | pub struct Rtc { |
| 168 | #[cfg(feature = "low-power")] | 168 | #[cfg(feature = "low-power")] |
| 169 | stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>, | 169 | stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>, |
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 3d7f65996..ef8802184 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | //! Serial Audio Interface (SAI) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | use embassy_embedded_hal::SetConfig; | 4 | use core::marker::PhantomData; |
| 5 | |||
| 4 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 6 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 5 | 7 | ||
| 8 | use self::sealed::WhichSubBlock; | ||
| 6 | pub use crate::dma::word; | 9 | pub use crate::dma::word; |
| 7 | use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; | 10 | use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; |
| 8 | use crate::gpio::sealed::{AFType, Pin as _}; | 11 | use crate::gpio::sealed::{AFType, Pin as _}; |
| @@ -11,48 +14,32 @@ use crate::pac::sai::{vals, Sai as Regs}; | |||
| 11 | use crate::rcc::RccPeripheral; | 14 | use crate::rcc::RccPeripheral; |
| 12 | use crate::{peripherals, Peripheral}; | 15 | use crate::{peripherals, Peripheral}; |
| 13 | 16 | ||
| 17 | /// SAI error | ||
| 14 | #[derive(Debug, PartialEq, Eq)] | 18 | #[derive(Debug, PartialEq, Eq)] |
| 15 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 19 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 16 | pub enum Error { | 20 | pub enum Error { |
| 21 | /// `write` called on a SAI in receive mode. | ||
| 17 | NotATransmitter, | 22 | NotATransmitter, |
| 23 | /// `read` called on a SAI in transmit mode. | ||
| 18 | NotAReceiver, | 24 | NotAReceiver, |
| 19 | OverrunError, | 25 | /// Overrun |
| 26 | Overrun, | ||
| 20 | } | 27 | } |
| 21 | 28 | ||
| 22 | impl From<ringbuffer::OverrunError> for Error { | 29 | impl From<ringbuffer::OverrunError> for Error { |
| 23 | fn from(_: ringbuffer::OverrunError) -> Self { | 30 | fn from(_: ringbuffer::OverrunError) -> Self { |
| 24 | Self::OverrunError | 31 | Self::Overrun |
| 25 | } | 32 | } |
| 26 | } | 33 | } |
| 27 | 34 | ||
| 35 | /// Master/slave mode. | ||
| 28 | #[derive(Copy, Clone)] | 36 | #[derive(Copy, Clone)] |
| 29 | pub enum SyncBlock { | 37 | #[allow(missing_docs)] |
| 30 | None, | ||
| 31 | Sai1BlockA, | ||
| 32 | Sai1BlockB, | ||
| 33 | Sai2BlockA, | ||
| 34 | Sai2BlockB, | ||
| 35 | } | ||
| 36 | |||
| 37 | #[derive(Copy, Clone)] | ||
| 38 | pub enum SyncIn { | ||
| 39 | None, | ||
| 40 | ChannelZero, | ||
| 41 | ChannelOne, | ||
| 42 | } | ||
| 43 | |||
| 44 | #[derive(Copy, Clone)] | ||
| 45 | pub enum Mode { | 38 | pub enum Mode { |
| 46 | Master, | 39 | Master, |
| 47 | Slave, | 40 | Slave, |
| 48 | } | 41 | } |
| 49 | 42 | ||
| 50 | #[derive(Copy, Clone)] | ||
| 51 | pub enum TxRx { | ||
| 52 | Transmitter, | ||
| 53 | Receiver, | ||
| 54 | } | ||
| 55 | |||
| 56 | impl Mode { | 43 | impl Mode { |
| 57 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 44 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 58 | const fn mode(&self, tx_rx: TxRx) -> vals::Mode { | 45 | const fn mode(&self, tx_rx: TxRx) -> vals::Mode { |
| @@ -69,7 +56,17 @@ impl Mode { | |||
| 69 | } | 56 | } |
| 70 | } | 57 | } |
| 71 | 58 | ||
| 59 | /// Direction: transmit or receive | ||
| 72 | #[derive(Copy, Clone)] | 60 | #[derive(Copy, Clone)] |
| 61 | #[allow(missing_docs)] | ||
| 62 | pub enum TxRx { | ||
| 63 | Transmitter, | ||
| 64 | Receiver, | ||
| 65 | } | ||
| 66 | |||
| 67 | /// Data slot size. | ||
| 68 | #[derive(Copy, Clone)] | ||
| 69 | #[allow(missing_docs)] | ||
| 73 | pub enum SlotSize { | 70 | pub enum SlotSize { |
| 74 | DataSize, | 71 | DataSize, |
| 75 | /// 16 bit data length on 16 bit wide channel | 72 | /// 16 bit data length on 16 bit wide channel |
| @@ -80,7 +77,7 @@ pub enum SlotSize { | |||
| 80 | 77 | ||
| 81 | impl SlotSize { | 78 | impl SlotSize { |
| 82 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 79 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 83 | pub const fn slotsz(&self) -> vals::Slotsz { | 80 | const fn slotsz(&self) -> vals::Slotsz { |
| 84 | match self { | 81 | match self { |
| 85 | SlotSize::DataSize => vals::Slotsz::DATASIZE, | 82 | SlotSize::DataSize => vals::Slotsz::DATASIZE, |
| 86 | SlotSize::Channel16 => vals::Slotsz::BIT16, | 83 | SlotSize::Channel16 => vals::Slotsz::BIT16, |
| @@ -89,7 +86,9 @@ impl SlotSize { | |||
| 89 | } | 86 | } |
| 90 | } | 87 | } |
| 91 | 88 | ||
| 89 | /// Data size. | ||
| 92 | #[derive(Copy, Clone)] | 90 | #[derive(Copy, Clone)] |
| 91 | #[allow(missing_docs)] | ||
| 93 | pub enum DataSize { | 92 | pub enum DataSize { |
| 94 | Data8, | 93 | Data8, |
| 95 | Data10, | 94 | Data10, |
| @@ -101,7 +100,7 @@ pub enum DataSize { | |||
| 101 | 100 | ||
| 102 | impl DataSize { | 101 | impl DataSize { |
| 103 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 102 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 104 | pub const fn ds(&self) -> vals::Ds { | 103 | const fn ds(&self) -> vals::Ds { |
| 105 | match self { | 104 | match self { |
| 106 | DataSize::Data8 => vals::Ds::BIT8, | 105 | DataSize::Data8 => vals::Ds::BIT8, |
| 107 | DataSize::Data10 => vals::Ds::BIT10, | 106 | DataSize::Data10 => vals::Ds::BIT10, |
| @@ -113,7 +112,9 @@ impl DataSize { | |||
| 113 | } | 112 | } |
| 114 | } | 113 | } |
| 115 | 114 | ||
| 115 | /// FIFO threshold level. | ||
| 116 | #[derive(Copy, Clone)] | 116 | #[derive(Copy, Clone)] |
| 117 | #[allow(missing_docs)] | ||
| 117 | pub enum FifoThreshold { | 118 | pub enum FifoThreshold { |
| 118 | Empty, | 119 | Empty, |
| 119 | Quarter, | 120 | Quarter, |
| @@ -124,7 +125,7 @@ pub enum FifoThreshold { | |||
| 124 | 125 | ||
| 125 | impl FifoThreshold { | 126 | impl FifoThreshold { |
| 126 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 127 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 127 | pub const fn fth(&self) -> vals::Fth { | 128 | const fn fth(&self) -> vals::Fth { |
| 128 | match self { | 129 | match self { |
| 129 | FifoThreshold::Empty => vals::Fth::EMPTY, | 130 | FifoThreshold::Empty => vals::Fth::EMPTY, |
| 130 | FifoThreshold::Quarter => vals::Fth::QUARTER1, | 131 | FifoThreshold::Quarter => vals::Fth::QUARTER1, |
| @@ -135,38 +136,9 @@ impl FifoThreshold { | |||
| 135 | } | 136 | } |
| 136 | } | 137 | } |
| 137 | 138 | ||
| 139 | /// Output value on mute. | ||
| 138 | #[derive(Copy, Clone)] | 140 | #[derive(Copy, Clone)] |
| 139 | pub enum FifoLevel { | 141 | #[allow(missing_docs)] |
| 140 | Empty, | ||
| 141 | FirstQuarter, | ||
| 142 | SecondQuarter, | ||
| 143 | ThirdQuarter, | ||
| 144 | FourthQuarter, | ||
| 145 | Full, | ||
| 146 | } | ||
| 147 | |||
| 148 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | ||
| 149 | impl From<vals::Flvl> for FifoLevel { | ||
| 150 | fn from(flvl: vals::Flvl) -> Self { | ||
| 151 | match flvl { | ||
| 152 | vals::Flvl::EMPTY => FifoLevel::Empty, | ||
| 153 | vals::Flvl::QUARTER1 => FifoLevel::FirstQuarter, | ||
| 154 | vals::Flvl::QUARTER2 => FifoLevel::SecondQuarter, | ||
| 155 | vals::Flvl::QUARTER3 => FifoLevel::ThirdQuarter, | ||
| 156 | vals::Flvl::QUARTER4 => FifoLevel::FourthQuarter, | ||
| 157 | vals::Flvl::FULL => FifoLevel::Full, | ||
| 158 | _ => FifoLevel::Empty, | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | #[derive(Copy, Clone)] | ||
| 164 | pub enum MuteDetection { | ||
| 165 | NoMute, | ||
| 166 | Mute, | ||
| 167 | } | ||
| 168 | |||
| 169 | #[derive(Copy, Clone)] | ||
| 170 | pub enum MuteValue { | 142 | pub enum MuteValue { |
| 171 | Zero, | 143 | Zero, |
| 172 | LastValue, | 144 | LastValue, |
| @@ -174,7 +146,7 @@ pub enum MuteValue { | |||
| 174 | 146 | ||
| 175 | impl MuteValue { | 147 | impl MuteValue { |
| 176 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 148 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 177 | pub const fn muteval(&self) -> vals::Muteval { | 149 | const fn muteval(&self) -> vals::Muteval { |
| 178 | match self { | 150 | match self { |
| 179 | MuteValue::Zero => vals::Muteval::SENDZERO, | 151 | MuteValue::Zero => vals::Muteval::SENDZERO, |
| 180 | MuteValue::LastValue => vals::Muteval::SENDLAST, | 152 | MuteValue::LastValue => vals::Muteval::SENDLAST, |
| @@ -182,13 +154,9 @@ impl MuteValue { | |||
| 182 | } | 154 | } |
| 183 | } | 155 | } |
| 184 | 156 | ||
| 157 | /// Protocol variant to use. | ||
| 185 | #[derive(Copy, Clone)] | 158 | #[derive(Copy, Clone)] |
| 186 | pub enum OverUnderStatus { | 159 | #[allow(missing_docs)] |
| 187 | NoError, | ||
| 188 | OverUnderRunDetected, | ||
| 189 | } | ||
| 190 | |||
| 191 | #[derive(Copy, Clone)] | ||
| 192 | pub enum Protocol { | 160 | pub enum Protocol { |
| 193 | Free, | 161 | Free, |
| 194 | Spdif, | 162 | Spdif, |
| @@ -197,7 +165,7 @@ pub enum Protocol { | |||
| 197 | 165 | ||
| 198 | impl Protocol { | 166 | impl Protocol { |
| 199 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 167 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 200 | pub const fn prtcfg(&self) -> vals::Prtcfg { | 168 | const fn prtcfg(&self) -> vals::Prtcfg { |
| 201 | match self { | 169 | match self { |
| 202 | Protocol::Free => vals::Prtcfg::FREE, | 170 | Protocol::Free => vals::Prtcfg::FREE, |
| 203 | Protocol::Spdif => vals::Prtcfg::SPDIF, | 171 | Protocol::Spdif => vals::Prtcfg::SPDIF, |
| @@ -206,7 +174,9 @@ impl Protocol { | |||
| 206 | } | 174 | } |
| 207 | } | 175 | } |
| 208 | 176 | ||
| 177 | /// Sync input between SAI units/blocks. | ||
| 209 | #[derive(Copy, Clone, PartialEq)] | 178 | #[derive(Copy, Clone, PartialEq)] |
| 179 | #[allow(missing_docs)] | ||
| 210 | pub enum SyncInput { | 180 | pub enum SyncInput { |
| 211 | /// Not synced to any other SAI unit. | 181 | /// Not synced to any other SAI unit. |
| 212 | None, | 182 | None, |
| @@ -218,7 +188,7 @@ pub enum SyncInput { | |||
| 218 | } | 188 | } |
| 219 | 189 | ||
| 220 | impl SyncInput { | 190 | impl SyncInput { |
| 221 | pub const fn syncen(&self) -> vals::Syncen { | 191 | const fn syncen(&self) -> vals::Syncen { |
| 222 | match self { | 192 | match self { |
| 223 | SyncInput::None => vals::Syncen::ASYNCHRONOUS, | 193 | SyncInput::None => vals::Syncen::ASYNCHRONOUS, |
| 224 | SyncInput::Internal => vals::Syncen::INTERNAL, | 194 | SyncInput::Internal => vals::Syncen::INTERNAL, |
| @@ -228,8 +198,10 @@ impl SyncInput { | |||
| 228 | } | 198 | } |
| 229 | } | 199 | } |
| 230 | 200 | ||
| 201 | /// SAI instance to sync from. | ||
| 231 | #[cfg(sai_v4)] | 202 | #[cfg(sai_v4)] |
| 232 | #[derive(Copy, Clone, PartialEq)] | 203 | #[derive(Copy, Clone, PartialEq)] |
| 204 | #[allow(missing_docs)] | ||
| 233 | pub enum SyncInputInstance { | 205 | pub enum SyncInputInstance { |
| 234 | #[cfg(peri_sai1)] | 206 | #[cfg(peri_sai1)] |
| 235 | Sai1 = 0, | 207 | Sai1 = 0, |
| @@ -241,7 +213,9 @@ pub enum SyncInputInstance { | |||
| 241 | Sai4 = 3, | 213 | Sai4 = 3, |
| 242 | } | 214 | } |
| 243 | 215 | ||
| 216 | /// Channels (stereo or mono). | ||
| 244 | #[derive(Copy, Clone, PartialEq)] | 217 | #[derive(Copy, Clone, PartialEq)] |
| 218 | #[allow(missing_docs)] | ||
| 245 | pub enum StereoMono { | 219 | pub enum StereoMono { |
| 246 | Stereo, | 220 | Stereo, |
| 247 | Mono, | 221 | Mono, |
| @@ -249,7 +223,7 @@ pub enum StereoMono { | |||
| 249 | 223 | ||
| 250 | impl StereoMono { | 224 | impl StereoMono { |
| 251 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 225 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 252 | pub const fn mono(&self) -> vals::Mono { | 226 | const fn mono(&self) -> vals::Mono { |
| 253 | match self { | 227 | match self { |
| 254 | StereoMono::Stereo => vals::Mono::STEREO, | 228 | StereoMono::Stereo => vals::Mono::STEREO, |
| 255 | StereoMono::Mono => vals::Mono::MONO, | 229 | StereoMono::Mono => vals::Mono::MONO, |
| @@ -257,15 +231,18 @@ impl StereoMono { | |||
| 257 | } | 231 | } |
| 258 | } | 232 | } |
| 259 | 233 | ||
| 234 | /// Bit order | ||
| 260 | #[derive(Copy, Clone)] | 235 | #[derive(Copy, Clone)] |
| 261 | pub enum BitOrder { | 236 | pub enum BitOrder { |
| 237 | /// Least significant bit first. | ||
| 262 | LsbFirst, | 238 | LsbFirst, |
| 239 | /// Most significant bit first. | ||
| 263 | MsbFirst, | 240 | MsbFirst, |
| 264 | } | 241 | } |
| 265 | 242 | ||
| 266 | impl BitOrder { | 243 | impl BitOrder { |
| 267 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 244 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 268 | pub const fn lsbfirst(&self) -> vals::Lsbfirst { | 245 | const fn lsbfirst(&self) -> vals::Lsbfirst { |
| 269 | match self { | 246 | match self { |
| 270 | BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, | 247 | BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, |
| 271 | BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, | 248 | BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, |
| @@ -273,6 +250,7 @@ impl BitOrder { | |||
| 273 | } | 250 | } |
| 274 | } | 251 | } |
| 275 | 252 | ||
| 253 | /// Frame sync offset. | ||
| 276 | #[derive(Copy, Clone)] | 254 | #[derive(Copy, Clone)] |
| 277 | pub enum FrameSyncOffset { | 255 | pub enum FrameSyncOffset { |
| 278 | /// This is used in modes other than standard I2S phillips mode | 256 | /// This is used in modes other than standard I2S phillips mode |
| @@ -283,7 +261,7 @@ pub enum FrameSyncOffset { | |||
| 283 | 261 | ||
| 284 | impl FrameSyncOffset { | 262 | impl FrameSyncOffset { |
| 285 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 263 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 286 | pub const fn fsoff(&self) -> vals::Fsoff { | 264 | const fn fsoff(&self) -> vals::Fsoff { |
| 287 | match self { | 265 | match self { |
| 288 | FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST, | 266 | FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST, |
| 289 | FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST, | 267 | FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST, |
| @@ -291,15 +269,18 @@ impl FrameSyncOffset { | |||
| 291 | } | 269 | } |
| 292 | } | 270 | } |
| 293 | 271 | ||
| 272 | /// Frame sync polarity | ||
| 294 | #[derive(Copy, Clone)] | 273 | #[derive(Copy, Clone)] |
| 295 | pub enum FrameSyncPolarity { | 274 | pub enum FrameSyncPolarity { |
| 275 | /// Sync signal is active low. | ||
| 296 | ActiveLow, | 276 | ActiveLow, |
| 277 | /// Sync signal is active high | ||
| 297 | ActiveHigh, | 278 | ActiveHigh, |
| 298 | } | 279 | } |
| 299 | 280 | ||
| 300 | impl FrameSyncPolarity { | 281 | impl FrameSyncPolarity { |
| 301 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 282 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 302 | pub const fn fspol(&self) -> vals::Fspol { | 283 | const fn fspol(&self) -> vals::Fspol { |
| 303 | match self { | 284 | match self { |
| 304 | FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE, | 285 | FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE, |
| 305 | FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE, | 286 | FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE, |
| @@ -307,7 +288,9 @@ impl FrameSyncPolarity { | |||
| 307 | } | 288 | } |
| 308 | } | 289 | } |
| 309 | 290 | ||
| 291 | /// Sync definition. | ||
| 310 | #[derive(Copy, Clone)] | 292 | #[derive(Copy, Clone)] |
| 293 | #[allow(missing_docs)] | ||
| 311 | pub enum FrameSyncDefinition { | 294 | pub enum FrameSyncDefinition { |
| 312 | StartOfFrame, | 295 | StartOfFrame, |
| 313 | ChannelIdentification, | 296 | ChannelIdentification, |
| @@ -315,7 +298,7 @@ pub enum FrameSyncDefinition { | |||
| 315 | 298 | ||
| 316 | impl FrameSyncDefinition { | 299 | impl FrameSyncDefinition { |
| 317 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 300 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 318 | pub const fn fsdef(&self) -> bool { | 301 | const fn fsdef(&self) -> bool { |
| 319 | match self { | 302 | match self { |
| 320 | FrameSyncDefinition::StartOfFrame => false, | 303 | FrameSyncDefinition::StartOfFrame => false, |
| 321 | FrameSyncDefinition::ChannelIdentification => true, | 304 | FrameSyncDefinition::ChannelIdentification => true, |
| @@ -323,7 +306,9 @@ impl FrameSyncDefinition { | |||
| 323 | } | 306 | } |
| 324 | } | 307 | } |
| 325 | 308 | ||
| 309 | /// Clock strobe. | ||
| 326 | #[derive(Copy, Clone)] | 310 | #[derive(Copy, Clone)] |
| 311 | #[allow(missing_docs)] | ||
| 327 | pub enum ClockStrobe { | 312 | pub enum ClockStrobe { |
| 328 | Falling, | 313 | Falling, |
| 329 | Rising, | 314 | Rising, |
| @@ -331,7 +316,7 @@ pub enum ClockStrobe { | |||
| 331 | 316 | ||
| 332 | impl ClockStrobe { | 317 | impl ClockStrobe { |
| 333 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 318 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 334 | pub const fn ckstr(&self) -> vals::Ckstr { | 319 | const fn ckstr(&self) -> vals::Ckstr { |
| 335 | match self { | 320 | match self { |
| 336 | ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE, | 321 | ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE, |
| 337 | ClockStrobe::Rising => vals::Ckstr::RISINGEDGE, | 322 | ClockStrobe::Rising => vals::Ckstr::RISINGEDGE, |
| @@ -339,7 +324,9 @@ impl ClockStrobe { | |||
| 339 | } | 324 | } |
| 340 | } | 325 | } |
| 341 | 326 | ||
| 327 | /// Complements format for negative samples. | ||
| 342 | #[derive(Copy, Clone)] | 328 | #[derive(Copy, Clone)] |
| 329 | #[allow(missing_docs)] | ||
| 343 | pub enum ComplementFormat { | 330 | pub enum ComplementFormat { |
| 344 | OnesComplement, | 331 | OnesComplement, |
| 345 | TwosComplement, | 332 | TwosComplement, |
| @@ -347,7 +334,7 @@ pub enum ComplementFormat { | |||
| 347 | 334 | ||
| 348 | impl ComplementFormat { | 335 | impl ComplementFormat { |
| 349 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 336 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 350 | pub const fn cpl(&self) -> vals::Cpl { | 337 | const fn cpl(&self) -> vals::Cpl { |
| 351 | match self { | 338 | match self { |
| 352 | ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT, | 339 | ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT, |
| 353 | ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT, | 340 | ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT, |
| @@ -355,7 +342,9 @@ impl ComplementFormat { | |||
| 355 | } | 342 | } |
| 356 | } | 343 | } |
| 357 | 344 | ||
| 345 | /// Companding setting. | ||
| 358 | #[derive(Copy, Clone)] | 346 | #[derive(Copy, Clone)] |
| 347 | #[allow(missing_docs)] | ||
| 359 | pub enum Companding { | 348 | pub enum Companding { |
| 360 | None, | 349 | None, |
| 361 | MuLaw, | 350 | MuLaw, |
| @@ -364,7 +353,7 @@ pub enum Companding { | |||
| 364 | 353 | ||
| 365 | impl Companding { | 354 | impl Companding { |
| 366 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 355 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 367 | pub const fn comp(&self) -> vals::Comp { | 356 | const fn comp(&self) -> vals::Comp { |
| 368 | match self { | 357 | match self { |
| 369 | Companding::None => vals::Comp::NOCOMPANDING, | 358 | Companding::None => vals::Comp::NOCOMPANDING, |
| 370 | Companding::MuLaw => vals::Comp::MULAW, | 359 | Companding::MuLaw => vals::Comp::MULAW, |
| @@ -373,7 +362,9 @@ impl Companding { | |||
| 373 | } | 362 | } |
| 374 | } | 363 | } |
| 375 | 364 | ||
| 365 | /// Output drive | ||
| 376 | #[derive(Copy, Clone)] | 366 | #[derive(Copy, Clone)] |
| 367 | #[allow(missing_docs)] | ||
| 377 | pub enum OutputDrive { | 368 | pub enum OutputDrive { |
| 378 | OnStart, | 369 | OnStart, |
| 379 | Immediately, | 370 | Immediately, |
| @@ -381,7 +372,7 @@ pub enum OutputDrive { | |||
| 381 | 372 | ||
| 382 | impl OutputDrive { | 373 | impl OutputDrive { |
| 383 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 374 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 384 | pub const fn outdriv(&self) -> vals::Outdriv { | 375 | const fn outdriv(&self) -> vals::Outdriv { |
| 385 | match self { | 376 | match self { |
| 386 | OutputDrive::OnStart => vals::Outdriv::ONSTART, | 377 | OutputDrive::OnStart => vals::Outdriv::ONSTART, |
| 387 | OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY, | 378 | OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY, |
| @@ -389,7 +380,9 @@ impl OutputDrive { | |||
| 389 | } | 380 | } |
| 390 | } | 381 | } |
| 391 | 382 | ||
| 383 | /// Master clock divider. | ||
| 392 | #[derive(Copy, Clone, PartialEq)] | 384 | #[derive(Copy, Clone, PartialEq)] |
| 385 | #[allow(missing_docs)] | ||
| 393 | pub enum MasterClockDivider { | 386 | pub enum MasterClockDivider { |
| 394 | MasterClockDisabled, | 387 | MasterClockDisabled, |
| 395 | Div1, | 388 | Div1, |
| @@ -412,7 +405,7 @@ pub enum MasterClockDivider { | |||
| 412 | 405 | ||
| 413 | impl MasterClockDivider { | 406 | impl MasterClockDivider { |
| 414 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 407 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 415 | pub const fn mckdiv(&self) -> u8 { | 408 | const fn mckdiv(&self) -> u8 { |
| 416 | match self { | 409 | match self { |
| 417 | MasterClockDivider::MasterClockDisabled => 0, | 410 | MasterClockDivider::MasterClockDisabled => 0, |
| 418 | MasterClockDivider::Div1 => 0, | 411 | MasterClockDivider::Div1 => 0, |
| @@ -436,6 +429,7 @@ impl MasterClockDivider { | |||
| 436 | } | 429 | } |
| 437 | 430 | ||
| 438 | /// [`SAI`] configuration. | 431 | /// [`SAI`] configuration. |
| 432 | #[allow(missing_docs)] | ||
| 439 | #[non_exhaustive] | 433 | #[non_exhaustive] |
| 440 | #[derive(Copy, Clone)] | 434 | #[derive(Copy, Clone)] |
| 441 | pub struct Config { | 435 | pub struct Config { |
| @@ -459,7 +453,7 @@ pub struct Config { | |||
| 459 | pub clock_strobe: ClockStrobe, | 453 | pub clock_strobe: ClockStrobe, |
| 460 | pub output_drive: OutputDrive, | 454 | pub output_drive: OutputDrive, |
| 461 | pub master_clock_divider: MasterClockDivider, | 455 | pub master_clock_divider: MasterClockDivider, |
| 462 | pub is_high_impedenane_on_inactive_slot: bool, | 456 | pub is_high_impedance_on_inactive_slot: bool, |
| 463 | pub fifo_threshold: FifoThreshold, | 457 | pub fifo_threshold: FifoThreshold, |
| 464 | pub companding: Companding, | 458 | pub companding: Companding, |
| 465 | pub complement_format: ComplementFormat, | 459 | pub complement_format: ComplementFormat, |
| @@ -490,7 +484,7 @@ impl Default for Config { | |||
| 490 | master_clock_divider: MasterClockDivider::MasterClockDisabled, | 484 | master_clock_divider: MasterClockDivider::MasterClockDisabled, |
| 491 | clock_strobe: ClockStrobe::Rising, | 485 | clock_strobe: ClockStrobe::Rising, |
| 492 | output_drive: OutputDrive::Immediately, | 486 | output_drive: OutputDrive::Immediately, |
| 493 | is_high_impedenane_on_inactive_slot: false, | 487 | is_high_impedance_on_inactive_slot: false, |
| 494 | fifo_threshold: FifoThreshold::ThreeQuarters, | 488 | fifo_threshold: FifoThreshold::ThreeQuarters, |
| 495 | companding: Companding::None, | 489 | companding: Companding::None, |
| 496 | complement_format: ComplementFormat::TwosComplement, | 490 | complement_format: ComplementFormat::TwosComplement, |
| @@ -501,23 +495,10 @@ impl Default for Config { | |||
| 501 | } | 495 | } |
| 502 | 496 | ||
| 503 | impl Config { | 497 | impl Config { |
| 504 | pub fn new_i2s() -> Self { | 498 | /// Create a new config with all default values. |
| 499 | pub fn new() -> Self { | ||
| 505 | return Default::default(); | 500 | return Default::default(); |
| 506 | } | 501 | } |
| 507 | |||
| 508 | pub fn new_msb_first() -> Self { | ||
| 509 | Self { | ||
| 510 | bit_order: BitOrder::MsbFirst, | ||
| 511 | frame_sync_offset: FrameSyncOffset::OnFirstBit, | ||
| 512 | ..Default::default() | ||
| 513 | } | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | #[derive(Copy, Clone)] | ||
| 518 | enum WhichSubBlock { | ||
| 519 | A = 0, | ||
| 520 | B = 1, | ||
| 521 | } | 502 | } |
| 522 | 503 | ||
| 523 | enum RingBuffer<'d, C: Channel, W: word::Word> { | 504 | enum RingBuffer<'d, C: Channel, W: word::Word> { |
| @@ -531,28 +512,6 @@ fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut | |||
| 531 | ch.dr().as_ptr() as _ | 512 | ch.dr().as_ptr() as _ |
| 532 | } | 513 | } |
| 533 | 514 | ||
| 534 | pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> { | ||
| 535 | _peri: PeripheralRef<'d, T>, | ||
| 536 | sd: Option<PeripheralRef<'d, AnyPin>>, | ||
| 537 | fs: Option<PeripheralRef<'d, AnyPin>>, | ||
| 538 | sck: Option<PeripheralRef<'d, AnyPin>>, | ||
| 539 | mclk: Option<PeripheralRef<'d, AnyPin>>, | ||
| 540 | ring_buffer: RingBuffer<'d, C, W>, | ||
| 541 | sub_block: WhichSubBlock, | ||
| 542 | } | ||
| 543 | |||
| 544 | pub struct SubBlockA {} | ||
| 545 | pub struct SubBlockB {} | ||
| 546 | |||
| 547 | pub struct SubBlockAPeripheral<'d, T>(PeripheralRef<'d, T>); | ||
| 548 | pub struct SubBlockBPeripheral<'d, T>(PeripheralRef<'d, T>); | ||
| 549 | |||
| 550 | pub struct Sai<'d, T: Instance> { | ||
| 551 | _peri: PeripheralRef<'d, T>, | ||
| 552 | sub_block_a_peri: Option<SubBlockAPeripheral<'d, T>>, | ||
| 553 | sub_block_b_peri: Option<SubBlockBPeripheral<'d, T>>, | ||
| 554 | } | ||
| 555 | |||
| 556 | // return the type for (sd, sck) | 515 | // return the type for (sd, sck) |
| 557 | fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { | 516 | fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { |
| 558 | ( | 517 | ( |
| @@ -591,34 +550,6 @@ fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>( | |||
| 591 | } | 550 | } |
| 592 | } | 551 | } |
| 593 | 552 | ||
| 594 | impl<'d, T: Instance> Sai<'d, T> { | ||
| 595 | pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self { | ||
| 596 | T::enable_and_reset(); | ||
| 597 | |||
| 598 | Self { | ||
| 599 | _peri: unsafe { peri.clone_unchecked().into_ref() }, | ||
| 600 | sub_block_a_peri: Some(SubBlockAPeripheral(unsafe { peri.clone_unchecked().into_ref() })), | ||
| 601 | sub_block_b_peri: Some(SubBlockBPeripheral(peri.into_ref())), | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | pub fn take_sub_block_a(self: &mut Self) -> Option<SubBlockAPeripheral<'d, T>> { | ||
| 606 | if self.sub_block_a_peri.is_some() { | ||
| 607 | self.sub_block_a_peri.take() | ||
| 608 | } else { | ||
| 609 | None | ||
| 610 | } | ||
| 611 | } | ||
| 612 | |||
| 613 | pub fn take_sub_block_b(self: &mut Self) -> Option<SubBlockBPeripheral<'d, T>> { | ||
| 614 | if self.sub_block_b_peri.is_some() { | ||
| 615 | self.sub_block_b_peri.take() | ||
| 616 | } else { | ||
| 617 | None | ||
| 618 | } | ||
| 619 | } | ||
| 620 | } | ||
| 621 | |||
| 622 | fn update_synchronous_config(config: &mut Config) { | 553 | fn update_synchronous_config(config: &mut Config) { |
| 623 | config.mode = Mode::Slave; | 554 | config.mode = Mode::Slave; |
| 624 | config.sync_output = false; | 555 | config.sync_output = false; |
| @@ -636,122 +567,58 @@ fn update_synchronous_config(config: &mut Config) { | |||
| 636 | } | 567 | } |
| 637 | } | 568 | } |
| 638 | 569 | ||
| 639 | impl SubBlockA { | 570 | /// SAI subblock instance. |
| 640 | pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( | 571 | pub struct SubBlock<'d, T, S: SubBlockInstance> { |
| 641 | peri: SubBlockAPeripheral<'d, T>, | 572 | peri: PeripheralRef<'d, T>, |
| 642 | sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | 573 | _phantom: PhantomData<S>, |
| 643 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | 574 | } |
| 644 | fs: impl Peripheral<P = impl FsAPin<T>> + 'd, | ||
| 645 | mclk: impl Peripheral<P = impl MclkAPin<T>> + 'd, | ||
| 646 | dma: impl Peripheral<P = C> + 'd, | ||
| 647 | dma_buf: &'d mut [W], | ||
| 648 | mut config: Config, | ||
| 649 | ) -> SubBlock<'d, T, C, W> | ||
| 650 | where | ||
| 651 | C: Channel + DmaA<T>, | ||
| 652 | { | ||
| 653 | into_ref!(mclk); | ||
| 654 | |||
| 655 | let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); | ||
| 656 | |||
| 657 | mclk.set_as_af(mclk.af_num(), ck_af_type); | ||
| 658 | mclk.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 659 | |||
| 660 | if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { | ||
| 661 | config.master_clock_divider = MasterClockDivider::Div1; | ||
| 662 | } | ||
| 663 | |||
| 664 | Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) | ||
| 665 | } | ||
| 666 | |||
| 667 | pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( | ||
| 668 | peri: SubBlockAPeripheral<'d, T>, | ||
| 669 | sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | ||
| 670 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||
| 671 | fs: impl Peripheral<P = impl FsAPin<T>> + 'd, | ||
| 672 | dma: impl Peripheral<P = C> + 'd, | ||
| 673 | dma_buf: &'d mut [W], | ||
| 674 | config: Config, | ||
| 675 | ) -> SubBlock<'d, T, C, W> | ||
| 676 | where | ||
| 677 | C: Channel + DmaA<T>, | ||
| 678 | { | ||
| 679 | let peri = peri.0; | ||
| 680 | into_ref!(peri, dma, sck, sd, fs); | ||
| 681 | |||
| 682 | let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); | ||
| 683 | sd.set_as_af(sd.af_num(), sd_af_type); | ||
| 684 | sd.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 685 | |||
| 686 | sck.set_as_af(sck.af_num(), ck_af_type); | ||
| 687 | sck.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 688 | fs.set_as_af(fs.af_num(), ck_af_type); | ||
| 689 | fs.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 690 | 575 | ||
| 691 | let sub_block = WhichSubBlock::A; | 576 | /// Split the main SAIx peripheral into the two subblocks. |
| 692 | let request = dma.request(); | 577 | /// |
| 578 | /// You can then create a [`Sai`] driver for each each half. | ||
| 579 | pub fn split_subblocks<'d, T: Instance>(peri: impl Peripheral<P = T> + 'd) -> (SubBlock<'d, T, A>, SubBlock<'d, T, B>) { | ||
| 580 | into_ref!(peri); | ||
| 581 | T::enable_and_reset(); | ||
| 693 | 582 | ||
| 694 | SubBlock::new_inner( | 583 | ( |
| 584 | SubBlock { | ||
| 585 | peri: unsafe { peri.clone_unchecked() }, | ||
| 586 | _phantom: PhantomData, | ||
| 587 | }, | ||
| 588 | SubBlock { | ||
| 695 | peri, | 589 | peri, |
| 696 | sub_block, | 590 | _phantom: PhantomData, |
| 697 | Some(sck.map_into()), | 591 | }, |
| 698 | None, | 592 | ) |
| 699 | Some(sd.map_into()), | 593 | } |
| 700 | Some(fs.map_into()), | ||
| 701 | get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), | ||
| 702 | config, | ||
| 703 | ) | ||
| 704 | } | ||
| 705 | |||
| 706 | pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( | ||
| 707 | peri: SubBlockAPeripheral<'d, T>, | ||
| 708 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||
| 709 | dma: impl Peripheral<P = C> + 'd, | ||
| 710 | dma_buf: &'d mut [W], | ||
| 711 | mut config: Config, | ||
| 712 | ) -> SubBlock<'d, T, C, W> | ||
| 713 | where | ||
| 714 | C: Channel + DmaA<T>, | ||
| 715 | { | ||
| 716 | update_synchronous_config(&mut config); | ||
| 717 | |||
| 718 | let peri = peri.0; | ||
| 719 | into_ref!(dma, peri, sd); | ||
| 720 | |||
| 721 | let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); | ||
| 722 | |||
| 723 | sd.set_as_af(sd.af_num(), sd_af_type); | ||
| 724 | sd.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 725 | |||
| 726 | let sub_block = WhichSubBlock::A; | ||
| 727 | let request = dma.request(); | ||
| 728 | 594 | ||
| 729 | SubBlock::new_inner( | 595 | /// SAI sub-block driver. |
| 730 | peri, | 596 | pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { |
| 731 | sub_block, | 597 | _peri: PeripheralRef<'d, T>, |
| 732 | None, | 598 | sd: Option<PeripheralRef<'d, AnyPin>>, |
| 733 | None, | 599 | fs: Option<PeripheralRef<'d, AnyPin>>, |
| 734 | Some(sd.map_into()), | 600 | sck: Option<PeripheralRef<'d, AnyPin>>, |
| 735 | None, | 601 | mclk: Option<PeripheralRef<'d, AnyPin>>, |
| 736 | get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), | 602 | ring_buffer: RingBuffer<'d, C, W>, |
| 737 | config, | 603 | sub_block: WhichSubBlock, |
| 738 | ) | ||
| 739 | } | ||
| 740 | } | 604 | } |
| 741 | 605 | ||
| 742 | impl SubBlockB { | 606 | impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { |
| 743 | pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( | 607 | /// Create a new SAI driver in asynchronous mode with MCLK. |
| 744 | peri: SubBlockBPeripheral<'d, T>, | 608 | /// |
| 745 | sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | 609 | /// You can obtain the [`SubBlock`] with [`split_subblocks`]. |
| 746 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | 610 | pub fn new_asynchronous_with_mclk<S: SubBlockInstance>( |
| 747 | fs: impl Peripheral<P = impl FsBPin<T>> + 'd, | 611 | peri: SubBlock<'d, T, S>, |
| 748 | mclk: impl Peripheral<P = impl MclkBPin<T>> + 'd, | 612 | sck: impl Peripheral<P = impl SckPin<T, S>> + 'd, |
| 613 | sd: impl Peripheral<P = impl SdPin<T, S>> + 'd, | ||
| 614 | fs: impl Peripheral<P = impl FsPin<T, S>> + 'd, | ||
| 615 | mclk: impl Peripheral<P = impl MclkPin<T, S>> + 'd, | ||
| 749 | dma: impl Peripheral<P = C> + 'd, | 616 | dma: impl Peripheral<P = C> + 'd, |
| 750 | dma_buf: &'d mut [W], | 617 | dma_buf: &'d mut [W], |
| 751 | mut config: Config, | 618 | mut config: Config, |
| 752 | ) -> SubBlock<'d, T, C, W> | 619 | ) -> Self |
| 753 | where | 620 | where |
| 754 | C: Channel + DmaB<T>, | 621 | C: Channel + Dma<T, S>, |
| 755 | { | 622 | { |
| 756 | into_ref!(mclk); | 623 | into_ref!(mclk); |
| 757 | 624 | ||
| @@ -767,23 +634,25 @@ impl SubBlockB { | |||
| 767 | Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) | 634 | Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) |
| 768 | } | 635 | } |
| 769 | 636 | ||
| 770 | pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( | 637 | /// Create a new SAI driver in asynchronous mode without MCLK. |
| 771 | peri: SubBlockBPeripheral<'d, T>, | 638 | /// |
| 772 | sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | 639 | /// You can obtain the [`SubBlock`] with [`split_subblocks`]. |
| 773 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | 640 | pub fn new_asynchronous<S: SubBlockInstance>( |
| 774 | fs: impl Peripheral<P = impl FsBPin<T>> + 'd, | 641 | peri: SubBlock<'d, T, S>, |
| 642 | sck: impl Peripheral<P = impl SckPin<T, S>> + 'd, | ||
| 643 | sd: impl Peripheral<P = impl SdPin<T, S>> + 'd, | ||
| 644 | fs: impl Peripheral<P = impl FsPin<T, S>> + 'd, | ||
| 775 | dma: impl Peripheral<P = C> + 'd, | 645 | dma: impl Peripheral<P = C> + 'd, |
| 776 | dma_buf: &'d mut [W], | 646 | dma_buf: &'d mut [W], |
| 777 | config: Config, | 647 | config: Config, |
| 778 | ) -> SubBlock<'d, T, C, W> | 648 | ) -> Self |
| 779 | where | 649 | where |
| 780 | C: Channel + DmaB<T>, | 650 | C: Channel + Dma<T, S>, |
| 781 | { | 651 | { |
| 782 | let peri = peri.0; | 652 | let peri = peri.peri; |
| 783 | into_ref!(dma, peri, sck, sd, fs); | 653 | into_ref!(peri, dma, sck, sd, fs); |
| 784 | 654 | ||
| 785 | let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); | 655 | let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); |
| 786 | |||
| 787 | sd.set_as_af(sd.af_num(), sd_af_type); | 656 | sd.set_as_af(sd.af_num(), sd_af_type); |
| 788 | sd.set_speed(crate::gpio::Speed::VeryHigh); | 657 | sd.set_speed(crate::gpio::Speed::VeryHigh); |
| 789 | 658 | ||
| @@ -792,10 +661,10 @@ impl SubBlockB { | |||
| 792 | fs.set_as_af(fs.af_num(), ck_af_type); | 661 | fs.set_as_af(fs.af_num(), ck_af_type); |
| 793 | fs.set_speed(crate::gpio::Speed::VeryHigh); | 662 | fs.set_speed(crate::gpio::Speed::VeryHigh); |
| 794 | 663 | ||
| 795 | let sub_block = WhichSubBlock::B; | 664 | let sub_block = S::WHICH; |
| 796 | let request = dma.request(); | 665 | let request = dma.request(); |
| 797 | 666 | ||
| 798 | SubBlock::new_inner( | 667 | Self::new_inner( |
| 799 | peri, | 668 | peri, |
| 800 | sub_block, | 669 | sub_block, |
| 801 | Some(sck.map_into()), | 670 | Some(sck.map_into()), |
| @@ -807,18 +676,22 @@ impl SubBlockB { | |||
| 807 | ) | 676 | ) |
| 808 | } | 677 | } |
| 809 | 678 | ||
| 810 | pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( | 679 | /// Create a new SAI driver in synchronous mode. |
| 811 | peri: SubBlockBPeripheral<'d, T>, | 680 | /// |
| 812 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | 681 | /// You can obtain the [`SubBlock`] with [`split_subblocks`]. |
| 682 | pub fn new_synchronous<S: SubBlockInstance>( | ||
| 683 | peri: SubBlock<'d, T, S>, | ||
| 684 | sd: impl Peripheral<P = impl SdPin<T, S>> + 'd, | ||
| 813 | dma: impl Peripheral<P = C> + 'd, | 685 | dma: impl Peripheral<P = C> + 'd, |
| 814 | dma_buf: &'d mut [W], | 686 | dma_buf: &'d mut [W], |
| 815 | mut config: Config, | 687 | mut config: Config, |
| 816 | ) -> SubBlock<'d, T, C, W> | 688 | ) -> Self |
| 817 | where | 689 | where |
| 818 | C: Channel + DmaB<T>, | 690 | C: Channel + Dma<T, S>, |
| 819 | { | 691 | { |
| 820 | update_synchronous_config(&mut config); | 692 | update_synchronous_config(&mut config); |
| 821 | let peri = peri.0; | 693 | |
| 694 | let peri = peri.peri; | ||
| 822 | into_ref!(dma, peri, sd); | 695 | into_ref!(dma, peri, sd); |
| 823 | 696 | ||
| 824 | let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); | 697 | let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); |
| @@ -826,10 +699,10 @@ impl SubBlockB { | |||
| 826 | sd.set_as_af(sd.af_num(), sd_af_type); | 699 | sd.set_as_af(sd.af_num(), sd_af_type); |
| 827 | sd.set_speed(crate::gpio::Speed::VeryHigh); | 700 | sd.set_speed(crate::gpio::Speed::VeryHigh); |
| 828 | 701 | ||
| 829 | let sub_block = WhichSubBlock::B; | 702 | let sub_block = S::WHICH; |
| 830 | let request = dma.request(); | 703 | let request = dma.request(); |
| 831 | 704 | ||
| 832 | SubBlock::new_inner( | 705 | Self::new_inner( |
| 833 | peri, | 706 | peri, |
| 834 | sub_block, | 707 | sub_block, |
| 835 | None, | 708 | None, |
| @@ -840,26 +713,6 @@ impl SubBlockB { | |||
| 840 | config, | 713 | config, |
| 841 | ) | 714 | ) |
| 842 | } | 715 | } |
| 843 | } | ||
| 844 | |||
| 845 | impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | ||
| 846 | pub fn start(self: &mut Self) { | ||
| 847 | match self.ring_buffer { | ||
| 848 | RingBuffer::Writable(ref mut rb) => { | ||
| 849 | rb.start(); | ||
| 850 | } | ||
| 851 | RingBuffer::Readable(ref mut rb) => { | ||
| 852 | rb.start(); | ||
| 853 | } | ||
| 854 | } | ||
| 855 | } | ||
| 856 | |||
| 857 | fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool { | ||
| 858 | match ring_buffer { | ||
| 859 | RingBuffer::Writable(_) => true, | ||
| 860 | _ => false, | ||
| 861 | } | ||
| 862 | } | ||
| 863 | 716 | ||
| 864 | fn new_inner( | 717 | fn new_inner( |
| 865 | peri: impl Peripheral<P = T> + 'd, | 718 | peri: impl Peripheral<P = T> + 'd, |
| @@ -929,7 +782,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | |||
| 929 | w.set_cpl(config.complement_format.cpl()); | 782 | w.set_cpl(config.complement_format.cpl()); |
| 930 | w.set_muteval(config.mute_value.muteval()); | 783 | w.set_muteval(config.mute_value.muteval()); |
| 931 | w.set_mutecnt(config.mute_detection_counter.0 as u8); | 784 | w.set_mutecnt(config.mute_detection_counter.0 as u8); |
| 932 | w.set_tris(config.is_high_impedenane_on_inactive_slot); | 785 | w.set_tris(config.is_high_impedance_on_inactive_slot); |
| 933 | }); | 786 | }); |
| 934 | 787 | ||
| 935 | ch.frcr().modify(|w| { | 788 | ch.frcr().modify(|w| { |
| @@ -965,10 +818,31 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | |||
| 965 | } | 818 | } |
| 966 | } | 819 | } |
| 967 | 820 | ||
| 821 | /// Start the SAI driver. | ||
| 822 | pub fn start(&mut self) { | ||
| 823 | match self.ring_buffer { | ||
| 824 | RingBuffer::Writable(ref mut rb) => { | ||
| 825 | rb.start(); | ||
| 826 | } | ||
| 827 | RingBuffer::Readable(ref mut rb) => { | ||
| 828 | rb.start(); | ||
| 829 | } | ||
| 830 | } | ||
| 831 | } | ||
| 832 | |||
| 833 | fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool { | ||
| 834 | match ring_buffer { | ||
| 835 | RingBuffer::Writable(_) => true, | ||
| 836 | _ => false, | ||
| 837 | } | ||
| 838 | } | ||
| 839 | |||
| 840 | /// Reset SAI operation. | ||
| 968 | pub fn reset() { | 841 | pub fn reset() { |
| 969 | T::enable_and_reset(); | 842 | T::enable_and_reset(); |
| 970 | } | 843 | } |
| 971 | 844 | ||
| 845 | /// Flush. | ||
| 972 | pub fn flush(&mut self) { | 846 | pub fn flush(&mut self) { |
| 973 | let ch = T::REGS.ch(self.sub_block as usize); | 847 | let ch = T::REGS.ch(self.sub_block as usize); |
| 974 | ch.cr1().modify(|w| w.set_saien(false)); | 848 | ch.cr1().modify(|w| w.set_saien(false)); |
| @@ -983,19 +857,18 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | |||
| 983 | ch.cr1().modify(|w| w.set_saien(true)); | 857 | ch.cr1().modify(|w| w.set_saien(true)); |
| 984 | } | 858 | } |
| 985 | 859 | ||
| 860 | /// Enable or disable mute. | ||
| 986 | pub fn set_mute(&mut self, value: bool) { | 861 | pub fn set_mute(&mut self, value: bool) { |
| 987 | let ch = T::REGS.ch(self.sub_block as usize); | 862 | let ch = T::REGS.ch(self.sub_block as usize); |
| 988 | ch.cr2().modify(|w| w.set_mute(value)); | 863 | ch.cr2().modify(|w| w.set_mute(value)); |
| 989 | } | 864 | } |
| 990 | 865 | ||
| 991 | #[allow(dead_code)] | 866 | /// Write data to the SAI ringbuffer. |
| 992 | /// Reconfigures it with the supplied config. | 867 | /// |
| 993 | fn reconfigure(&mut self, _config: Config) {} | 868 | /// This appends the data to the buffer and returns immediately. The |
| 994 | 869 | /// data will be transmitted in the background. | |
| 995 | pub fn get_current_config(&self) -> Config { | 870 | /// |
| 996 | Config::default() | 871 | /// If there's no space in the buffer, this waits until there is. |
| 997 | } | ||
| 998 | |||
| 999 | pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { | 872 | pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { |
| 1000 | match &mut self.ring_buffer { | 873 | match &mut self.ring_buffer { |
| 1001 | RingBuffer::Writable(buffer) => { | 874 | RingBuffer::Writable(buffer) => { |
| @@ -1006,6 +879,12 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | |||
| 1006 | } | 879 | } |
| 1007 | } | 880 | } |
| 1008 | 881 | ||
| 882 | /// Read data from the SAI ringbuffer. | ||
| 883 | /// | ||
| 884 | /// SAI is always receiving data in the background. This function pops already-received | ||
| 885 | /// data from the buffer. | ||
| 886 | /// | ||
| 887 | /// If there's less than `data.len()` data in the buffer, this waits until there is. | ||
| 1009 | pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { | 888 | pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { |
| 1010 | match &mut self.ring_buffer { | 889 | match &mut self.ring_buffer { |
| 1011 | RingBuffer::Readable(buffer) => { | 890 | RingBuffer::Readable(buffer) => { |
| @@ -1017,7 +896,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | |||
| 1017 | } | 896 | } |
| 1018 | } | 897 | } |
| 1019 | 898 | ||
| 1020 | impl<'d, T: Instance, C: Channel, W: word::Word> Drop for SubBlock<'d, T, C, W> { | 899 | impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> { |
| 1021 | fn drop(&mut self) { | 900 | fn drop(&mut self) { |
| 1022 | let ch = T::REGS.ch(self.sub_block as usize); | 901 | let ch = T::REGS.ch(self.sub_block as usize); |
| 1023 | ch.cr1().modify(|w| w.set_saien(false)); | 902 | ch.cr1().modify(|w| w.set_saien(false)); |
| @@ -1034,22 +913,43 @@ pub(crate) mod sealed { | |||
| 1034 | pub trait Instance { | 913 | pub trait Instance { |
| 1035 | const REGS: Regs; | 914 | const REGS: Regs; |
| 1036 | } | 915 | } |
| 916 | |||
| 917 | #[derive(Copy, Clone)] | ||
| 918 | pub enum WhichSubBlock { | ||
| 919 | A = 0, | ||
| 920 | B = 1, | ||
| 921 | } | ||
| 922 | |||
| 923 | pub trait SubBlock { | ||
| 924 | const WHICH: WhichSubBlock; | ||
| 925 | } | ||
| 1037 | } | 926 | } |
| 1038 | 927 | ||
| 1039 | pub trait Word: word::Word {} | 928 | /// Sub-block instance trait. |
| 929 | pub trait SubBlockInstance: sealed::SubBlock {} | ||
| 1040 | 930 | ||
| 931 | /// Sub-block A. | ||
| 932 | pub enum A {} | ||
| 933 | impl sealed::SubBlock for A { | ||
| 934 | const WHICH: WhichSubBlock = WhichSubBlock::A; | ||
| 935 | } | ||
| 936 | impl SubBlockInstance for A {} | ||
| 937 | |||
| 938 | /// Sub-block B. | ||
| 939 | pub enum B {} | ||
| 940 | impl sealed::SubBlock for B { | ||
| 941 | const WHICH: WhichSubBlock = WhichSubBlock::B; | ||
| 942 | } | ||
| 943 | impl SubBlockInstance for B {} | ||
| 944 | |||
| 945 | /// SAI instance trait. | ||
| 1041 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} | 946 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} |
| 1042 | pin_trait!(SckAPin, Instance); | 947 | pin_trait!(SckPin, Instance, SubBlockInstance); |
| 1043 | pin_trait!(SckBPin, Instance); | 948 | pin_trait!(FsPin, Instance, SubBlockInstance); |
| 1044 | pin_trait!(FsAPin, Instance); | 949 | pin_trait!(SdPin, Instance, SubBlockInstance); |
| 1045 | pin_trait!(FsBPin, Instance); | 950 | pin_trait!(MclkPin, Instance, SubBlockInstance); |
| 1046 | pin_trait!(SdAPin, Instance); | 951 | |
| 1047 | pin_trait!(SdBPin, Instance); | 952 | dma_trait!(Dma, Instance, SubBlockInstance); |
| 1048 | pin_trait!(MclkAPin, Instance); | ||
| 1049 | pin_trait!(MclkBPin, Instance); | ||
| 1050 | |||
| 1051 | dma_trait!(DmaA, Instance); | ||
| 1052 | dma_trait!(DmaB, Instance); | ||
| 1053 | 953 | ||
| 1054 | foreach_peripheral!( | 954 | foreach_peripheral!( |
| 1055 | (sai, $inst:ident) => { | 955 | (sai, $inst:ident) => { |
| @@ -1060,13 +960,3 @@ foreach_peripheral!( | |||
| 1060 | impl Instance for peripherals::$inst {} | 960 | impl Instance for peripherals::$inst {} |
| 1061 | }; | 961 | }; |
| 1062 | ); | 962 | ); |
| 1063 | |||
| 1064 | impl<'d, T: Instance> SetConfig for Sai<'d, T> { | ||
| 1065 | type Config = Config; | ||
| 1066 | type ConfigError = (); | ||
| 1067 | fn set_config(&mut self, _config: &Self::Config) -> Result<(), ()> { | ||
| 1068 | // self.reconfigure(*config); | ||
| 1069 | |||
| 1070 | Ok(()) | ||
| 1071 | } | ||
| 1072 | } | ||
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 27a12062c..6099b9f43 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Secure Digital / MultiMedia Card (SDMMC) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | use core::default::Default; | 4 | use core::default::Default; |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 92599c75e..5a1ad3e91 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Serial Peripheral Interface (SPI) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | use core::ptr; | 4 | use core::ptr; |
diff --git a/embassy-stm32/src/traits.rs b/embassy-stm32/src/traits.rs index b4166e71a..13f695821 100644 --- a/embassy-stm32/src/traits.rs +++ b/embassy-stm32/src/traits.rs | |||
| @@ -1,18 +1,18 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | macro_rules! pin_trait { | 3 | macro_rules! pin_trait { |
| 4 | ($signal:ident, $instance:path) => { | 4 | ($signal:ident, $instance:path $(, $mode:path)?) => { |
| 5 | #[doc = concat!(stringify!($signal), " pin trait")] | 5 | #[doc = concat!(stringify!($signal), " pin trait")] |
| 6 | pub trait $signal<T: $instance>: crate::gpio::Pin { | 6 | pub trait $signal<T: $instance $(, M: $mode)?>: crate::gpio::Pin { |
| 7 | #[doc = concat!("Get the AF number needed to use this pin as", stringify!($signal))] | 7 | #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))] |
| 8 | fn af_num(&self) -> u8; | 8 | fn af_num(&self) -> u8; |
| 9 | } | 9 | } |
| 10 | }; | 10 | }; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | macro_rules! pin_trait_impl { | 13 | macro_rules! pin_trait_impl { |
| 14 | (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, $af:expr) => { | 14 | (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr) => { |
| 15 | impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$pin { | 15 | impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$pin { |
| 16 | fn af_num(&self) -> u8 { | 16 | fn af_num(&self) -> u8 { |
| 17 | $af | 17 | $af |
| 18 | } | 18 | } |
| @@ -23,9 +23,9 @@ macro_rules! pin_trait_impl { | |||
| 23 | // ==================== | 23 | // ==================== |
| 24 | 24 | ||
| 25 | macro_rules! dma_trait { | 25 | macro_rules! dma_trait { |
| 26 | ($signal:ident, $instance:path) => { | 26 | ($signal:ident, $instance:path$(, $mode:path)?) => { |
| 27 | #[doc = concat!(stringify!($signal), " DMA request trait")] | 27 | #[doc = concat!(stringify!($signal), " DMA request trait")] |
| 28 | pub trait $signal<T: $instance>: crate::dma::Channel { | 28 | pub trait $signal<T: $instance $(, M: $mode)?>: crate::dma::Channel { |
| 29 | #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))] | 29 | #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))] |
| 30 | /// Note: in some chips, ST calls this the "channel", and calls channels "streams". | 30 | /// Note: in some chips, ST calls this the "channel", and calls channels "streams". |
| 31 | /// `embassy-stm32` always uses the "channel" and "request number" names. | 31 | /// `embassy-stm32` always uses the "channel" and "request number" names. |
| @@ -37,8 +37,8 @@ macro_rules! dma_trait { | |||
| 37 | #[allow(unused)] | 37 | #[allow(unused)] |
| 38 | macro_rules! dma_trait_impl { | 38 | macro_rules! dma_trait_impl { |
| 39 | // DMAMUX | 39 | // DMAMUX |
| 40 | (crate::$mod:ident::$trait:ident, $instance:ident, {dmamux: $dmamux:ident}, $request:expr) => { | 40 | (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dmamux: $dmamux:ident}, $request:expr) => { |
| 41 | impl<T> crate::$mod::$trait<crate::peripherals::$instance> for T | 41 | impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T |
| 42 | where | 42 | where |
| 43 | T: crate::dma::Channel + crate::dma::MuxChannel<Mux = crate::dma::$dmamux>, | 43 | T: crate::dma::Channel + crate::dma::MuxChannel<Mux = crate::dma::$dmamux>, |
| 44 | { | 44 | { |
| @@ -49,8 +49,8 @@ macro_rules! dma_trait_impl { | |||
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | // DMAMUX | 51 | // DMAMUX |
| 52 | (crate::$mod:ident::$trait:ident, $instance:ident, {dma: $dma:ident}, $request:expr) => { | 52 | (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dma: $dma:ident}, $request:expr) => { |
| 53 | impl<T> crate::$mod::$trait<crate::peripherals::$instance> for T | 53 | impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T |
| 54 | where | 54 | where |
| 55 | T: crate::dma::Channel, | 55 | T: crate::dma::Channel, |
| 56 | { | 56 | { |
| @@ -61,8 +61,8 @@ macro_rules! dma_trait_impl { | |||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | // DMA/GPDMA, without DMAMUX | 63 | // DMA/GPDMA, without DMAMUX |
| 64 | (crate::$mod:ident::$trait:ident, $instance:ident, {channel: $channel:ident}, $request:expr) => { | 64 | (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {channel: $channel:ident}, $request:expr) => { |
| 65 | impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$channel { | 65 | impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel { |
| 66 | fn request(&self) -> crate::dma::Request { | 66 | fn request(&self) -> crate::dma::Request { |
| 67 | $request | 67 | $request |
| 68 | } | 68 | } |
diff --git a/embassy-stm32/src/uid.rs b/embassy-stm32/src/uid.rs index 6dcfcb96e..aa13586f8 100644 --- a/embassy-stm32/src/uid.rs +++ b/embassy-stm32/src/uid.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | //! Unique ID (UID) | ||
| 2 | |||
| 1 | /// Get this device's unique 96-bit ID. | 3 | /// Get this device's unique 96-bit ID. |
| 2 | pub fn uid() -> &'static [u8; 12] { | 4 | pub fn uid() -> &'static [u8; 12] { |
| 3 | unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() } | 5 | unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() } |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index dfa1f3a6a..e2e3bd3eb 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | use core::future::poll_fn; | 4 | use core::future::poll_fn; |
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs index be54a3d10..1abd031dd 100644 --- a/embassy-stm32/src/usb_otg/mod.rs +++ b/embassy-stm32/src/usb_otg/mod.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | //! USB On The Go (OTG) | ||
| 2 | |||
| 1 | use crate::rcc::RccPeripheral; | 3 | use crate::rcc::RccPeripheral; |
| 2 | use crate::{interrupt, peripherals}; | 4 | use crate::{interrupt, peripherals}; |
| 3 | 5 | ||
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index c7c2694e0..5751a9ff3 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Watchdog Timer (IWDG, WWDG) | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | 3 | ||
| 3 | use embassy_hal_internal::{into_ref, Peripheral}; | 4 | use embassy_hal_internal::{into_ref, Peripheral}; |
