use crate::patable::{TX_POWERS_315, TX_POWERS_433, TX_POWERS_868, TX_POWERS_915};
use crate::{CC1101Error, ConfigError};
use std::fmt;
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u8)]
pub enum Modulation {
FSK2 = 0,
GFSK = 1,
OOK = 3,
FSK4 = 4,
MSK = 7,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum CarrierSense {
Relative(i8),
Absolute(i8),
}
impl fmt::Display for CarrierSense {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CarrierSense::Relative(v) => write!(f, "Relative(+{} dB)", v),
CarrierSense::Absolute(v) => write!(f, "Absolute({} dB)", v),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u8)]
enum CarrierSenseMode {
Disabled = 0,
Relative = 1,
Absolute = 2,
}
#[derive(Copy, Clone)]
pub enum RegistersType {
Device,
Tx,
Rx,
}
#[allow(non_snake_case)]
#[repr(C, packed)]
#[derive(Debug, Default)]
pub struct Registers {
pub IOCFG2: u8,
pub IOCFG1: u8,
pub IOCFG0: u8,
pub FIFOTHR: u8,
pub SYNC1: u8,
pub SYNC0: u8,
pub PKTLEN: u8,
pub PKTCTRL1: u8,
pub PKTCTRL0: u8,
pub ADDR: u8,
pub CHANNR: u8,
pub FSCTRL1: u8,
pub FSCTRL0: u8,
pub FREQ2: u8,
pub FREQ1: u8,
pub FREQ0: u8,
pub MDMCFG4: u8,
pub MDMCFG3: u8,
pub MDMCFG2: u8,
pub MDMCFG1: u8,
pub MDMCFG0: u8,
pub DEVIATN: u8,
pub MCSM2: u8,
pub MCSM1: u8,
pub MCSM0: u8,
pub FOCCFG: u8,
pub BSCFG: u8,
pub AGCCTRL2: u8,
pub AGCCTRL1: u8,
pub AGCCTRL0: u8,
pub WOREVT1: u8,
pub WOREVT0: u8,
pub WORCTRL: u8,
pub FREND1: u8,
pub FREND0: u8,
pub FSCAL3: u8,
pub FSCAL2: u8,
pub FSCAL1: u8,
pub FSCAL0: u8,
pub RCCTRL1: u8,
pub RCCTRL0: u8,
pub FSTEST: u8,
pub PTEST: u8,
pub AGCTEST: u8,
pub TEST2: u8,
pub TEST1: u8,
pub TEST0: u8,
}
#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct CommonConfig {
frequency: u32,
modulation: Modulation,
baud_rate_mantissa: u8,
baud_rate_exponent: u8,
deviation_mantissa: u8,
deviation_exponent: u8,
sync_word: u32,
}
impl Default for CommonConfig {
fn default() -> CommonConfig {
CommonConfig {
frequency: 0x10B071, modulation: Modulation::OOK,
baud_rate_mantissa: 0x43, baud_rate_exponent: 0x05,
deviation_mantissa: 0x07, deviation_exponent: 0x04,
sync_word: 0x0,
}
}
}
impl fmt::Display for CommonConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CommonConfig: {{Frequency: {} MHz, Modulation: {:?}, Baud Rate: {} kBaud, Deviation: {} kHz, Sync Word: 0x{:08x}}}", Self::get_frequency(self), self.modulation, Self::get_baud_rate(self), Self::get_deviation(self), self.sync_word)
}
}
#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct RXConfig {
common: CommonConfig,
bandwidth_mantissa: u8,
bandwidth_exponent: u8,
max_lna_gain: u8,
max_dvga_gain: u8,
magn_target: u8,
carrier_sense_mode: CarrierSenseMode,
carrier_sense: i8,
packet_length: u32,
}
impl Default for RXConfig {
fn default() -> RXConfig {
RXConfig {
common: CommonConfig::default(),
bandwidth_mantissa: 0x00, bandwidth_exponent: 0x02,
max_lna_gain: 0,
max_dvga_gain: 0,
magn_target: 33,
carrier_sense_mode: CarrierSenseMode::Relative,
carrier_sense: 6,
packet_length: 1024,
}
}
}
impl fmt::Display for RXConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let carrier_sense = match Self::get_carrier_sense(self) {
Some(v) => format!("{}", v),
None => "Disabled".to_owned(),
};
write!(f, "RXConfig: {{{}, Bandwidth: {} kHz, Max LNA Gain: {} dB, Max DVGA Gain: {} dB, Magn Target: {} dB, Carrier Sense: {}, Packet Length: {}}}", self.common, Self::get_bandwith(self), self.max_lna_gain, self.max_dvga_gain, self.magn_target, carrier_sense, self.packet_length)
}
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct TXConfig {
common: CommonConfig,
tx_power: u8,
}
impl fmt::Display for TXConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let tx_power = match Self::get_tx_power(self) {
Ok(tx_power) => format!("{} dBm", tx_power),
Err(_) => format!("{:02x}", self.tx_power),
};
write!(f, "TXConfig: {{{}, TX Power: {}}}", self.common, tx_power)
}
}
const XTAL_FREQ: f32 = 26.0;
fn round(value: f32, precision: u8) -> f32 {
let m = 10_f32.powi(precision as i32);
(value * m).round() / m
}
impl CommonConfig {
pub fn new(
frequency: f32,
modulation: Modulation,
baud_rate: f32,
deviation: Option<f32>,
sync_word: Option<u32>,
) -> Result<CommonConfig, CC1101Error> {
let mut config = CommonConfig::default();
config.set_frequency(frequency)?;
config.set_modulation_and_baud_rate(modulation, baud_rate)?;
if let Some(sync_word) = sync_word {
config.set_sync_word(sync_word)?;
} else {
config.set_sync_word(0x00)?;
}
if let Some(deviation) = deviation {
config.set_deviation(deviation)?;
}
Ok(config)
}
fn frequency_to_config(frequency: f32) -> Result<u32, CC1101Error> {
if !((299.99976..=347.99994).contains(&frequency)
|| (386.99994..=463.9998).contains(&frequency)
|| (778.9999..=928.000000).contains(&frequency))
{
return Err(CC1101Error::Config(ConfigError::InvalidFrequency));
}
let f = ((frequency * 65536_f32) / XTAL_FREQ) as u32;
Ok(f)
}
fn config_to_frequency(config: u32) -> f32 {
(XTAL_FREQ / 2.0_f32.powi(16)) * config as f32
}
pub fn set_frequency(&mut self, frequency: f32) -> Result<(), CC1101Error> {
self.frequency = CommonConfig::frequency_to_config(frequency)?;
Ok(())
}
pub fn get_frequency(&self) -> f32 {
CommonConfig::config_to_frequency(self.frequency)
}
fn baud_rate_to_config(
modulation: Modulation,
baud_rate: f32,
) -> Result<(u8, u8), CC1101Error> {
let valid_baud_rate = match modulation {
Modulation::GFSK | Modulation::OOK => (0.599742..=249.939).contains(&baud_rate),
Modulation::FSK2 => (0.599742..=500.0).contains(&baud_rate),
Modulation::FSK4 => (0.599742..=299.927).contains(&baud_rate),
Modulation::MSK => (25.9857..=499.878).contains(&baud_rate),
};
if !valid_baud_rate {
return Err(CC1101Error::Config(ConfigError::InvalidBaudRate));
}
let xtal_freq = XTAL_FREQ * 1000000.0;
let r_data = baud_rate * 1000.0;
let exponent = ((r_data * 2_f32.powi(20)) / xtal_freq).log(2.0).floor();
let mantissa =
((r_data * 2_f32.powi(28) / (xtal_freq * 2_f32.powf(exponent))) - 256_f32).round();
let mantissa = mantissa as u8;
let exponent = exponent as u8;
Ok((mantissa, exponent))
}
fn config_to_baud_rate(mantissa: u8, exponent: u8) -> f32 {
let xtal_freq = XTAL_FREQ * 1000000.0;
let r_data = ((((256 + mantissa as u32) as f32) * 2_f32.powi(exponent as i32))
/ 2_f32.powi(28))
* xtal_freq;
round(r_data / 1000.0, 6)
}
pub fn set_modulation_and_baud_rate(
&mut self,
modulation: Modulation,
baud_rate: f32,
) -> Result<(), CC1101Error> {
let (mantissa, exponent) = CommonConfig::baud_rate_to_config(modulation, baud_rate)?;
self.modulation = modulation;
self.baud_rate_mantissa = mantissa;
self.baud_rate_exponent = exponent;
Ok(())
}
pub fn get_modulation(&self) -> Modulation {
self.modulation
}
pub fn get_baud_rate(&self) -> f32 {
CommonConfig::config_to_baud_rate(self.baud_rate_mantissa, self.baud_rate_exponent)
}
fn config_to_deviation(mantissa: u8, exponent: u8) -> f32 {
let xtal_freq = XTAL_FREQ * 1000000.0;
let dev =
(xtal_freq / 2_f32.powi(17)) * (mantissa + 8) as f32 * 2_f32.powi(exponent as i32);
round(dev / 1000.0, 6)
}
fn deviation_to_config(deviation: f32) -> Result<(u8, u8), CC1101Error> {
for mantissa in 0..8 {
for exponent in 0..8 {
#[allow(clippy::float_cmp)]
if CommonConfig::config_to_deviation(mantissa, exponent) == deviation {
return Ok((mantissa, exponent));
}
}
}
Err(CC1101Error::Config(ConfigError::InvalidDeviation))
}
pub fn set_deviation(&mut self, deviation: f32) -> Result<(), CC1101Error> {
let (mantissa, exponent) = CommonConfig::deviation_to_config(deviation)?;
self.deviation_mantissa = mantissa;
self.deviation_exponent = exponent;
Ok(())
}
pub fn get_deviation(&self) -> f32 {
CommonConfig::config_to_deviation(self.deviation_mantissa, self.deviation_exponent)
}
fn sync_word_to_config(sync_word: u32) -> Result<u32, CC1101Error> {
if sync_word > 0xFFFF {
let lsb = sync_word & 0x0000FFFF;
let msb = sync_word >> 16;
if lsb != msb {
return Err(CC1101Error::Config(ConfigError::InvalidSyncWord));
}
}
Ok(sync_word)
}
pub fn set_sync_word(&mut self, sync_word: u32) -> Result<(), CC1101Error> {
self.sync_word = CommonConfig::sync_word_to_config(sync_word)?;
Ok(())
}
pub fn get_sync_word(&self) -> u32 {
self.sync_word
}
}
impl RXConfig {
#[allow(clippy::too_many_arguments)]
pub fn new(
frequency: f32,
modulation: Modulation,
baud_rate: f32,
packet_length: u32,
deviation: Option<f32>,
sync_word: Option<u32>,
bandwidth: Option<u32>,
carrier_sense: Option<CarrierSense>,
max_lna_gain: Option<u8>,
max_dvga_gain: Option<u8>,
magn_target: Option<u8>,
) -> Result<RXConfig, CC1101Error> {
let common = CommonConfig::new(frequency, modulation, baud_rate, deviation, sync_word)?;
let mut rx_config = RXConfig {
common,
packet_length,
..RXConfig::default()
};
rx_config.set_carrier_sense(carrier_sense)?;
if let Some(bandwidth) = bandwidth {
rx_config.set_bandwidth(bandwidth)?;
}
if let Some(max_lna_gain) = max_lna_gain {
rx_config.set_max_lna_gain(max_lna_gain)?;
}
if let Some(max_dvga_gain) = max_dvga_gain {
rx_config.set_max_dvga_gain(max_dvga_gain)?;
}
if let Some(magn_target) = magn_target {
rx_config.set_magn_target(magn_target)?;
}
Ok(rx_config)
}
pub fn get_common_config(&self) -> &CommonConfig {
&self.common
}
pub fn get_common_config_mut(&mut self) -> &mut CommonConfig {
&mut self.common
}
fn config_to_bandwidth(mantissa: u8, exponent: u8) -> u32 {
let xtal_freq = XTAL_FREQ * 1000000.0;
let bw_channel = xtal_freq / (8.0 * (mantissa as f32 + 4.0) * 2_f32.powi(exponent as i32));
(bw_channel / 1000.0) as u32
}
fn bandwidth_to_config(bandwidth: u32) -> Result<(u8, u8), CC1101Error> {
for mantissa in 0..4 {
for exponent in 0..4 {
#[allow(clippy::float_cmp)]
if bandwidth == RXConfig::config_to_bandwidth(mantissa, exponent) {
return Ok((mantissa, exponent));
}
}
}
Err(CC1101Error::Config(ConfigError::InvalidBandwidth))
}
pub fn set_bandwidth(&mut self, bandwidth: u32) -> Result<(), CC1101Error> {
let (mantissa, exponent) = RXConfig::bandwidth_to_config(bandwidth)?;
self.bandwidth_mantissa = mantissa;
self.bandwidth_exponent = exponent;
Ok(())
}
pub fn get_bandwith(&self) -> u32 {
RXConfig::config_to_bandwidth(self.bandwidth_mantissa, self.bandwidth_exponent)
}
pub fn set_carrier_sense(
&mut self,
carrier_sense: Option<CarrierSense>,
) -> Result<(), CC1101Error> {
match carrier_sense {
Some(CarrierSense::Relative(carrier_sense)) => match carrier_sense {
6 | 10 | 14 => {
self.carrier_sense_mode = CarrierSenseMode::Relative;
self.carrier_sense = carrier_sense;
}
_ => return Err(CC1101Error::Config(ConfigError::InvalidCarrierSense)),
},
Some(CarrierSense::Absolute(carrier_sense)) => match carrier_sense {
-7..=7 => {
self.carrier_sense_mode = CarrierSenseMode::Absolute;
self.carrier_sense = carrier_sense;
}
_ => return Err(CC1101Error::Config(ConfigError::InvalidCarrierSense)),
},
None => {
self.carrier_sense_mode = CarrierSenseMode::Disabled;
self.carrier_sense = 0;
}
}
Ok(())
}
pub fn get_carrier_sense(&self) -> Option<CarrierSense> {
match self.carrier_sense_mode {
CarrierSenseMode::Disabled => None,
CarrierSenseMode::Relative => Some(CarrierSense::Relative(self.carrier_sense)),
CarrierSenseMode::Absolute => Some(CarrierSense::Absolute(self.carrier_sense)),
}
}
pub fn set_max_lna_gain(&mut self, max_lna_gain: u8) -> Result<(), CC1101Error> {
match max_lna_gain {
0 | 3 | 6 | 7 | 9 | 12 | 15 | 17 => self.max_lna_gain = max_lna_gain,
_ => return Err(CC1101Error::Config(ConfigError::InvalidMaxLNAGain)),
}
Ok(())
}
pub fn get_max_lna_gain(&self) -> u8 {
self.max_lna_gain
}
pub fn set_max_dvga_gain(&mut self, max_dvga_gain: u8) -> Result<(), CC1101Error> {
match max_dvga_gain {
0 | 6 | 12 | 18 => self.max_dvga_gain = max_dvga_gain,
_ => return Err(CC1101Error::Config(ConfigError::InvalidMaxDVGAGain)),
}
Ok(())
}
pub fn get_max_dvga_gain(&self) -> u8 {
self.max_dvga_gain
}
pub fn set_magn_target(&mut self, magn_target: u8) -> Result<(), CC1101Error> {
match magn_target {
24 | 27 | 30 | 33 | 36 | 38 | 40 | 42 => self.magn_target = magn_target,
_ => return Err(CC1101Error::Config(ConfigError::InvalidMagnTarget)),
}
Ok(())
}
pub fn get_magn_target(&self) -> u8 {
self.magn_target
}
pub fn set_packet_length(&mut self, packet_length: u32) {
self.packet_length = packet_length
}
pub fn get_packet_length(&self) -> u32 {
self.packet_length
}
}
impl TXConfig {
fn frequency_near(frequency: f32, target_frequency: f32) -> bool {
(frequency - target_frequency).abs() < 1.0
}
fn get_power_table(frequency: f32) -> Result<&'static [(u8, f32)], CC1101Error> {
if Self::frequency_near(frequency, 315.0) {
Ok(TX_POWERS_315)
} else if Self::frequency_near(frequency, 433.0) {
Ok(TX_POWERS_433)
} else if Self::frequency_near(frequency, 868.0) {
Ok(TX_POWERS_868)
} else if Self::frequency_near(frequency, 915.0) {
Ok(TX_POWERS_915)
} else {
Err(CC1101Error::Config(ConfigError::InvalidFrequency))
}
}
pub fn new(
frequency: f32,
modulation: Modulation,
baud_rate: f32,
tx_power: f32,
deviation: Option<f32>,
sync_word: Option<u32>,
) -> Result<TXConfig, CC1101Error> {
let common = CommonConfig::new(frequency, modulation, baud_rate, deviation, sync_word)?;
let mut tx_config = TXConfig {
common,
..TXConfig::default()
};
tx_config.set_tx_power(tx_power)?;
Ok(tx_config)
}
pub fn get_common_config(&self) -> &CommonConfig {
&self.common
}
pub fn get_common_config_mut(&mut self) -> &mut CommonConfig {
&mut self.common
}
pub fn new_raw(
frequency: f32,
modulation: Modulation,
baud_rate: f32,
tx_power: u8,
deviation: Option<f32>,
sync_word: Option<u32>,
) -> Result<TXConfig, CC1101Error> {
let common = CommonConfig::new(frequency, modulation, baud_rate, deviation, sync_word)?;
Ok(TXConfig { common, tx_power })
}
fn tx_power_to_config(frequency: f32, tx_power: f32) -> Result<u8, CC1101Error> {
let power_table = Self::get_power_table(frequency)?;
for (hex, dbm) in power_table {
if (dbm - tx_power).abs() < f32::EPSILON {
return Ok(*hex);
}
}
Err(CC1101Error::Config(ConfigError::InvalidTXPower))
}
fn config_to_tx_power(frequency: f32, tx_power: u8) -> Result<f32, CC1101Error> {
let power_table = Self::get_power_table(frequency)?;
for (hex, dbm) in power_table {
if *hex == tx_power {
return Ok(*dbm);
}
}
Err(CC1101Error::Config(ConfigError::InvalidTXPower))
}
pub fn set_tx_power(&mut self, tx_power: f32) -> Result<(), CC1101Error> {
self.tx_power = Self::tx_power_to_config(self.common.get_frequency(), tx_power)?;
Ok(())
}
pub fn get_tx_power(&self) -> Result<f32, CC1101Error> {
Self::config_to_tx_power(self.common.get_frequency(), self.tx_power)
}
pub fn set_tx_power_raw(&mut self, tx_power: u8) {
self.tx_power = tx_power;
}
pub fn get_tx_power_raw(&self) -> u8 {
self.tx_power
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::excessive_precision)]
use super::*;
#[test]
fn test_freq() -> Result<(), CC1101Error> {
assert_eq!(CommonConfig::frequency_to_config(315.0)?, 0x000C1D89);
assert_eq!(CommonConfig::frequency_to_config(433.0)?, 0x0010A762);
assert_eq!(CommonConfig::frequency_to_config(868.0)?, 0x00216276);
assert_eq!(CommonConfig::frequency_to_config(915.0)?, 0x0023313B);
assert_eq!(CommonConfig::frequency_to_config(299.999756)?, 0x000B89D8);
assert_eq!(CommonConfig::frequency_to_config(347.999939)?, 0x000D6276);
assert_eq!(CommonConfig::frequency_to_config(386.999939)?, 0x000EE276);
assert_eq!(CommonConfig::frequency_to_config(463.999786)?, 0x0011D89D);
assert_eq!(CommonConfig::frequency_to_config(778.999878)?, 0x001DF627);
assert_eq!(CommonConfig::frequency_to_config(928.000000)?, 0x0023B13B);
assert_eq!(CommonConfig::config_to_frequency(0x000B89D8), 299.999756);
assert_eq!(CommonConfig::config_to_frequency(0x000D6276), 347.999939);
assert_eq!(CommonConfig::config_to_frequency(0x000EE276), 386.999939);
assert_eq!(CommonConfig::config_to_frequency(0x0011D89D), 463.999786);
assert_eq!(CommonConfig::config_to_frequency(0x001DF627), 778.999878);
assert_eq!(CommonConfig::config_to_frequency(0x0023B13B), 928.000000);
assert_eq!(CommonConfig::config_to_frequency(0x000C1D89), 314.999664);
assert_eq!(CommonConfig::config_to_frequency(0x0010A762), 432.999817);
assert_eq!(CommonConfig::config_to_frequency(0x00216276), 867.999939);
assert_eq!(CommonConfig::config_to_frequency(0x0023313B), 915.000000);
assert!(CommonConfig::frequency_to_config(0.0).is_err());
assert!(CommonConfig::frequency_to_config(464.0).is_err());
assert!(CommonConfig::frequency_to_config(999.0).is_err());
Ok(())
}
#[test]
fn test_baud_rate() -> Result<(), CC1101Error> {
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 0.6)?,
(0x83, 0x04)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 0.599742)?,
(0x83, 0x04)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 26.0)?,
(0x06, 0x0A)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 25.9857)?,
(0x06, 0x0A)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 250.0)?,
(0x3B, 0x0D)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 249.939)?,
(0x3B, 0x0D)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 300.0)?,
(0x7A, 0x0D)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 299.927)?,
(0x7A, 0x0D)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 500.0)?,
(0x3B, 0x0E)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 499.878)?,
(0x3B, 0x0E)
);
assert_eq!(
CommonConfig::baud_rate_to_config(Modulation::FSK2, 115.051)?,
(0x22, 0x0C)
);
assert_eq!(CommonConfig::config_to_baud_rate(0x83, 0x04), 0.599742);
assert_eq!(CommonConfig::config_to_baud_rate(0x06, 0x0A), 25.98572);
assert_eq!(CommonConfig::config_to_baud_rate(0x3B, 0x0D), 249.93896);
assert_eq!(CommonConfig::config_to_baud_rate(0x7A, 0x0D), 299.92676);
assert_eq!(CommonConfig::config_to_baud_rate(0x3B, 0x0E), 499.87793);
assert_eq!(CommonConfig::config_to_baud_rate(0x22, 0x0C), 115.05126);
assert!(CommonConfig::baud_rate_to_config(Modulation::FSK2, 0.0).is_err());
assert!(CommonConfig::baud_rate_to_config(Modulation::FSK2, 999.0).is_err());
Ok(())
}
#[test]
fn test_deviation() -> Result<(), CC1101Error> {
assert_eq!(CommonConfig::deviation_to_config(1.586914)?, (0x00, 0x00));
assert_eq!(CommonConfig::deviation_to_config(380.85938)?, (0x07, 0x07));
assert_eq!(CommonConfig::config_to_deviation(0x00, 0x00), 1.586914);
assert_eq!(CommonConfig::config_to_deviation(0x07, 0x07), 380.859375);
assert!(CommonConfig::deviation_to_config(0.0).is_err());
assert!(CommonConfig::deviation_to_config(400.0).is_err());
Ok(())
}
#[test]
fn test_sync_word() -> Result<(), CC1101Error> {
CommonConfig::sync_word_to_config(0x00000000)?;
CommonConfig::sync_word_to_config(0x0000FFFF)?;
CommonConfig::sync_word_to_config(0xFFFFFFFF)?;
assert!(CommonConfig::sync_word_to_config(0xFFFF0000).is_err());
assert!(CommonConfig::sync_word_to_config(0xAAAABBBB).is_err());
Ok(())
}
#[test]
fn test_bandwidth() -> Result<(), CC1101Error> {
assert_eq!(RXConfig::bandwidth_to_config(812)?, (0x00, 0x00));
assert_eq!(RXConfig::bandwidth_to_config(58)?, (0x03, 0x03));
assert_eq!(RXConfig::config_to_bandwidth(0x00, 0x00), 812);
assert_eq!(RXConfig::config_to_bandwidth(0x03, 0x03), 58);
assert!(RXConfig::bandwidth_to_config(0).is_err());
assert!(RXConfig::bandwidth_to_config(400).is_err());
Ok(())
}
#[test]
fn test_tx_power() -> Result<(), CC1101Error> {
assert!(TXConfig::config_to_tx_power(123.0, 0xFF).is_err());
assert!(TXConfig::config_to_tx_power(433.0, 0xFF).is_err());
assert!(TXConfig::tx_power_to_config(433.0, -1.0).is_err());
for frequency in [315.0, 433.0, 868.0, 915.0] {
let power_table = TXConfig::get_power_table(frequency)?;
for (hex, dbm) in power_table {
assert_eq!(TXConfig::config_to_tx_power(frequency, *hex)?, *dbm);
assert_eq!(TXConfig::tx_power_to_config(frequency, *dbm)?, *hex);
}
}
Ok(())
}
}