#![macro_use]
use core::future::poll_fn;
use core::marker::PhantomData;
use core::mem::size_of;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{AtomicBool, Ordering, compiler_fence};
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{AnyPin, Pin as GpioPin, PselBits};
use crate::interrupt::typelevel::Interrupt;
use crate::pac::i2s::vals;
use crate::util::slice_in_ram_or;
use crate::{EASY_DMA_SIZE, interrupt, pac};
pub type DoubleBuffering<S, const NS: usize> = MultiBuffering<S, 2, NS>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error {
BufferTooLong,
BufferZeroLength,
BufferNotInRAM,
BufferMisaligned,
BufferLengthMisaligned,
}
#[derive(Clone)]
#[non_exhaustive]
pub struct Config {
pub sample_width: SampleWidth,
pub align: Align,
pub format: Format,
pub channels: Channels,
}
impl Default for Config {
fn default() -> Self {
Self {
sample_width: SampleWidth::_16bit,
align: Align::Left,
format: Format::I2S,
channels: Channels::Stereo,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct MasterClock {
freq: MckFreq,
ratio: Ratio,
}
impl MasterClock {
pub fn new(freq: MckFreq, ratio: Ratio) -> Self {
Self { freq, ratio }
}
}
impl MasterClock {
pub fn sample_rate(&self) -> u32 {
self.freq.to_frequency() / self.ratio.to_divisor()
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum MckFreq {
_32MDiv8,
_32MDiv10,
_32MDiv11,
_32MDiv15,
_32MDiv16,
_32MDiv21,
_32MDiv23,
_32MDiv30,
_32MDiv31,
_32MDiv32,
_32MDiv42,
_32MDiv63,
_32MDiv125,
}
impl MckFreq {
const REGISTER_VALUES: &'static [vals::Mckfreq] = &[
vals::Mckfreq::_32MDIV8,
vals::Mckfreq::_32MDIV10,
vals::Mckfreq::_32MDIV11,
vals::Mckfreq::_32MDIV15,
vals::Mckfreq::_32MDIV16,
vals::Mckfreq::_32MDIV21,
vals::Mckfreq::_32MDIV23,
vals::Mckfreq::_32MDIV30,
vals::Mckfreq::_32MDIV31,
vals::Mckfreq::_32MDIV32,
vals::Mckfreq::_32MDIV42,
vals::Mckfreq::_32MDIV63,
vals::Mckfreq::_32MDIV125,
];
const FREQUENCIES: &'static [u32] = &[
4000000, 3200000, 2909090, 2133333, 2000000, 1523809, 1391304, 1066666, 1032258, 1000000, 761904, 507936,
256000,
];
pub fn to_register_value(&self) -> vals::Mckfreq {
Self::REGISTER_VALUES[usize::from(*self)]
}
pub fn to_frequency(&self) -> u32 {
Self::FREQUENCIES[usize::from(*self)]
}
}
impl From<MckFreq> for usize {
fn from(variant: MckFreq) -> Self {
variant as _
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Ratio {
_32x,
_48x,
_64x,
_96x,
_128x,
_192x,
_256x,
_384x,
_512x,
}
impl Ratio {
const RATIOS: &'static [u32] = &[32, 48, 64, 96, 128, 192, 256, 384, 512];
pub fn to_register_value(&self) -> vals::Ratio {
vals::Ratio::from_bits(*self as u8)
}
pub fn to_divisor(&self) -> u32 {
Self::RATIOS[usize::from(*self)]
}
}
impl From<Ratio> for usize {
fn from(variant: Ratio) -> Self {
variant as _
}
}
#[derive(Clone, Copy)]
pub enum ApproxSampleRate {
_11025,
_16000,
_22050,
_32000,
_44100,
_48000,
}
impl From<ApproxSampleRate> for MasterClock {
fn from(value: ApproxSampleRate) -> Self {
match value {
ApproxSampleRate::_11025 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_192x),
ApproxSampleRate::_16000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_96x),
ApproxSampleRate::_22050 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_96x),
ApproxSampleRate::_32000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_48x),
ApproxSampleRate::_44100 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_48x),
ApproxSampleRate::_48000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_32x),
}
}
}
impl ApproxSampleRate {
pub fn sample_rate(&self) -> u32 {
MasterClock::from(*self).sample_rate()
}
}
#[derive(Clone, Copy)]
pub enum ExactSampleRate {
_8000,
_10582,
_12500,
_15625,
_15873,
_25000,
_31250,
_50000,
_62500,
_100000,
_125000,
}
impl ExactSampleRate {
pub fn sample_rate(&self) -> u32 {
MasterClock::from(*self).sample_rate()
}
}
impl From<ExactSampleRate> for MasterClock {
fn from(value: ExactSampleRate) -> Self {
match value {
ExactSampleRate::_8000 => MasterClock::new(MckFreq::_32MDiv125, Ratio::_32x),
ExactSampleRate::_10582 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_48x),
ExactSampleRate::_12500 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_256x),
ExactSampleRate::_15625 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_64x),
ExactSampleRate::_15873 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_32x),
ExactSampleRate::_25000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_128x),
ExactSampleRate::_31250 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_32x),
ExactSampleRate::_50000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_64x),
ExactSampleRate::_62500 => MasterClock::new(MckFreq::_32MDiv16, Ratio::_32x),
ExactSampleRate::_100000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_32x),
ExactSampleRate::_125000 => MasterClock::new(MckFreq::_32MDiv8, Ratio::_32x),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum SampleWidth {
_8bit,
_16bit,
_24bit,
}
impl From<SampleWidth> for vals::Swidth {
fn from(variant: SampleWidth) -> Self {
vals::Swidth::from_bits(variant as u8)
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Align {
Left,
Right,
}
impl From<Align> for vals::Align {
fn from(variant: Align) -> Self {
match variant {
Align::Left => vals::Align::LEFT,
Align::Right => vals::Align::RIGHT,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Format {
I2S,
Aligned,
}
impl From<Format> for vals::Format {
fn from(variant: Format) -> Self {
match variant {
Format::I2S => vals::Format::I2S,
Format::Aligned => vals::Format::ALIGNED,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Channels {
Stereo,
MonoLeft,
MonoRight,
}
impl From<Channels> for vals::Channels {
fn from(variant: Channels) -> Self {
vals::Channels::from_bits(variant as u8)
}
}
pub struct InterruptHandler<T: Instance> {
_phantom: PhantomData<T>,
}
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() {
let device = Device::new(T::regs());
let s = T::state();
if device.is_tx_ptr_updated() {
trace!("TX INT");
s.tx_waker.wake();
device.disable_tx_ptr_interrupt();
}
if device.is_rx_ptr_updated() {
trace!("RX INT");
s.rx_waker.wake();
device.disable_rx_ptr_interrupt();
}
if device.is_stopped() {
trace!("STOPPED INT");
s.stop_waker.wake();
device.disable_stopped_interrupt();
}
}
}
pub struct I2S<'d> {
r: pac::i2s::I2s,
state: &'static State,
mck: Option<Peri<'d, AnyPin>>,
sck: Peri<'d, AnyPin>,
lrck: Peri<'d, AnyPin>,
sdin: Option<Peri<'d, AnyPin>>,
sdout: Option<Peri<'d, AnyPin>>,
master_clock: Option<MasterClock>,
config: Config,
}
impl<'d> I2S<'d> {
pub fn new_master<T: Instance>(
_i2s: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
mck: Peri<'d, impl GpioPin>,
sck: Peri<'d, impl GpioPin>,
lrck: Peri<'d, impl GpioPin>,
master_clock: MasterClock,
config: Config,
) -> Self {
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
Self {
r: T::regs(),
state: T::state(),
mck: Some(mck.into()),
sck: sck.into(),
lrck: lrck.into(),
sdin: None,
sdout: None,
master_clock: Some(master_clock),
config,
}
}
pub fn new_slave<T: Instance>(
_i2s: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: Peri<'d, impl GpioPin>,
lrck: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
Self {
r: T::regs(),
state: T::state(),
mck: None,
sck: sck.into(),
lrck: lrck.into(),
sdin: None,
sdout: None,
master_clock: None,
config,
}
}
pub fn output<S: Sample, const NB: usize, const NS: usize>(
mut self,
sdout: Peri<'d, impl GpioPin>,
buffers: MultiBuffering<S, NB, NS>,
) -> OutputStream<'d, S, NB, NS> {
self.sdout = Some(sdout.into());
let p = self.build();
OutputStream {
r: p.0,
state: p.1,
_phantom: PhantomData,
buffers,
}
}
pub fn input<S: Sample, const NB: usize, const NS: usize>(
mut self,
sdin: Peri<'d, impl GpioPin>,
buffers: MultiBuffering<S, NB, NS>,
) -> InputStream<'d, S, NB, NS> {
self.sdin = Some(sdin.into());
let p = self.build();
InputStream {
r: p.0,
state: p.1,
buffers,
_phantom: PhantomData,
}
}
pub fn full_duplex<S: Sample, const NB: usize, const NS: usize>(
mut self,
sdin: Peri<'d, impl GpioPin>,
sdout: Peri<'d, impl GpioPin>,
buffers_out: MultiBuffering<S, NB, NS>,
buffers_in: MultiBuffering<S, NB, NS>,
) -> FullDuplexStream<'d, S, NB, NS> {
self.sdout = Some(sdout.into());
self.sdin = Some(sdin.into());
let p = self.build();
FullDuplexStream {
r: p.0,
state: p.1,
_phantom: PhantomData,
buffers_out,
buffers_in,
}
}
fn build(self) -> (pac::i2s::I2s, &'static State) {
self.apply_config();
self.select_pins();
self.setup_interrupt();
let device = Device::new(self.r);
device.enable();
(self.r, self.state)
}
fn apply_config(&self) {
let c = self.r.config();
match &self.master_clock {
Some(MasterClock { freq, ratio }) => {
c.mode().write(|w| w.set_mode(vals::Mode::MASTER));
c.mcken().write(|w| w.set_mcken(true));
c.mckfreq().write(|w| w.set_mckfreq(freq.to_register_value()));
c.ratio().write(|w| w.set_ratio(ratio.to_register_value()));
}
None => {
c.mode().write(|w| w.set_mode(vals::Mode::SLAVE));
}
};
c.swidth().write(|w| w.set_swidth(self.config.sample_width.into()));
c.align().write(|w| w.set_align(self.config.align.into()));
c.format().write(|w| w.set_format(self.config.format.into()));
c.channels().write(|w| w.set_channels(self.config.channels.into()));
}
fn select_pins(&self) {
let psel = self.r.psel();
psel.mck().write_value(self.mck.psel_bits());
psel.sck().write_value(self.sck.psel_bits());
psel.lrck().write_value(self.lrck.psel_bits());
psel.sdin().write_value(self.sdin.psel_bits());
psel.sdout().write_value(self.sdout.psel_bits());
}
fn setup_interrupt(&self) {
let device = Device::new(self.r);
device.disable_tx_ptr_interrupt();
device.disable_rx_ptr_interrupt();
device.disable_stopped_interrupt();
device.reset_tx_ptr_event();
device.reset_rx_ptr_event();
device.reset_stopped_event();
device.enable_tx_ptr_interrupt();
device.enable_rx_ptr_interrupt();
device.enable_stopped_interrupt();
}
async fn stop(r: pac::i2s::I2s, state: &State) {
compiler_fence(Ordering::SeqCst);
let device = Device::new(r);
device.stop();
state.started.store(false, Ordering::Relaxed);
poll_fn(|cx| {
state.stop_waker.register(cx.waker());
if device.is_stopped() {
trace!("STOP: Ready");
device.reset_stopped_event();
Poll::Ready(())
} else {
trace!("STOP: Pending");
Poll::Pending
}
})
.await;
device.disable();
}
async fn send_from_ram<S>(r: pac::i2s::I2s, state: &State, buffer_ptr: *const [S]) -> Result<(), Error>
where
S: Sample,
{
trace!("SEND: {}", buffer_ptr as *const S as u32);
slice_in_ram_or(buffer_ptr, Error::BufferNotInRAM)?;
compiler_fence(Ordering::SeqCst);
let device = Device::new(r);
device.update_tx(buffer_ptr)?;
Self::wait_tx_ptr_update(r, state).await;
compiler_fence(Ordering::SeqCst);
Ok(())
}
async fn wait_tx_ptr_update(r: pac::i2s::I2s, state: &State) {
let drop = OnDrop::new(move || {
trace!("TX DROP: Stopping");
let device = Device::new(r);
device.disable_tx_ptr_interrupt();
device.reset_tx_ptr_event();
device.disable_tx();
while !device.is_tx_ptr_updated() {}
trace!("TX DROP: Stopped");
});
poll_fn(|cx| {
state.tx_waker.register(cx.waker());
let device = Device::new(r);
if device.is_tx_ptr_updated() {
trace!("TX POLL: Ready");
device.reset_tx_ptr_event();
device.enable_tx_ptr_interrupt();
Poll::Ready(())
} else {
trace!("TX POLL: Pending");
Poll::Pending
}
})
.await;
drop.defuse();
}
async fn receive_from_ram<S>(r: pac::i2s::I2s, state: &State, buffer_ptr: *mut [S]) -> Result<(), Error>
where
S: Sample,
{
trace!("RECEIVE: {}", buffer_ptr as *const S as u32);
compiler_fence(Ordering::SeqCst);
let device = Device::new(r);
device.update_rx(buffer_ptr)?;
Self::wait_rx_ptr_update(r, state).await;
compiler_fence(Ordering::SeqCst);
Ok(())
}
async fn wait_rx_ptr_update(r: pac::i2s::I2s, state: &State) {
let drop = OnDrop::new(move || {
trace!("RX DROP: Stopping");
let device = Device::new(r);
device.disable_rx_ptr_interrupt();
device.reset_rx_ptr_event();
device.disable_rx();
while !device.is_rx_ptr_updated() {}
trace!("RX DROP: Stopped");
});
poll_fn(|cx| {
state.rx_waker.register(cx.waker());
let device = Device::new(r);
if device.is_rx_ptr_updated() {
trace!("RX POLL: Ready");
device.reset_rx_ptr_event();
device.enable_rx_ptr_interrupt();
Poll::Ready(())
} else {
trace!("RX POLL: Pending");
Poll::Pending
}
})
.await;
drop.defuse();
}
}
pub struct OutputStream<'d, S: Sample, const NB: usize, const NS: usize> {
r: pac::i2s::I2s,
state: &'static State,
buffers: MultiBuffering<S, NB, NS>,
_phantom: PhantomData<&'d ()>,
}
impl<'d, S: Sample, const NB: usize, const NS: usize> OutputStream<'d, S, NB, NS> {
pub fn buffer(&mut self) -> &mut [S] {
self.buffers.get_mut()
}
pub async fn start(&mut self) -> Result<(), Error>
where
S: Sample,
{
let device = Device::new(self.r);
if self.state.started.load(Ordering::Relaxed) {
self.stop().await;
}
device.enable();
device.enable_tx();
device.update_tx(self.buffers.switch())?;
self.state.started.store(true, Ordering::Relaxed);
device.start();
I2S::wait_tx_ptr_update(self.r, self.state).await;
Ok(())
}
#[inline(always)]
pub async fn stop(&self) {
I2S::stop(self.r, self.state).await
}
pub async fn send(&mut self) -> Result<(), Error>
where
S: Sample,
{
I2S::send_from_ram(self.r, self.state, self.buffers.switch()).await
}
}
pub struct InputStream<'d, S: Sample, const NB: usize, const NS: usize> {
r: pac::i2s::I2s,
state: &'static State,
buffers: MultiBuffering<S, NB, NS>,
_phantom: PhantomData<&'d ()>,
}
impl<'d, S: Sample, const NB: usize, const NS: usize> InputStream<'d, S, NB, NS> {
pub fn buffer(&mut self) -> &mut [S] {
self.buffers.get_mut()
}
pub async fn start(&mut self) -> Result<(), Error>
where
S: Sample,
{
let device = Device::new(self.r);
if self.state.started.load(Ordering::Relaxed) {
self.stop().await;
}
device.enable();
device.enable_rx();
device.update_rx(self.buffers.switch())?;
self.state.started.store(true, Ordering::Relaxed);
device.start();
I2S::wait_rx_ptr_update(self.r, self.state).await;
Ok(())
}
#[inline(always)]
pub async fn stop(&self) {
I2S::stop(self.r, self.state).await
}
#[allow(unused_mut)]
pub async fn receive(&mut self) -> Result<(), Error>
where
S: Sample,
{
I2S::receive_from_ram(self.r, self.state, self.buffers.switch_mut()).await
}
}
pub struct FullDuplexStream<'d, S: Sample, const NB: usize, const NS: usize> {
r: pac::i2s::I2s,
state: &'static State,
buffers_out: MultiBuffering<S, NB, NS>,
buffers_in: MultiBuffering<S, NB, NS>,
_phantom: PhantomData<&'d ()>,
}
impl<'d, S: Sample, const NB: usize, const NS: usize> FullDuplexStream<'d, S, NB, NS> {
pub fn buffers(&mut self) -> (&mut [S], &[S]) {
(self.buffers_out.get_mut(), self.buffers_in.get())
}
pub async fn start(&mut self) -> Result<(), Error>
where
S: Sample,
{
let device = Device::new(self.r);
if self.state.started.load(Ordering::Relaxed) {
self.stop().await;
}
device.enable();
device.enable_tx();
device.enable_rx();
device.update_tx(self.buffers_out.switch())?;
device.update_rx(self.buffers_in.switch_mut())?;
self.state.started.store(true, Ordering::Relaxed);
device.start();
I2S::wait_tx_ptr_update(self.r, self.state).await;
I2S::wait_rx_ptr_update(self.r, self.state).await;
Ok(())
}
#[inline(always)]
pub async fn stop(&self) {
I2S::stop(self.r, self.state).await
}
pub async fn send_and_receive(&mut self) -> Result<(), Error>
where
S: Sample,
{
I2S::send_from_ram(self.r, self.state, self.buffers_out.switch()).await?;
I2S::receive_from_ram(self.r, self.state, self.buffers_in.switch_mut()).await?;
Ok(())
}
}
struct Device(pac::i2s::I2s);
impl Device {
fn new(r: pac::i2s::I2s) -> Self {
Self(r)
}
#[inline(always)]
pub fn enable(&self) {
trace!("ENABLED");
self.0.enable().write(|w| w.set_enable(true));
}
#[inline(always)]
pub fn disable(&self) {
trace!("DISABLED");
self.0.enable().write(|w| w.set_enable(false));
}
#[inline(always)]
fn enable_tx(&self) {
trace!("TX ENABLED");
self.0.config().txen().write(|w| w.set_txen(true));
}
#[inline(always)]
fn disable_tx(&self) {
trace!("TX DISABLED");
self.0.config().txen().write(|w| w.set_txen(false));
}
#[inline(always)]
fn enable_rx(&self) {
trace!("RX ENABLED");
self.0.config().rxen().write(|w| w.set_rxen(true));
}
#[inline(always)]
fn disable_rx(&self) {
trace!("RX DISABLED");
self.0.config().rxen().write(|w| w.set_rxen(false));
}
#[inline(always)]
fn start(&self) {
trace!("START");
self.0.tasks_start().write_value(1);
}
#[inline(always)]
fn stop(&self) {
self.0.tasks_stop().write_value(1);
}
#[inline(always)]
fn is_stopped(&self) -> bool {
self.0.events_stopped().read() != 0
}
#[inline(always)]
fn reset_stopped_event(&self) {
trace!("STOPPED EVENT: Reset");
self.0.events_stopped().write_value(0);
}
#[inline(always)]
fn disable_stopped_interrupt(&self) {
trace!("STOPPED INTERRUPT: Disabled");
self.0.intenclr().write(|w| w.set_stopped(true));
}
#[inline(always)]
fn enable_stopped_interrupt(&self) {
trace!("STOPPED INTERRUPT: Enabled");
self.0.intenset().write(|w| w.set_stopped(true));
}
#[inline(always)]
fn reset_tx_ptr_event(&self) {
trace!("TX PTR EVENT: Reset");
self.0.events_txptrupd().write_value(0);
}
#[inline(always)]
fn reset_rx_ptr_event(&self) {
trace!("RX PTR EVENT: Reset");
self.0.events_rxptrupd().write_value(0);
}
#[inline(always)]
fn disable_tx_ptr_interrupt(&self) {
trace!("TX PTR INTERRUPT: Disabled");
self.0.intenclr().write(|w| w.set_txptrupd(true));
}
#[inline(always)]
fn disable_rx_ptr_interrupt(&self) {
trace!("RX PTR INTERRUPT: Disabled");
self.0.intenclr().write(|w| w.set_rxptrupd(true));
}
#[inline(always)]
fn enable_tx_ptr_interrupt(&self) {
trace!("TX PTR INTERRUPT: Enabled");
self.0.intenset().write(|w| w.set_txptrupd(true));
}
#[inline(always)]
fn enable_rx_ptr_interrupt(&self) {
trace!("RX PTR INTERRUPT: Enabled");
self.0.intenset().write(|w| w.set_rxptrupd(true));
}
#[inline(always)]
fn is_tx_ptr_updated(&self) -> bool {
self.0.events_txptrupd().read() != 0
}
#[inline(always)]
fn is_rx_ptr_updated(&self) -> bool {
self.0.events_rxptrupd().read() != 0
}
#[inline]
fn update_tx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
self.0.rxtxd().maxcnt().write(|w| w.0 = maxcnt);
self.0.txd().ptr().write_value(ptr);
Ok(())
}
#[inline]
fn update_rx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
self.0.rxtxd().maxcnt().write(|w| w.0 = maxcnt);
self.0.rxd().ptr().write_value(ptr);
Ok(())
}
fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> {
let ptr = buffer_ptr as *const S as u32;
let bytes_len = buffer_ptr.len() * size_of::<S>();
let maxcnt = (bytes_len / size_of::<u32>()) as u32;
trace!("PTR={}, MAXCNT={}", ptr, maxcnt);
if ptr % 4 != 0 {
Err(Error::BufferMisaligned)
} else if bytes_len % 4 != 0 {
Err(Error::BufferLengthMisaligned)
} else if maxcnt as usize > EASY_DMA_SIZE {
Err(Error::BufferTooLong)
} else {
Ok((ptr, maxcnt))
}
}
}
pub trait Sample: Sized + Copy + Default {
const WIDTH: usize;
const SCALE: Self;
}
impl Sample for i8 {
const WIDTH: usize = 8;
const SCALE: Self = 1 << (Self::WIDTH - 1);
}
impl Sample for i16 {
const WIDTH: usize = 16;
const SCALE: Self = 1 << (Self::WIDTH - 1);
}
impl Sample for i32 {
const WIDTH: usize = 24;
const SCALE: Self = 1 << (Self::WIDTH - 1);
}
#[derive(Clone, Copy)]
#[repr(align(4))]
pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]);
impl<T: Sample, const N: usize> AlignedBuffer<T, N> {
pub fn new(array: [T; N]) -> Self {
Self(array)
}
}
impl<T: Sample, const N: usize> Default for AlignedBuffer<T, N> {
fn default() -> Self {
Self([T::default(); N])
}
}
impl<T: Sample, const N: usize> Deref for AlignedBuffer<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.0.as_slice()
}
}
impl<T: Sample, const N: usize> DerefMut for AlignedBuffer<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.as_mut_slice()
}
}
pub struct MultiBuffering<S: Sample, const NB: usize, const NS: usize> {
buffers: [AlignedBuffer<S, NS>; NB],
index: usize,
}
impl<S: Sample, const NB: usize, const NS: usize> MultiBuffering<S, NB, NS> {
pub fn new() -> Self {
assert!(NB > 1);
Self {
buffers: [AlignedBuffer::<S, NS>::default(); NB],
index: 0,
}
}
fn get(&self) -> &[S] {
&self.buffers[self.index]
}
fn get_mut(&mut self) -> &mut [S] {
&mut self.buffers[self.index]
}
fn switch(&mut self) -> *const [S] {
let prev_index = self.index;
self.index = (self.index + 1) % NB;
self.buffers[prev_index].deref() as *const [S]
}
fn switch_mut(&mut self) -> *mut [S] {
let prev_index = self.index;
self.index = (self.index + 1) % NB;
self.buffers[prev_index].deref_mut() as *mut [S]
}
}
pub(crate) struct State {
started: AtomicBool,
rx_waker: AtomicWaker,
tx_waker: AtomicWaker,
stop_waker: AtomicWaker,
}
impl State {
pub(crate) const fn new() -> Self {
Self {
started: AtomicBool::new(false),
rx_waker: AtomicWaker::new(),
tx_waker: AtomicWaker::new(),
stop_waker: AtomicWaker::new(),
}
}
}
pub(crate) trait SealedInstance {
fn regs() -> pac::i2s::I2s;
fn state() -> &'static State;
}
#[allow(private_bounds)]
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
type Interrupt: interrupt::typelevel::Interrupt;
}
macro_rules! impl_i2s {
($type:ident, $pac_type:ident, $irq:ident) => {
impl crate::i2s::SealedInstance for peripherals::$type {
fn regs() -> pac::i2s::I2s {
pac::$pac_type
}
fn state() -> &'static crate::i2s::State {
static STATE: crate::i2s::State = crate::i2s::State::new();
&STATE
}
}
impl crate::i2s::Instance for peripherals::$type {
type Interrupt = crate::interrupt::typelevel::$irq;
}
};
}