use core::convert::TryInto;
use crate::error::{Error, Result};
use crate::registers::{
ContinuousDagc, DioMapping, DioPin, FifoMode, IrqFlags1, IrqFlags2, LnaConfig, Mode,
Modulation, Pa13dBm1, Pa13dBm2, PacketConfig, PacketFormat, Registers, RxBw, RxBwFreq,
SensitivityBoost,
};
use crate::rw::ReadWrite;
const F_SCALE: u64 = 1_000_000;
const FOSC: u64 = 32_000_000 * F_SCALE;
const FSTEP: u64 = FOSC / 524_288;
macro_rules! _f_scale {
($val:ident) => {
u64::from($val) * F_SCALE
};
}
pub struct Rfm69<S> {
pub(crate) spi: S,
mode: Mode,
dio: [Option<DioMapping>; 6],
rssi: i16,
}
impl<S, Espi> Rfm69<S>
where
S: ReadWrite<Error = Espi>,
{
pub fn new(spi: S) -> Self {
Rfm69 {
spi,
mode: Mode::Standby,
dio: [None; 6],
rssi: 0,
}
}
pub fn read_all_regs(&mut self) -> Result<[u8; 0x4f], Espi> {
let mut buffer = [0u8; 0x4f];
self.read_many(Registers::OpMode, &mut buffer)?;
Ok(buffer)
}
pub fn mode(&mut self, mode: Mode) -> Result<(), Espi> {
if self.mode == mode {
return Ok(());
}
self.update(Registers::OpMode, |r| (r & 0xe3) | mode as u8)?;
self.mode = mode;
self.dio()
}
pub fn modulation(&mut self, modulation: Modulation) -> Result<(), Espi> {
self.write(Registers::DataModul, modulation.value())
}
pub fn bit_rate(&mut self, bit_rate: u32) -> Result<(), Espi> {
let reg = (FOSC / _f_scale!(bit_rate)) as u16;
self.write_many(Registers::BitrateMsb, ®.to_be_bytes())
}
pub fn fdev(&mut self, fdev: u32) -> Result<(), Espi> {
let reg = (_f_scale!(fdev) / FSTEP) as u16;
self.write_many(Registers::FdevMsb, ®.to_be_bytes())
}
pub fn frequency(&mut self, frequency: u32) -> Result<(), Espi> {
let reg = (_f_scale!(frequency) / FSTEP) as u32;
self.write_many(Registers::FrfMsb, ®.to_be_bytes()[1..])
}
pub fn dio_mapping(&mut self, mapping: DioMapping) -> Result<(), Espi> {
let pin = mapping.pin;
let dio = Some(mapping);
match pin {
DioPin::Dio0 => self.dio[0] = dio,
DioPin::Dio1 => self.dio[1] = dio,
DioPin::Dio2 => self.dio[2] = dio,
DioPin::Dio3 => self.dio[3] = dio,
DioPin::Dio4 => self.dio[4] = dio,
DioPin::Dio5 => self.dio[5] = dio,
}
self.dio()
}
pub fn clear_dio(&mut self, pin: DioPin) -> Result<(), Espi> {
match pin {
DioPin::Dio0 => self.dio[0] = None,
DioPin::Dio1 => self.dio[1] = None,
DioPin::Dio2 => self.dio[2] = None,
DioPin::Dio3 => self.dio[3] = None,
DioPin::Dio4 => self.dio[4] = None,
DioPin::Dio5 => self.dio[5] = None,
}
self.dio()
}
pub fn preamble(&mut self, reg: u16) -> Result<(), Espi> {
self.write_many(Registers::PreambleMsb, ®.to_be_bytes())
}
pub fn sync(&mut self, sync: &[u8]) -> Result<(), Espi> {
let len = sync.len();
if len == 0 {
return self.update(Registers::SyncConfig, |r| r & 0x7f);
} else if len > 8 {
return Err(Error::SyncSize);
}
let reg = 0x80 | ((len - 1) as u8) << 3;
self.write(Registers::SyncConfig, reg)?;
self.write_many(Registers::SyncValue1, sync)
}
pub fn packet(&mut self, packet_config: PacketConfig) -> Result<(), Espi> {
let len: u8;
let mut reg = 0x00;
match packet_config.format {
PacketFormat::Fixed(size) => len = size,
PacketFormat::Variable(size) => {
len = size;
reg |= 0x80;
}
}
reg |=
packet_config.dc as u8 | packet_config.filtering as u8 | (packet_config.crc as u8) << 4;
self.write_many(Registers::PacketConfig1, &[reg, len])?;
reg = packet_config.interpacket_rx_delay as u8 | (packet_config.auto_rx_restart as u8) << 1;
self.update(Registers::PacketConfig2, |r| r & 0x0d | reg)
}
pub fn node_address(&mut self, a: u8) -> Result<(), Espi> {
self.write(Registers::NodeAddrs, a)
}
pub fn broadcast_address(&mut self, a: u8) -> Result<(), Espi> {
self.write(Registers::BroadcastAddrs, a)
}
pub fn fifo_mode(&mut self, mode: FifoMode) -> Result<(), Espi> {
match mode {
FifoMode::NotEmpty => self.update(Registers::FifoThresh, |r| r | 0x80),
FifoMode::Level(level) => self.write(Registers::FifoThresh, level & 0x7f),
}
}
pub fn aes(&mut self, key: &[u8]) -> Result<(), Espi> {
let len = key.len();
if len == 0 {
return self.update(Registers::PacketConfig2, |r| r & 0xfe);
} else if len == 16 {
self.update(Registers::PacketConfig2, |r| r | 0x01)?;
return self.write_many(Registers::AesKey1, key);
}
Err(Error::AesKeySize)
}
pub fn rssi(&self) -> i16 {
self.rssi
}
pub fn recv(&mut self, buffer: &mut [u8]) -> Result<(), Espi> {
if buffer.is_empty() {
return Ok(());
}
self.mode(Mode::Receiver)?;
while !self.is_packet_ready()? {}
self.mode(Mode::Standby)?;
self.read_many(Registers::Fifo, buffer)?;
self.rssi = self.read_rssi()?;
Ok(())
}
pub fn recv_large(&mut self, buffer: &mut [u8]) -> Result<usize, Espi> {
self.mode(Mode::Receiver)?;
while self.is_fifo_empty()? {}
let len: usize = self.read(Registers::Fifo)?.into();
if len > buffer.len() {
for _ in 0..len {
while self.is_fifo_empty()? {}
self.read(Registers::Fifo)?;
}
self.mode(Mode::Standby)?;
self.rssi = self.read_rssi()?;
return Err(Error::BufferTooSmall);
}
for b in &mut buffer[0..len] {
while self.is_fifo_empty()? {}
*b = self.read(Registers::Fifo)?;
}
self.mode(Mode::Standby)?;
self.rssi = self.read_rssi()?;
Ok(len)
}
pub fn send(&mut self, buffer: &[u8]) -> Result<(), Espi> {
if buffer.is_empty() {
return Ok(());
}
self.mode(Mode::Standby)?;
while !self.is_mode_ready()? {}
self.reset_fifo()?;
self.write_many(Registers::Fifo, buffer)?;
self.mode(Mode::Transmitter)?;
while !self.is_packet_sent()? {}
self.mode(Mode::Standby)
}
pub fn send_large(&mut self, buffer: &[u8]) -> Result<(), Espi> {
let packet_size: u8 = buffer.len().try_into().or(Err(Error::PacketTooLarge))?;
self.mode(Mode::Standby)?;
while !self.is_mode_ready()? {}
self.reset_fifo()?;
self.write(Registers::Fifo, packet_size)?;
self.mode(Mode::Transmitter)?;
for b in buffer {
while self.is_fifo_full()? {}
self.write(Registers::Fifo, *b)?;
}
while !self.is_packet_sent()? {}
self.mode(Mode::Standby)
}
pub fn is_sync_address_match(&mut self) -> Result<bool, Espi> {
Ok(self.read(Registers::IrqFlags1)? & IrqFlags1::SyncAddressMatch != 0)
}
pub fn is_fifo_empty(&mut self) -> Result<bool, Espi> {
Ok(self.read(Registers::IrqFlags2)? & IrqFlags2::FifoNotEmpty == 0)
}
pub fn is_fifo_full(&mut self) -> Result<bool, Espi> {
Ok(self.read(Registers::IrqFlags2)? & IrqFlags2::FifoFull != 0)
}
pub fn is_packet_ready(&mut self) -> Result<bool, Espi> {
Ok(self.read(Registers::IrqFlags2)? & IrqFlags2::PayloadReady != 0)
}
pub fn is_mode_ready(&mut self) -> Result<bool, Espi> {
Ok((self.read(Registers::IrqFlags1)? & IrqFlags1::ModeReady) != 0)
}
pub fn is_packet_sent(&mut self) -> Result<bool, Espi> {
Ok((self.read(Registers::IrqFlags2)? & IrqFlags2::PacketSent) != 0)
}
pub fn lna(&mut self, lna: LnaConfig) -> Result<(), Espi> {
let reg = (lna.zin as u8) | (lna.gain_select as u8);
self.update(Registers::Lna, |r| (r & 0x78) | reg)
}
pub fn rssi_threshold(&mut self, threshold: u8) -> Result<(), Espi> {
self.write(Registers::RssiThresh, threshold)
}
pub fn sensitivity_boost(&mut self, boost: SensitivityBoost) -> Result<(), Espi> {
self.write(Registers::TestLna, boost as u8)
}
pub fn pa13_dbm1(&mut self, pa13: Pa13dBm1) -> Result<(), Espi> {
self.write(Registers::TestPa1, pa13 as u8)
}
pub fn pa13_dbm2(&mut self, pa13: Pa13dBm2) -> Result<(), Espi> {
self.write(Registers::TestPa2, pa13 as u8)
}
pub fn continuous_dagc(&mut self, cdagc: ContinuousDagc) -> Result<(), Espi> {
self.write(Registers::TestDagc, cdagc as u8)
}
pub fn rx_bw<RxBwT>(&mut self, rx_bw: RxBw<RxBwT>) -> Result<(), Espi>
where
RxBwT: RxBwFreq,
{
self.write(
Registers::RxBw,
rx_bw.dcc_cutoff as u8 | rx_bw.rx_bw.value(),
)
}
pub fn rx_afc_bw<RxBwT>(&mut self, rx_bw: RxBw<RxBwT>) -> Result<(), Espi>
where
RxBwT: RxBwFreq,
{
self.write(
Registers::AfcBw,
rx_bw.dcc_cutoff as u8 | rx_bw.rx_bw.value(),
)
}
pub fn write(&mut self, reg: Registers, val: u8) -> Result<(), Espi> {
self.write_many(reg, &[val])
}
pub fn write_many(&mut self, reg: Registers, data: &[u8]) -> Result<(), Espi> {
self.spi.write_many(reg, data).map_err(Error::Spi)
}
pub fn read(&mut self, reg: Registers) -> Result<u8, Espi> {
let mut buffer = [0u8; 1];
self.read_many(reg, &mut buffer)?;
Ok(buffer[0])
}
pub fn read_many(&mut self, reg: Registers, buffer: &mut [u8]) -> Result<(), Espi> {
self.spi.read_many(reg, buffer).map_err(Error::Spi)
}
fn dio(&mut self) -> Result<(), Espi> {
let mut reg = 0x07;
for mapping in self.dio.iter().flatten() {
if mapping.dio_mode.eq(self.mode) {
reg |= (mapping.dio_type as u16) << (mapping.pin as u16);
}
}
self.write_many(Registers::DioMapping1, ®.to_be_bytes())
}
fn read_rssi(&mut self) -> Result<i16, Espi> {
Ok(-i16::from(self.read(Registers::RssiValue)?) >> 1)
}
fn reset_fifo(&mut self) -> Result<(), Espi> {
self.write(Registers::IrqFlags2, IrqFlags2::FifoOverrun as u8)
}
fn update<F>(&mut self, reg: Registers, f: F) -> Result<(), Espi>
where
F: FnOnce(u8) -> u8,
{
let val = self.read(reg)?;
self.write(reg, f(val))
}
}