faster and smarter DMA

This commit is contained in:
Priec
2025-11-19 18:48:09 +01:00
parent e2378cd436
commit bf34ff1bcb
2 changed files with 44 additions and 11 deletions

View File

@@ -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;
}

View File

@@ -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;