aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/i2s.rs122
-rw-r--r--examples/nrf/src/bin/i2s.rs7
2 files changed, 66 insertions, 63 deletions
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs
index 8752dfdef..3f5491ee3 100644
--- a/embassy-nrf/src/i2s.rs
+++ b/embassy-nrf/src/i2s.rs
@@ -284,7 +284,7 @@ impl<'d, T: Instance> I2S<'d, T> {
284 284
285 /// Stops the I2S transfer and waits until it has stopped. 285 /// Stops the I2S transfer and waits until it has stopped.
286 #[inline(always)] 286 #[inline(always)]
287 pub fn stop(&self) -> &Self { 287 pub async fn stop(&self) -> &Self {
288 todo!() 288 todo!()
289 } 289 }
290 290
@@ -307,10 +307,12 @@ impl<'d, T: Instance> I2S<'d, T> {
307 /// Transmits the given `tx_buffer`. 307 /// Transmits the given `tx_buffer`.
308 /// Buffer address must be 4 byte aligned and located in RAM. 308 /// Buffer address must be 4 byte aligned and located in RAM.
309 /// Returns a value that represents the in-progress DMA transfer. 309 /// Returns a value that represents the in-progress DMA transfer.
310 // TODO Define a better interface for the input buffer
311 #[allow(unused_mut)] 310 #[allow(unused_mut)]
312 pub async fn tx(&mut self, ptr: *const u8, len: usize) -> Result<(), Error> { 311 pub async fn tx<B>(&mut self, buffer: B) -> Result<(), Error>
313 self.output.tx(ptr, len).await 312 where
313 B: Buffer,
314 {
315 self.output.tx(buffer).await
314 } 316 }
315 317
316 fn apply_config(c: &CONFIG, config: &Config) { 318 fn apply_config(c: &CONFIG, config: &Config) {
@@ -319,54 +321,12 @@ impl<'d, T: Instance> I2S<'d, T> {
319 c.mckfreq.write(|w| w.mckfreq()._32mdiv16()); 321 c.mckfreq.write(|w| w.mckfreq()._32mdiv16());
320 c.mode.write(|w| w.mode().master()); 322 c.mode.write(|w| w.mode().master());
321 323
322 c.ratio.write(|w| { 324 c.ratio.write(|w| unsafe { w.ratio().bits(config.ratio.into()) });
323 let ratio = w.ratio(); 325 c.swidth.write(|w| unsafe { w.swidth().bits(config.swidth.into()) });
324 match config.ratio { 326 c.align.write(|w| w.align().bit(config.align.into()));
325 Ratio::_32x => ratio._32x(), 327 c.format.write(|w| w.format().bit(config.format.into()));
326 Ratio::_48x => ratio._48x(), 328 c.channels
327 Ratio::_64x => ratio._64x(), 329 .write(|w| unsafe { w.channels().bits(config.channels.into()) });
328 Ratio::_96x => ratio._96x(),
329 Ratio::_128x => ratio._128x(),
330 Ratio::_192x => ratio._192x(),
331 Ratio::_256x => ratio._256x(),
332 Ratio::_384x => ratio._384x(),
333 Ratio::_512x => ratio._512x(),
334 }
335 });
336
337 c.swidth.write(|w| {
338 let swidth = w.swidth();
339 match config.swidth {
340 SampleWidth::_8bit => swidth._8bit(),
341 SampleWidth::_16bit => swidth._16bit(),
342 SampleWidth::_24bit => swidth._24bit(),
343 }
344 });
345
346 c.align.write(|w| {
347 let align = w.align();
348 match config.align {
349 Align::Left => align.left(),
350 Align::Right => align.right(),
351 }
352 });
353
354 c.format.write(|w| {
355 let format = w.format();
356 match config.format {
357 Format::I2S => format.i2s(),
358 Format::Aligned => format.aligned(),
359 }
360 });
361
362 c.channels.write(|w| {
363 let channels = w.channels();
364 match config.channels {
365 Channels::Stereo => channels.stereo(),
366 Channels::Left => channels.left(),
367 Channels::Right => channels.right(),
368 }
369 });
370 } 330 }
371} 331}
372 332
@@ -374,18 +334,23 @@ impl<'d, T: Instance> I2sOutput<'d, T> {
374 /// Transmits the given `tx_buffer`. 334 /// Transmits the given `tx_buffer`.
375 /// Buffer address must be 4 byte aligned and located in RAM. 335 /// Buffer address must be 4 byte aligned and located in RAM.
376 /// Returns a value that represents the in-progress DMA transfer. 336 /// Returns a value that represents the in-progress DMA transfer.
377 // TODO Define a better interface for the input buffer 337 pub async fn tx<B>(&mut self, buffer: B) -> Result<(), Error>
378 pub async fn tx(&mut self, ptr: *const u8, len: usize) -> Result<(), Error> { 338 where
339 B: Buffer,
340 {
341 let ptr = buffer.bytes_ptr();
342 let len = buffer.bytes_len();
343
379 if ptr as u32 % 4 != 0 { 344 if ptr as u32 % 4 != 0 {
380 return Err(Error::BufferMisaligned); 345 return Err(Error::BufferMisaligned);
381 } 346 }
382 let maxcnt = (len / (core::mem::size_of::<u32>() / core::mem::size_of::<u8>())) as u32;
383 if maxcnt > MAX_DMA_MAXCNT {
384 return Err(Error::BufferTooLong);
385 }
386 if (ptr as usize) < SRAM_LOWER || (ptr as usize) > SRAM_UPPER { 347 if (ptr as usize) < SRAM_LOWER || (ptr as usize) > SRAM_UPPER {
387 return Err(Error::DMABufferNotInDataMemory); 348 return Err(Error::DMABufferNotInDataMemory);
388 } 349 }
350 let maxcnt = ((len + core::mem::size_of::<u32>() - 1) / core::mem::size_of::<u32>()) as u32;
351 if maxcnt > MAX_DMA_MAXCNT {
352 return Err(Error::BufferTooLong);
353 }
389 354
390 let r = T::regs(); 355 let r = T::regs();
391 let _s = T::state(); 356 let _s = T::state();
@@ -401,6 +366,47 @@ impl<'d, T: Instance> I2sOutput<'d, T> {
401 } 366 }
402} 367}
403 368
369pub trait Buffer: Sized {
370 fn bytes_ptr(&self) -> *const u8;
371 fn bytes_len(&self) -> usize;
372}
373
374impl Buffer for &[u8] {
375 #[inline]
376 fn bytes_ptr(&self) -> *const u8 {
377 self.as_ptr()
378 }
379
380 #[inline]
381 fn bytes_len(&self) -> usize {
382 self.len()
383 }
384}
385
386impl Buffer for &[i16] {
387 #[inline]
388 fn bytes_ptr(&self) -> *const u8 {
389 self.as_ptr() as *const u8
390 }
391
392 #[inline]
393 fn bytes_len(&self) -> usize {
394 self.len() * core::mem::size_of::<i16>()
395 }
396}
397
398impl Buffer for &[i32] {
399 #[inline]
400 fn bytes_ptr(&self) -> *const u8 {
401 self.as_ptr() as *const u8
402 }
403
404 #[inline]
405 fn bytes_len(&self) -> usize {
406 self.len() * core::mem::size_of::<i16>()
407 }
408}
409
404pub(crate) mod sealed { 410pub(crate) mod sealed {
405 use core::sync::atomic::AtomicU8; 411 use core::sync::atomic::AtomicU8;
406 412
diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs
index a395c7141..e8ddb4a40 100644
--- a/examples/nrf/src/bin/i2s.rs
+++ b/examples/nrf/src/bin/i2s.rs
@@ -26,14 +26,11 @@ async fn main(_spawner: Spawner) {
26 signal_buf.0[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; 26 signal_buf.0[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16;
27 } 27 }
28 28
29 let ptr = &signal_buf.0 as *const i16 as *const u8;
30 let len = signal_buf.0.len() * core::mem::size_of::<i16>();
31
32 i2s.start();
33 i2s.set_tx_enabled(true); 29 i2s.set_tx_enabled(true);
30 i2s.start();
34 31
35 loop { 32 loop {
36 match i2s.tx(ptr, len).await { 33 match i2s.tx(signal_buf.0.as_slice()).await {
37 Ok(_) => todo!(), 34 Ok(_) => todo!(),
38 Err(_) => todo!(), 35 Err(_) => todo!(),
39 }; 36 };