From da02f35df636c47869db51af547b7862c46c6a6a Mon Sep 17 00:00:00 2001 From: Stephen D <webmaster@scd31.com> Date: Sat, 4 Nov 2023 18:45:33 -0300 Subject: [PATCH] wip moving to borrowed ram --- src/internal_state.rs | 6 +-- src/lib.rs | 86 ++++++++++++++++++++++++++----------------- src/rx.rs | 14 ++++--- 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/src/internal_state.rs b/src/internal_state.rs index 3bdb772..ef64e3b 100644 --- a/src/internal_state.rs +++ b/src/internal_state.rs @@ -1,15 +1,15 @@ // Tracks the state of our instance, *not* the state of the radio. #[derive(Debug)] -pub enum InternalState<const PACKET_LEN: usize> { +pub enum InternalState<'a, const PACKET_LEN: usize> { Idle, Rx { - data: [u8; PACKET_LEN], + data: &'a mut [u8; PACKET_LEN], i: usize, received: bool, rssi: Option<f64>, }, Tx { - data: [u8; PACKET_LEN], + data: &'a [u8], i: usize, len: usize, }, diff --git a/src/lib.rs b/src/lib.rs index 187f549..d9b2afa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,20 +22,21 @@ use state::State; use crate::internal_radio::InternalRadio; -pub struct Rf4463<const MAX_PACKET_LEN: usize, Spi, SdnPin, CsPin, Delay> { +pub struct Rf4463<'a, const MAX_PACKET_LEN: usize, Spi, SdnPin, CsPin, Delay> { radio: InternalRadio<Spi, SdnPin, CsPin, Delay>, - state: InternalState<MAX_PACKET_LEN>, + state: InternalState<'a, MAX_PACKET_LEN>, rx_forever: bool, channel: u8, } impl< + 'a, const MAX_PACKET_LEN: usize, Spi: Transfer<u8>, SdnPin: OutputPin<Error = Infallible>, CsPin: OutputPin<Error = Infallible>, Delay: DelayUs<u16>, - > Rf4463<MAX_PACKET_LEN, Spi, SdnPin, CsPin, Delay> + > Rf4463<'a, MAX_PACKET_LEN, Spi, SdnPin, CsPin, Delay> where Spi::Error: Debug, { @@ -91,14 +92,19 @@ where } // Len is none when using a variable-length packet - pub fn start_rx(&mut self, len: Option<usize>, rx_forever: bool) -> Result<(), Spi::Error> { + pub fn start_rx( + &mut self, + buf: &'a mut [u8; MAX_PACKET_LEN], + len: Option<usize>, + rx_forever: bool, + ) -> Result<(), Spi::Error> { self.radio.clear_fifo()?; self.radio.clear_ph_and_modem_interrupts()?; let len = len.unwrap_or(0); self.state = InternalState::Rx { - data: [0; MAX_PACKET_LEN], + data: buf, i: 0, received: false, rssi: None, @@ -124,44 +130,58 @@ where Ok(()) } - pub fn finish_rx(&mut self) -> Result<Option<RxPacket<MAX_PACKET_LEN>>, Spi::Error> { - let pkt = match self.state { + /// Panics if rx_forever is true and new_buf is None + pub fn finish_rx( + &mut self, + new_buf: Option<&'a mut [u8; MAX_PACKET_LEN]>, + ) -> Result<Option<RxPacket<MAX_PACKET_LEN>>, Spi::Error> { + let (set_idle, ret) = match &mut self.state { InternalState::Rx { data, received, i, rssi, - } if received => { - let rssi = match rssi { + } if *received => { + let ret_rssi = match *rssi { Some(x) => x, - None => self.get_rssi()?, + None => self.radio.get_rssi()?, }; - let ret = Some(RxPacket::new(data, i, rssi)); + let ret = if self.rx_forever { + let new_buf = new_buf.expect("rx_forever=true and no replacement buffer given"); - if self.rx_forever { self.radio.clear_ph_and_modem_interrupts()?; - self.state = InternalState::Rx { - data: [0; MAX_PACKET_LEN], - i: 0, - received: false, - rssi: None, - }; + core::mem::swap(new_buf, data); + *i = 0; + *received = false; + *rssi = None; + + (false, Some(RxPacket::new(new_buf, *i, ret_rssi))) } else { - self.state = InternalState::Idle; - } + (true, Some(RxPacket::new(data, *i, ret_rssi))) + }; ret } - _ => None, + _ => (false, None), }; - Ok(pkt) + if set_idle { + self.state = InternalState::Idle; + } + + Ok(ret) } - pub fn start_tx(&mut self, data: &[u8]) -> Result<(), TxError<Spi::Error>> { + /// Panics if data length is > 8191 + pub fn start_tx(&mut self, data: &'a [u8]) -> Result<(), TxError<Spi::Error>> { + assert!( + MAX_PACKET_LEN < 8192, + "Packet length cannot be above 8191 bytes" + ); + let len = data.len(); if len > MAX_PACKET_LEN { return Err(TxError::TooMuchData); @@ -194,13 +214,7 @@ where ]) .txe()?; - let mut padded_data = [0; MAX_PACKET_LEN]; - padded_data[0..len].copy_from_slice(data); - self.state = InternalState::Tx { - data: padded_data, - i, - len, - }; + self.state = InternalState::Tx { data, i, len }; Ok(()) } @@ -288,12 +302,12 @@ where fn tx_step(&mut self) -> Result<(), TransferError<Spi::Error>> { let (data, i) = match &mut self.state { - InternalState::Tx { data, i, len } => (&mut data[0..*len], i), + InternalState::Tx { data, i, len } => (&data[0..*len], i), _ => return Ok(()), }; // only look at the slice we haven't sent yet - let data = &mut data[*i..]; + let data = &data[*i..]; let len: usize = self.radio.tx_fifo_space().te()?.into(); let len = len.min(data.len()); @@ -301,13 +315,19 @@ where return Ok(()); } + // we need a mutable reference on data for our transfer function + // so we copy that data into a temporary buffer + const FIFO_BUFFER_LEN: usize = 129; + let mut buf = [0; FIFO_BUFFER_LEN]; + buf[..len].copy_from_slice(&data[..len]); + if self.radio.fifo_underflow_pending().te()? { return Err(TransferError::FifoOverflow); } self.radio.with_cs(|s| { s.spi_transfer_byte(WRITE_TX_FIFO).te()?; - s.spi.transfer(&mut data[0..len]).te()?; + s.spi.transfer(&mut buf[0..len]).te()?; Ok(()) })?; diff --git a/src/rx.rs b/src/rx.rs index 7677257..e7f99d6 100644 --- a/src/rx.rs +++ b/src/rx.rs @@ -1,12 +1,12 @@ -#[derive(Debug, Clone)] -pub struct RxPacket<const N: usize> { - data: [u8; N], +#[derive(Debug)] +pub struct RxPacket<'a, const N: usize> { + data: &'a mut [u8; N], i: usize, rssi: f64, } -impl<const N: usize> RxPacket<N> { - pub(crate) fn new(data: [u8; N], i: usize, rssi: f64) -> Self { +impl<'a, const N: usize> RxPacket<'a, N> { + pub(crate) fn new(data: &'a mut [u8; N], i: usize, rssi: f64) -> Self { Self { data, i, rssi } } @@ -17,4 +17,8 @@ impl<const N: usize> RxPacket<N> { pub fn rssi(&self) -> f64 { self.rssi } + + fn into_buf(self) -> &'a mut [u8; N] { + self.data + } } -- GitLab