From f22f36f51ba4466dd15df78df0ad86ac96f9051c Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Thu, 10 Nov 2022 00:24:49 +0100 Subject: [PATCH] Add input rx --- embassy-nrf/src/i2s.rs | 59 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs index 3f5491ee..fb6fa4bd 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs @@ -166,7 +166,7 @@ pub enum Mode { /// For more details about EasyDMA, consult the module documentation. pub struct I2S<'d, T: Instance> { output: I2sOutput<'d, T>, - _input: I2sInput<'d, T>, + input: I2sInput<'d, T>, } /// Transmitter interface to the UARTE peripheral obtained @@ -253,7 +253,7 @@ impl<'d, T: Instance> I2S<'d, T> { output: I2sOutput { _p: unsafe { i2s.clone_unchecked() }, }, - _input: I2sInput { _p: i2s }, + input: I2sInput { _p: i2s }, } } @@ -284,7 +284,7 @@ impl<'d, T: Instance> I2S<'d, T> { /// Stops the I2S transfer and waits until it has stopped. #[inline(always)] - pub async fn stop(&self) -> &Self { + pub async fn stop(&self) { todo!() } @@ -304,10 +304,8 @@ impl<'d, T: Instance> I2S<'d, T> { self } - /// Transmits the given `tx_buffer`. + /// Transmits the given `buffer`. /// Buffer address must be 4 byte aligned and located in RAM. - /// Returns a value that represents the in-progress DMA transfer. - #[allow(unused_mut)] pub async fn tx(&mut self, buffer: B) -> Result<(), Error> where B: Buffer, @@ -315,6 +313,15 @@ impl<'d, T: Instance> I2S<'d, T> { self.output.tx(buffer).await } + /// Receives data into the given `buffer` until it's filled. + /// Buffer address must be 4 byte aligned and located in RAM. + pub async fn rx(&mut self, buffer: B) -> Result<(), Error> + where + B: Buffer, + { + self.input.rx(buffer).await + } + fn apply_config(c: &CONFIG, config: &Config) { // TODO support slave too c.mcken.write(|w| w.mcken().enabled()); @@ -331,9 +338,9 @@ impl<'d, T: Instance> I2S<'d, T> { } impl<'d, T: Instance> I2sOutput<'d, T> { - /// Transmits the given `tx_buffer`. + /// Transmits the given `buffer`. /// Buffer address must be 4 byte aligned and located in RAM. - /// Returns a value that represents the in-progress DMA transfer. + #[allow(unused_mut)] pub async fn tx(&mut self, buffer: B) -> Result<(), Error> where B: Buffer, @@ -366,6 +373,42 @@ impl<'d, T: Instance> I2sOutput<'d, T> { } } +impl<'d, T: Instance> I2sInput<'d, T> { + /// Receives into the given `buffer`. + /// Buffer address must be 4 byte aligned and located in RAM. + #[allow(unused_mut)] + pub async fn rx(&mut self, buffer: B) -> Result<(), Error> + where + B: Buffer, + { + let ptr = buffer.bytes_ptr(); + let len = buffer.bytes_len(); + + if ptr as u32 % 4 != 0 { + return Err(Error::BufferMisaligned); + } + if (ptr as usize) < SRAM_LOWER || (ptr as usize) > SRAM_UPPER { + return Err(Error::DMABufferNotInDataMemory); + } + let maxcnt = ((len + core::mem::size_of::() - 1) / core::mem::size_of::()) as u32; + if maxcnt > MAX_DMA_MAXCNT { + return Err(Error::BufferTooLong); + } + + let r = T::regs(); + let _s = T::state(); + + // TODO we can not progress until the last buffer written in RXD.PTR + // has started the transmission. + // We can use some sync primitive from `embassy-sync`. + + r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); + r.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) }); + + Ok(()) + } +} + pub trait Buffer: Sized { fn bytes_ptr(&self) -> *const u8; fn bytes_len(&self) -> usize;