aboutsummaryrefslogtreecommitdiff
path: root/examples/rp235x/src
diff options
context:
space:
mode:
authorThor McAvenia <[email protected]>2025-05-16 00:09:10 -0700
committerDario Nieuwenhuis <[email protected]>2025-09-05 21:01:37 +0200
commit241129c569023dc71d0025cdc41bcfe40418e7b8 (patch)
tree2a6bf63e2deef67efd0d9f71e86d651d37a0a125 /examples/rp235x/src
parent4ac4452c16e1b75bcf70814a9530b7724cc16e7d (diff)
Add PioI2sIn, PioI2sInProgram, and example binary
Diffstat (limited to 'examples/rp235x/src')
-rw-r--r--examples/rp235x/src/bin/pio_i2s_rx.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/examples/rp235x/src/bin/pio_i2s_rx.rs b/examples/rp235x/src/bin/pio_i2s_rx.rs
new file mode 100644
index 000000000..c3f505b13
--- /dev/null
+++ b/examples/rp235x/src/bin/pio_i2s_rx.rs
@@ -0,0 +1,81 @@
1//! This example shows receiving audio from a connected I2S microphone (or other audio source)
2//! using the PIO module of the RP235x.
3//!
4//!
5//! Connect the i2s microphone as follows:
6//! bclk : GPIO 18
7//! lrc : GPIO 19
8//! din : GPIO 20
9//! Then hold down the boot select button to begin receiving audio. Received I2S words will be written to
10//! buffers for the left and right channels for use in your application, whether that's storage or
11//! further processing
12//!
13//! Note the const USE_ONBOARD_PULLDOWN is by default set to false, meaning an external
14//! pull-down resistor is being used on the data pin if required by the mic being used.
15
16#![no_std]
17#![no_main]
18use core::mem;
19
20use defmt::*;
21use embassy_executor::Spawner;
22use embassy_rp::bind_interrupts;
23use embassy_rp::peripherals::PIO0;
24use embassy_rp::pio::{InterruptHandler, Pio};
25use embassy_rp::pio_programs::i2s::{PioI2sIn, PioI2sInProgram};
26use static_cell::StaticCell;
27use {defmt_rtt as _, panic_probe as _};
28
29bind_interrupts!(struct Irqs {
30 PIO0_IRQ_0 => InterruptHandler<PIO0>;
31});
32
33const SAMPLE_RATE: u32 = 48_000;
34const BIT_DEPTH: u32 = 16;
35const CHANNELS: u32 = 2;
36const USE_ONBOARD_PULLDOWN: bool = false; // whether or not to use the onboard pull-down resistor,
37 // which has documented issues on many RP235x boards
38#[embassy_executor::main]
39async fn main(_spawner: Spawner) {
40 let p = embassy_rp::init(Default::default());
41
42 // Setup pio state machine for i2s input
43 let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs);
44
45 let bit_clock_pin = p.PIN_18;
46 let left_right_clock_pin = p.PIN_19;
47 let data_pin = p.PIN_20;
48
49 let program = PioI2sInProgram::new(&mut common);
50 let mut i2s = PioI2sIn::new(
51 &mut common,
52 sm0,
53 p.DMA_CH0,
54 USE_ONBOARD_PULLDOWN,
55 data_pin,
56 bit_clock_pin,
57 left_right_clock_pin,
58 SAMPLE_RATE,
59 BIT_DEPTH,
60 CHANNELS,
61 &program,
62 );
63
64 // create two audio buffers (back and front) which will take turns being
65 // filled with new audio data from the PIO fifo using DMA
66 const BUFFER_SIZE: usize = 960;
67 static DMA_BUFFER: StaticCell<[u32; BUFFER_SIZE * 2]> = StaticCell::new();
68 let dma_buffer = DMA_BUFFER.init_with(|| [0u32; BUFFER_SIZE * 2]);
69 let (mut back_buffer, mut front_buffer) = dma_buffer.split_at_mut(BUFFER_SIZE);
70
71 loop {
72 // trigger transfer of front buffer data to the pio fifo
73 // but don't await the returned future, yet
74 let dma_future = i2s.read(front_buffer);
75 // now await the dma future. once the dma finishes, the next buffer needs to be queued
76 // within DMA_DEPTH / SAMPLE_RATE = 8 / 48000 seconds = 166us
77 dma_future.await;
78 info!("Received I2S data word: {:?}", &front_buffer);
79 mem::swap(&mut back_buffer, &mut front_buffer);
80 }
81}