use embedded_hal::{
blocking::{delay::DelayUs, spi::Transfer},
digital::v2::OutputPin,
};
use crate::{
consts::*,
error::{RfError, SpiErrorToOtherError},
state::State,
};
use core::{convert::Infallible, fmt::Debug};
pub(crate) struct InternalRadio<Spi, SdnPin, CsPin, Delay> {
pub spi: Spi,
sdn: SdnPin,
cs: CsPin,
delay: Delay,
}
impl<
Spi: Transfer<u8>,
SdnPin: OutputPin<Error = Infallible>,
CsPin: OutputPin<Error = Infallible>,
Delay: DelayUs<u16>,
> InternalRadio<Spi, SdnPin, CsPin, Delay>
where
Spi::Error: Debug,
{
pub fn new(
spi: Spi,
sdn: SdnPin,
mut cs: CsPin,
delay: Delay,
config: &mut [u8],
) -> Result<Self, RfError<Spi::Error>> {
cs.set_high().unwrap();
let mut s = Self {
spi,
sdn,
cs,
delay,
};
s.reset();
s.configure(config).re()?;
s.clear_interrupts().re()?;
s.enable_interrupts().re()?;
s.sleep()?;
Ok(s)
}
fn reset(&mut self) {
self.sdn.set_high().unwrap();
self.delay.delay_us(50_000);
self.sdn.set_low().unwrap();
self.delay.delay_us(50_000);
}
pub fn sleep(&mut self) -> Result<(), RfError<Spi::Error>> {
if self.get_state()? != State::Tx {
self.set_state(State::Sleep).re()?;
}
Ok(())
}
pub fn get_state(&mut self) -> Result<State, RfError<Spi::Error>> {
let resp = self.send_command::<1>(&mut [READ_FRR_B]).re()?[0];
Ok(resp.try_into()?)
}
pub fn set_state(&mut self, s: State) -> Result<(), Spi::Error> {
self.send_command::<0>(&mut [CHANGE_STATE, s.into()])?;
Ok(())
}
pub fn get_temp(&mut self) -> Result<f32, Spi::Error> {
let result: f32 = self.get_adc(ADC_CONV_TEMP, ADC_SPEED << 4, 4)?.into();
Ok(899.0 * result / 4096.0 - 293.0)
}
pub fn get_rssi(&mut self) -> Result<f64, Spi::Error> {
let frr = self.read_frr()?;
Ok((frr[0] as f64) / 2.0 - 136.0)
}
fn configure(&mut self, config: &mut [u8]) -> Result<(), Spi::Error> {
let mut i = 0;
while i < config.len() {
let l: usize = config[i].into();
self.send_command::<0>(&mut config[(i + 1)..(i + 1 + l)])?;
i += l + 1;
}
Ok(())
}
fn clear_interrupts(&mut self) -> Result<(), Spi::Error> {
self.send_command::<8>(&mut [GET_INT_STATUS])?;
Ok(())
}
fn enable_interrupts(&mut self) -> Result<(), Spi::Error> {
self.send_command::<0>(&mut [SET_PROPERTY, 0x01, 2, 0x00, 0b00000001, 0b00110011])?;
Ok(())
}
pub fn clear_ph_and_modem_interrupts(&mut self) -> Result<(), Spi::Error> {
self.send_command::<0>(&mut [GET_INT_STATUS, 0, 0, 0xFF])?;
Ok(())
}
pub fn packet_received_pending(&mut self) -> Result<bool, Spi::Error> {
let ph_pend =
self.send_command::<3>(&mut [GET_INT_STATUS, 0xFF ^ (1 << 4), 0xFF, 0xFF])?[2];
Ok((ph_pend & (1 << 4)) != 0)
}
pub fn packet_sent_pending(&mut self) -> Result<bool, Spi::Error> {
let ph_pend =
self.send_command::<3>(&mut [GET_INT_STATUS, 0xFF ^ (1 << 5), 0xFF, 0xFF])?[2];
Ok((ph_pend & (1 << 5)) != 0)
}
pub fn fifo_underflow_pending(&mut self) -> Result<bool, Spi::Error> {
let ch_pend =
self.send_command::<7>(&mut [GET_INT_STATUS, 0xFF, 0xFF, 0xFF ^ (1 << 5)])?[6];
Ok(ch_pend & (1 << 5) != 0)
}
pub fn tx_fifo_space(&mut self) -> Result<u8, Spi::Error> {
let fifo = self.send_command::<2>(&mut [FIFO_INFO, 0])?;
Ok(fifo[1])
}
pub fn rx_fifo_len(&mut self) -> Result<u8, Spi::Error> {
let fifo = self.send_command::<2>(&mut [FIFO_INFO, 0])?;
Ok(fifo[0])
}
pub fn clear_fifo(&mut self) -> Result<(), Spi::Error> {
self.send_command::<0>(&mut [FIFO_INFO, FIFO_CLEAR_RX | FIFO_CLEAR_TX])?;
Ok(())
}
fn get_adc(&mut self, en: u8, cfg: u8, part: usize) -> Result<u16, Spi::Error> {
let data: [_; 6] = self.send_command(&mut [GET_ADC_READING, en, cfg])?;
Ok((u16::from(data[part]) << 8) | u16::from(data[part + 1]))
}
pub fn send_command<const NUM_BYTES_OUT: usize>(
&mut self,
command: &mut [u8],
) -> Result<[u8; NUM_BYTES_OUT], Spi::Error> {
self.with_cs(|s| {
s.spi.transfer(command)?;
Ok(())
})?;
loop {
if let Some(out) = self.with_cs(|s| {
s.spi_transfer_byte(READ_CMD_BUF)?;
if s.spi_transfer_byte(0xFF)? != 0xFF {
return Ok(None);
}
let mut out = [0xFF; NUM_BYTES_OUT];
s.spi.transfer(&mut out)?;
Ok(Some(out))
})? {
return Ok(out);
}
}
}
fn read_frr(&mut self) -> Result<[u8; 4], Spi::Error> {
self.with_cs(|s| {
s.spi_transfer_byte(FRR_A_READ)?;
let mut out = [0xFF; 4];
s.spi.transfer(&mut out)?;
Ok(out)
})
}
pub fn spi_transfer_byte(&mut self, byte: u8) -> Result<u8, Spi::Error> {
let mut buf = [byte];
let buf = self.spi.transfer(&mut buf)?;
Ok(buf[0])
}
pub fn with_cs<T, F: FnMut(&mut Self) -> T>(&mut self, mut f: F) -> T {
self.cs.set_low().unwrap();
self.delay.delay_us(1);
let ret = f(self);
self.cs.set_high().unwrap();
self.delay.delay_us(1);
ret
}
}