@@ -13,7 +13,8 @@ use embassy_time::{Duration, Instant, Timer};
1313use esp_alloc;
1414use esp_backtrace as _;
1515use esp_hal:: {
16- dma_buffers,
16+ dma:: DmaRxStreamBuf ,
17+ dma_rx_stream_buffer,
1718 i2s:: master:: { Channels , Config as I2sConfig , DataFormat , I2s } ,
1819 rng:: Rng ,
1920 time:: Rate ,
@@ -43,6 +44,7 @@ const PASSWORD: &str = env!("PASSWORD");
4344
4445const SAMPLE_RATE : u32 = 16_000 ;
4546const I2S_BUFFER_SIZE : usize = 4092 * 8 ; // DMA ring size
47+ const I2S_CHUNK_SIZE : usize = 4092 ;
4648
4749macro_rules! mk_static {
4850 ( $t: ty, $val: expr) => { {
@@ -126,19 +128,15 @@ async fn connection_manager(
126128#[ embassy_executor:: task]
127129async fn i2s_dma_drain (
128130 i2s_rx : esp_hal:: i2s:: master:: I2sRx < ' static , esp_hal:: Async > ,
129- buffer : & ' static mut [ u8 ] ,
131+ buffer : DmaRxStreamBuf ,
130132 connected_signal : & ' static Signal < NoopRawMutex , bool > ,
131133) {
132- // Temporary buffer for DMA pops
133- static I2S_DATA_BUFFER : StaticCell < [ u8 ; 8192 ] > = StaticCell :: new ( ) ;
134- let i2s_data = I2S_DATA_BUFFER . init ( [ 0u8 ; 8192 ] ) ;
135-
136- // Create circular DMA transaction
134+ // Create streaming DMA transaction
137135 println ! (
138- "🎛️ Creating I2S DMA circular transaction with ring size: {} bytes" ,
139- buffer . len ( )
136+ "🎛️ Creating I2S DMA transaction with streaming buffer of size: {} bytes" ,
137+ I2S_BUFFER_SIZE
140138 ) ;
141- let mut transaction = match i2s_rx. read_dma_circular_async ( buffer) {
139+ let mut transaction = match i2s_rx. read ( buffer, I2S_CHUNK_SIZE ) {
142140 Ok ( t) => t,
143141 Err ( e) => {
144142 println ! ( "❌ Failed to start I2S DMA: {:?}" , e) ;
@@ -153,10 +151,19 @@ async fn i2s_dma_drain(
153151 // Start continuous draining to prevent DmaError(Late)
154152 println ! ( "🧹 Starting continuous buffer drain to keep DMA synchronized..." ) ;
155153 while !connected_signal. signaled ( ) {
154+ let available_bytes = match transaction. available_bytes ( ) {
155+ 0 => transaction
156+ . wait_for_available ( )
157+ . await
158+ . map ( |_| transaction. available_bytes ( ) ) ,
159+ b => Ok ( b) ,
160+ } ;
161+
156162 // Check for available data and drain it
157- match transaction . pop ( i2s_data ) . await {
163+ match available_bytes {
158164 Ok ( bytes) => {
159165 total_drained += bytes;
166+ transaction. consume ( bytes) ;
160167 }
161168 Err ( e) => {
162169 if matches ! (
@@ -187,9 +194,17 @@ async fn i2s_dma_drain(
187194 late_errors,
188195 start. elapsed( ) . as_millis( )
189196 ) ;
190- match transaction. pop ( i2s_data) . await {
197+ let available_bytes = match transaction. available_bytes ( ) {
198+ 0 => transaction
199+ . wait_for_available ( )
200+ . await
201+ . map ( |_| transaction. available_bytes ( ) ) ,
202+ b => Ok ( b) ,
203+ } ;
204+ match available_bytes {
191205 Ok ( bytes) => {
192206 println ! ( "🧹 Final drained {} bytes total" , bytes) ;
207+ transaction. consume ( bytes) ;
193208 }
194209 Err ( e) => {
195210 if matches ! (
@@ -246,7 +261,7 @@ async fn main(spawner: Spawner) {
246261 let dma_channel = peripherals. DMA_I2S0 ;
247262 #[ cfg( not( any( feature = "esp32" , feature = "esp32s2" ) ) ) ]
248263 let dma_channel = peripherals. DMA_CH0 ;
249- let ( rx_buffer, rx_descriptors , _ , _ ) = dma_buffers ! ( I2S_BUFFER_SIZE , 0 ) ;
264+ let rx_buffer = dma_rx_stream_buffer ! ( I2S_BUFFER_SIZE , I2S_CHUNK_SIZE ) ;
250265
251266 let i2s_cfg = I2sConfig :: new_tdm_philips ( )
252267 . with_sample_rate ( Rate :: from_hz ( SAMPLE_RATE ) )
@@ -262,7 +277,7 @@ async fn main(spawner: Spawner) {
262277 . with_bclk ( peripherals. GPIO7 ) // SCK
263278 . with_ws ( peripherals. GPIO6 ) // WS
264279 . with_din ( peripherals. GPIO5 ) // SD
265- . build ( rx_descriptors ) ;
280+ . build ( ) ;
266281
267282 // WiFi + network stack
268283 let esp_radio_ctrl = & * mk_static ! ( Controller <' static >, esp_radio:: init( ) . unwrap( ) ) ;
0 commit comments