From 5b2696fdbdcaa435e94efb2ba2c6e1f34fca73b0 Mon Sep 17 00:00:00 2001 From: Stephen D <webmaster@scd31.com> Date: Tue, 3 Oct 2023 12:47:57 -0300 Subject: [PATCH] support variable length packets --- src/error.rs | 13 +++++++ src/internal_state.rs | 1 + src/lib.rs | 87 ++++++++++++++++++++++++++----------------- src/rx.rs | 19 ++++++++++ 4 files changed, 85 insertions(+), 35 deletions(-) create mode 100644 src/rx.rs diff --git a/src/error.rs b/src/error.rs index 5e9b9b3..b7e422f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -23,12 +23,21 @@ pub enum TransferError<SE: Debug> { SpiError(SE), } +#[derive(Debug)] +pub enum TxError<SE: Debug> { + // Given slice was bigger than the maximum packet size + TooMuchData, + SpiError(SE), +} + pub(crate) trait SpiErrorToOtherError<T, E: Debug> { fn re(self) -> Result<T, RfError<E>> where Self: Sized; fn te(self) -> Result<T, TransferError<E>>; + + fn txe(self) -> Result<T, TxError<E>>; } impl<T, E: Debug> SpiErrorToOtherError<T, E> for Result<T, E> { @@ -39,4 +48,8 @@ impl<T, E: Debug> SpiErrorToOtherError<T, E> for Result<T, E> { fn te(self) -> Result<T, TransferError<E>> { self.map_err(|e| TransferError::SpiError(e)) } + + fn txe(self) -> Result<T, TxError<E>> { + self.map_err(|e| TxError::SpiError(e)) + } } diff --git a/src/internal_state.rs b/src/internal_state.rs index 43dab00..3bdb772 100644 --- a/src/internal_state.rs +++ b/src/internal_state.rs @@ -11,5 +11,6 @@ pub enum InternalState<const PACKET_LEN: usize> { Tx { data: [u8; PACKET_LEN], i: usize, + len: usize, }, } diff --git a/src/lib.rs b/src/lib.rs index afcf228..9943a6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ mod consts; pub mod error; mod internal_radio; mod internal_state; +pub mod rx; pub(crate) mod state; use core::{convert::Infallible, fmt::Debug}; @@ -14,25 +15,26 @@ use embedded_hal::{ }; use consts::*; -use error::{RfError, SpiErrorToOtherError, TransferError}; +use error::{RfError, SpiErrorToOtherError, TransferError, TxError}; use internal_state::InternalState; +use rx::RxPacket; use state::State; use crate::internal_radio::InternalRadio; -pub struct Rf4463<const PACKET_LEN: usize, Spi, SdnPin, CsPin, Delay> { +pub struct Rf4463<const MAX_PACKET_LEN: usize, Spi, SdnPin, CsPin, Delay> { radio: InternalRadio<Spi, SdnPin, CsPin, Delay>, - state: InternalState<PACKET_LEN>, + state: InternalState<MAX_PACKET_LEN>, rx_forever: bool, } impl< - const PACKET_LEN: usize, + const MAX_PACKET_LEN: usize, Spi: Transfer<u8>, SdnPin: OutputPin<Error = Infallible>, CsPin: OutputPin<Error = Infallible>, Delay: DelayUs<u16>, - > Rf4463<PACKET_LEN, Spi, SdnPin, CsPin, Delay> + > Rf4463<MAX_PACKET_LEN, Spi, SdnPin, CsPin, Delay> where Spi::Error: Debug, { @@ -44,7 +46,7 @@ where config: &mut [u8], ) -> Result<Self, RfError<Spi::Error>> { assert!( - PACKET_LEN < 8192, + MAX_PACKET_LEN < 8192, "Packet length cannot be above 8191 bytes" ); @@ -78,7 +80,7 @@ where self.radio.clear_ph_and_modem_interrupts()?; self.state = InternalState::Rx { - data: [0; PACKET_LEN], + data: [0; MAX_PACKET_LEN], i: 0, received: false, rssi: None, @@ -88,8 +90,8 @@ where START_RX, 0, 0, - (PACKET_LEN >> 8).try_into().unwrap(), - (PACKET_LEN & 0xff).try_into().unwrap(), + (MAX_PACKET_LEN >> 8).try_into().unwrap(), + (MAX_PACKET_LEN & 0xff).try_into().unwrap(), State::Rx.into(), if rx_forever { State::Rx.into() @@ -104,26 +106,26 @@ where Ok(()) } - pub fn finish_rx(&mut self) -> Result<Option<([u8; PACKET_LEN], f64)>, Spi::Error> { + pub fn finish_rx(&mut self) -> Result<Option<RxPacket<MAX_PACKET_LEN>>, Spi::Error> { let pkt = match self.state { InternalState::Rx { data, received, i, rssi, - } if i == PACKET_LEN && received => { + } if received => { let rssi = match rssi { Some(x) => x, None => self.get_rssi()?, }; - let ret = Some((data, rssi)); + let ret = Some(RxPacket::new(data, i, rssi)); if self.rx_forever { self.radio.clear_ph_and_modem_interrupts()?; self.state = InternalState::Rx { - data: [0; PACKET_LEN], + data: [0; MAX_PACKET_LEN], i: 0, received: false, rssi: None, @@ -141,31 +143,46 @@ where Ok(pkt) } - pub fn start_tx(&mut self, mut data: [u8; PACKET_LEN]) -> Result<(), Spi::Error> { - self.radio.clear_fifo()?; - self.radio.clear_ph_and_modem_interrupts()?; + pub fn start_tx(&mut self, data: &[u8]) -> Result<(), TxError<Spi::Error>> { + let len = data.len(); + if len > MAX_PACKET_LEN { + return Err(TxError::TooMuchData); + } + + self.radio.clear_fifo().txe()?; + self.radio.clear_ph_and_modem_interrupts().txe()?; // 128-byte TX buffer let i = data.len().min(128); + let mut segment = [0; 128]; + segment[..i].copy_from_slice(&data[..i]); self.radio.with_cs(|s| { - s.spi_transfer_byte(WRITE_TX_FIFO)?; - s.spi.transfer(&mut data[0..i])?; + s.spi_transfer_byte(WRITE_TX_FIFO).txe()?; + s.spi.transfer(&mut segment[..i]).txe()?; Ok(()) })?; - self.radio.send_command::<0>(&mut [ - START_TX, - 0, - u8::from(State::Sleep) << 4, - (PACKET_LEN >> 8).try_into().unwrap(), - (PACKET_LEN & 0xff).try_into().unwrap(), - 0, - 0, - ])?; - - self.state = InternalState::Tx { data, i }; + self.radio + .send_command::<0>(&mut [ + START_TX, + 0, + u8::from(State::Sleep) << 4, + (MAX_PACKET_LEN >> 8).try_into().unwrap(), + (MAX_PACKET_LEN & 0xff).try_into().unwrap(), + 0, + 0, + ]) + .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, + }; Ok(()) } @@ -219,12 +236,12 @@ where _ => return Ok(()), }; - let len: usize = self.radio.rx_fifo_len().te()?.into(); - if len == 0 { + let fifo_len: usize = self.radio.rx_fifo_len().te()?.into(); + if fifo_len == 0 { return Ok(()); } - if len + *i > PACKET_LEN { + if fifo_len + *i > MAX_PACKET_LEN { return Err(TransferError::TooMuchData); } @@ -232,7 +249,7 @@ where return Err(TransferError::FifoOverflow); } - let data = &mut data[*i..(*i + len)]; + let data = &mut data[*i..(*i + fifo_len)]; self.radio .with_cs(|s| { s.spi_transfer_byte(READ_RX_FIFO)?; @@ -246,14 +263,14 @@ where *rssi = Some(self.radio.get_rssi().te()?) } - *i += len; + *i += fifo_len; Ok(()) } fn tx_step(&mut self) -> Result<(), TransferError<Spi::Error>> { let (data, i) = match &mut self.state { - InternalState::Tx { data, i, .. } => (data, i), + InternalState::Tx { data, i, len } => (&mut data[0..*len], i), _ => return Ok(()), }; diff --git a/src/rx.rs b/src/rx.rs new file mode 100644 index 0000000..fc40823 --- /dev/null +++ b/src/rx.rs @@ -0,0 +1,19 @@ +pub struct RxPacket<const N: usize> { + data: [u8; N], + i: usize, + rssi: f64, +} + +impl<const N: usize> RxPacket<N> { + pub(crate) fn new(data: [u8; N], i: usize, rssi: f64) -> Self { + Self { data, i, rssi } + } + + pub fn data(&self) -> &[u8] { + &self.data[..self.i] + } + + pub fn rssi(&self) -> f64 { + self.rssi + } +} -- GitLab