use cortex_m::singleton; use stm32f1xx_hal::{dma, pac, prelude::*, rcc, serial}; const DMX_LEN_MAX: usize = 512; type TxDma = dma::TxDma, dma::dma1::C4>; type DMXUniverse = &'static mut [u8; DMX_LEN]; type DMXTransfer = dma::Transfer, TxDma>; pub enum DMX { Idle(Option, Option>), Busy(Option>), } impl DMX { pub fn new( mut serial: serial::Serial, channel: dma::dma1::C4, clocks: &rcc::Clocks, ) -> Self where PINS: serial::Pins, { assert!(DMX_LEN <= DMX_LEN_MAX); serial.reconfigure(250_000.bps(), &clocks).unwrap(); Self::Idle(Some(serial.tx.with_dma(channel)), None) } pub fn send(&mut self, data: &[u8]) { if let Self::Busy(_) = self { self.wait(); } let Self::Idle(tx, txbuffer) = self else { panic!("Broken DMX State!") }; let txbuffer = txbuffer.take().unwrap_or_else(|| { let foo = singleton!(: [u8; DMX_LEN_MAX] = [0u8; DMX_LEN_MAX]).unwrap(); (&mut foo[..DMX_LEN]).try_into().unwrap() }); let tx = tx.take().unwrap(); txbuffer.copy_from_slice(&data[..DMX_LEN]); *self = Self::Busy(Some(tx.write(txbuffer))); } pub fn wait(&mut self) { let Self::Busy(xfer) = self else { return }; let xfer = xfer.take().unwrap(); let (txbuffer, tx) = xfer.wait(); *self = Self::Idle(Some(tx), Some(txbuffer)); } }