diff --git a/bluepill-rs/src/dmx2.rs b/bluepill-rs/src/dmx2.rs index 4f1b59f..88d9c8d 100644 --- a/bluepill-rs/src/dmx2.rs +++ b/bluepill-rs/src/dmx2.rs @@ -5,21 +5,76 @@ type DMXUniverse = &'static mut [u8; DMX_LEN]; type DMXTransfer = dma::Transfer, TxDma>; struct TxDMAIdle { - dma: Option, dma::dma1::C4>>, - buffer: Option>, + tx: TxDma, + buffer: DMXUniverse, } struct TxDMABusy { - transfer: Option>, + transfer: DMXTransfer, } enum TxDMA { - Idle(TxDMAIdle), - Busy(TxDMABusy), + Idle(Option>), + Busy(Option>), +} + +impl TxDMA { + fn new(tx: TxDma, buffer: DMXUniverse) -> Self { + TxDMA::Idle(Some(TxDMAIdle { tx, buffer })) + } + + fn start_sending(&mut self, tx_universe: &[u8]) { + let TxDMA::Idle(idle) = self else { + return; + }; + + let Some(TxDMAIdle { tx, buffer }) = idle.take() else { + panic!(); + }; + + buffer.copy_from_slice(tx_universe); + *self = TxDMA::Busy(Some(TxDMABusy { + transfer: tx.write(buffer), + })); + } + + fn wait(&mut self) { + let TxDMA::Busy(busy) = self else { + return; + }; + + let Some(TxDMABusy { transfer }) = busy.take() else { + panic!(); + }; + + let (buffer, tx) = transfer.wait(); + + *self = TxDMA::Idle(Some(TxDMAIdle { tx, buffer })); + } + + fn is_idle(&mut self) -> bool { + match self { + TxDMA::Idle(_) => true, + + TxDMA::Busy(busy) => { + let Some(TxDMABusy { transfer }) = busy.take() else { + panic!(); + }; + + let is_done = transfer.is_done(); + busy.replace(TxDMABusy { transfer }); + if is_done { + self.wait(); + } + + is_done + } + } + } } pub struct DMX { - tx_universe: Option>, + tx_universe: DMXUniverse, sender: TxDMA, } @@ -69,11 +124,20 @@ impl DMX { ); Self { - tx_universe: Some(tx_universe), - sender: TxDMA::Idle(TxDMAIdle { - dma: Some(serial.tx.with_dma(dma1.4)), - buffer: Some(tx_buffer), - }), + tx_universe, + sender: TxDMA::new(serial.tx.with_dma(dma1.4), tx_buffer), } } + + pub fn start_tx(&mut self) { + self.sender.start_sending(self.tx_universe); + } + + pub fn wait_tx(&mut self) { + self.sender.wait(); + } + + pub fn tx_is_idle(&mut self) -> bool { + return self.sender.is_idle(); + } }