From bf34ff1bcb811999b8c72086c741dd294c76cf55 Mon Sep 17 00:00:00 2001 From: Priec Date: Wed, 19 Nov 2025 18:48:09 +0100 Subject: [PATCH] faster and smarter DMA --- semestralka_1i_rx_dma/src/bin/main.rs | 2 +- .../src/software_uart/gpio_dma_uart_rx.rs | 53 +++++++++++++++---- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/semestralka_1i_rx_dma/src/bin/main.rs b/semestralka_1i_rx_dma/src/bin/main.rs index 0a72d6e..0a4a135 100644 --- a/semestralka_1i_rx_dma/src/bin/main.rs +++ b/semestralka_1i_rx_dma/src/bin/main.rs @@ -150,7 +150,7 @@ pub async fn bridge_usart1_rx_to_usart2_tx( let n = usart1_rx.read(&mut buf).await; if n > 0 { let _ = usart2_tx.write(&buf[..n]).await; - info!("bridge USART1 - USART2 sent:{} bytes: {}", n, &buf[..n]); + // info!("bridge USART1 - USART2 sent:{} bytes: {}", n, &buf[..n]); } yield_now().await; } diff --git a/semestralka_1i_rx_dma/src/software_uart/gpio_dma_uart_rx.rs b/semestralka_1i_rx_dma/src/software_uart/gpio_dma_uart_rx.rs index f983d56..466f403 100644 --- a/semestralka_1i_rx_dma/src/software_uart/gpio_dma_uart_rx.rs +++ b/semestralka_1i_rx_dma/src/software_uart/gpio_dma_uart_rx.rs @@ -35,23 +35,56 @@ pub async fn rx_dma_task( let mut rx = unsafe { ReadableRingBuffer::new(ch, TIM7_UP_REQ, register, ring, opts) }; rx.start(); - let mut raw_chunk = [0u8; 256]; - let mut levels = [0u8; 256]; - let mut last_bytes: [u8; 16] = [0; 16]; // remember previous 16 samples - let mut last_value: u8 = 0; // remember previous single IDR sample (optional) + // We read into the second half of a buffer, keeping "leftovers" in the first half. + const CHUNK_SIZE: usize = 256; + const HISTORY_SIZE: usize = 256; // Enough to hold a potential split frame + const TOTAL_BUF_SIZE: usize = HISTORY_SIZE + CHUNK_SIZE; + + // Logic level buffer + let mut level_buf = [0u8; TOTAL_BUF_SIZE]; + let mut valid_len = 0usize; + + let mut raw_chunk = [0u8; CHUNK_SIZE]; loop { let _ = rx.read_exact(&mut raw_chunk).await; - // convert IDR bits to logic levels for (i, b) in raw_chunk.iter().enumerate() { - levels[i] = ((*b >> RX_PIN_BIT) & 1) as u8; + level_buf[valid_len + i] = ((*b >> RX_PIN_BIT) & 1) as u8; + } + let current_end = valid_len + CHUNK_SIZE; + + // 3. Decode everything we have + let (decoded, consumed) = decode_uart_samples( + &level_buf[..current_end], + RX_OVERSAMPLE, + &UART_CFG + ); + + if !decoded.is_empty() { + pipe_rx.write(decoded.as_slice()).await; } - let (decoded, _consumed) = decode_uart_samples(&levels, RX_OVERSAMPLE, &UART_CFG); - if !decoded.is_empty() { - // info!("SW RX decoded {:a}", decoded.as_slice()); - pipe_rx.write(decoded.as_slice()).await; + // 4. Shift remaining data to front + // We processed 'consumed' samples. + // We keep everything from 'consumed' up to 'current_end'. + let remaining = current_end - consumed; + + // Safety check: if remaining > HISTORY_SIZE, we are in trouble (buffer too small / decoder stuck). + // But for now, just shift. + if remaining > 0 { + level_buf.copy_within(consumed..current_end, 0); + } + valid_len = remaining; + + // If valid_len grows too large (decoder not consuming), we must discard to avoid panic on next write + if valid_len >= HISTORY_SIZE { + // Discard oldest to make space + // logic: we move the last (HISTORY_SIZE/2) to 0. + // This effectively "skips" garbage data. + let keep = HISTORY_SIZE / 2; + level_buf.copy_within(valid_len - keep..valid_len, 0); + valid_len = keep; } yield_now().await;