diff options
| author | Christian Perez Llamas <[email protected]> | 2022-11-10 00:10:42 +0100 |
|---|---|---|
| committer | Christian Perez Llamas <[email protected]> | 2022-11-10 00:10:42 +0100 |
| commit | 5a64bf651c66f2da16cd3ae20ed9ba2489f40d7a (patch) | |
| tree | 738479ec9d41e301be25b61ff49e8eabd073bcee | |
| parent | 356beabc3b11d78612c6958d1cfe542209e43558 (diff) | |
Buffer trait. Simpler config.
| -rw-r--r-- | embassy-nrf/src/i2s.rs | 122 | ||||
| -rw-r--r-- | examples/nrf/src/bin/i2s.rs | 7 |
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 | ||
| 369 | pub trait Buffer: Sized { | ||
| 370 | fn bytes_ptr(&self) -> *const u8; | ||
| 371 | fn bytes_len(&self) -> usize; | ||
| 372 | } | ||
| 373 | |||
| 374 | impl 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 | |||
| 386 | impl 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 | |||
| 398 | impl 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 | |||
| 404 | pub(crate) mod sealed { | 410 | pub(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 | }; |
