// src/software_uart/runtime.rs
use embassy_executor::task;
use embassy_stm32::{
    dma::Request,
    peripherals::GPDMA1_CH1,
    Peri,
};
use embassy_stm32::dma::{
    ReadableRingBuffer,
    TransferOptions,
};
use crate::config::{RX_OVERSAMPLE, UART_CFG};
use crate::software_uart::decode_uart_samples;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
use embassy_futures::yield_now;

// datasheet tabulka 137
pub const TIM7_UP_REQ: Request = 5;

/// RX DMA task: reads GPIO samples paced by TIM7 and fills PIPE_RX
#[task]
pub async fn rx_dma_task(
    ch: Peri<'static, GPDMA1_CH1>,
    pipe_rx: &'static Pipe<CriticalSectionRawMutex, 256>,
    ring: &'static mut [u8],
) {
    let gpioa_idr = embassy_stm32::pac::GPIOA.idr().as_ptr() as *mut u8;

    let mut opts = TransferOptions::default();
    opts.half_transfer_ir = true;
    opts.complete_transfer_ir = true;

    // SAFETY: ring is exclusive to this task
    let mut rx = unsafe { ReadableRingBuffer::new(ch, TIM7_UP_REQ, gpioa_idr, ring, opts) };
    rx.start();

    let mut chunk = [0u8; 256];
    loop {
        let _ = rx.read_exact(&mut chunk).await;
        let decoded = decode_uart_samples(&chunk, RX_OVERSAMPLE, &UART_CFG);
        pipe_rx.write(&decoded).await;
        yield_now().await;
    }
}
