1use crate::patable::{TX_POWERS_315, TX_POWERS_433, TX_POWERS_868, TX_POWERS_915};
6use crate::{CC1101Error, ConfigError};
7use std::fmt;
8
9#[derive(Debug, Copy, Clone, PartialEq)]
11#[repr(u8)]
12pub enum Modulation {
13 FSK2 = 0,
15 GFSK = 1,
17 OOK = 3,
19 FSK4 = 4,
21 MSK = 7,
23}
24
25#[derive(Debug, Copy, Clone, PartialEq)]
26pub enum CarrierSense {
27 Relative(i8),
28 Absolute(i8),
29}
30
31impl fmt::Display for CarrierSense {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 CarrierSense::Relative(v) => write!(f, "Relative(+{} dB)", v),
35 CarrierSense::Absolute(v) => write!(f, "Absolute({} dB)", v),
36 }
37 }
38}
39
40#[derive(Debug, Copy, Clone, PartialEq)]
41#[repr(u8)]
42enum CarrierSenseMode {
43 Disabled = 0,
44 Relative = 1,
45 Absolute = 2,
46}
47
48#[derive(Copy, Clone)]
50pub enum RegistersType {
51 Device,
53 Tx,
55 Rx,
57}
58
59#[allow(non_snake_case)]
61#[repr(C, packed)]
62#[derive(Debug, Default)]
63pub struct Registers {
64 pub IOCFG2: u8,
66 pub IOCFG1: u8,
68 pub IOCFG0: u8,
70 pub FIFOTHR: u8,
72 pub SYNC1: u8,
74 pub SYNC0: u8,
76 pub PKTLEN: u8,
78 pub PKTCTRL1: u8,
80 pub PKTCTRL0: u8,
82 pub ADDR: u8,
84 pub CHANNR: u8,
86 pub FSCTRL1: u8,
88 pub FSCTRL0: u8,
90 pub FREQ2: u8,
92 pub FREQ1: u8,
94 pub FREQ0: u8,
96 pub MDMCFG4: u8,
98 pub MDMCFG3: u8,
100 pub MDMCFG2: u8,
102 pub MDMCFG1: u8,
104 pub MDMCFG0: u8,
106 pub DEVIATN: u8,
108 pub MCSM2: u8,
110 pub MCSM1: u8,
112 pub MCSM0: u8,
114 pub FOCCFG: u8,
116 pub BSCFG: u8,
118 pub AGCCTRL2: u8,
120 pub AGCCTRL1: u8,
122 pub AGCCTRL0: u8,
124 pub WOREVT1: u8,
126 pub WOREVT0: u8,
128 pub WORCTRL: u8,
130 pub FREND1: u8,
132 pub FREND0: u8,
134 pub FSCAL3: u8,
136 pub FSCAL2: u8,
138 pub FSCAL1: u8,
140 pub FSCAL0: u8,
142 pub RCCTRL1: u8,
144 pub RCCTRL0: u8,
146 pub FSTEST: u8,
148 pub PTEST: u8,
150 pub AGCTEST: u8,
152 pub TEST2: u8,
154 pub TEST1: u8,
156 pub TEST0: u8,
158}
159
160#[repr(C)]
162#[derive(Debug, Clone, PartialEq)]
163pub struct CommonConfig {
164 frequency: u32,
165 modulation: Modulation,
166 baud_rate_mantissa: u8,
167 baud_rate_exponent: u8,
168 deviation_mantissa: u8,
169 deviation_exponent: u8,
170 sync_word: u32,
171}
172
173impl Default for CommonConfig {
174 fn default() -> CommonConfig {
175 CommonConfig {
176 frequency: 0x10B071, modulation: Modulation::OOK,
178 baud_rate_mantissa: 0x43, baud_rate_exponent: 0x05,
180 deviation_mantissa: 0x07, deviation_exponent: 0x04,
182 sync_word: 0x0,
183 }
184 }
185}
186
187impl fmt::Display for CommonConfig {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 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)
190 }
191}
192
193#[repr(C)]
195#[derive(Debug, Clone, PartialEq)]
196pub struct RXConfig {
197 common: CommonConfig,
198 bandwidth_mantissa: u8,
199 bandwidth_exponent: u8,
200 max_lna_gain: u8,
201 max_dvga_gain: u8,
202 magn_target: u8,
203 carrier_sense_mode: CarrierSenseMode,
204 carrier_sense: i8,
205 packet_length: u32,
206}
207
208impl Default for RXConfig {
209 fn default() -> RXConfig {
210 RXConfig {
211 common: CommonConfig::default(),
212 bandwidth_mantissa: 0x00, bandwidth_exponent: 0x02,
214 max_lna_gain: 0,
215 max_dvga_gain: 0,
216 magn_target: 33,
217 carrier_sense_mode: CarrierSenseMode::Relative,
218 carrier_sense: 6,
219 packet_length: 1024,
220 }
221 }
222}
223
224impl fmt::Display for RXConfig {
225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226 let carrier_sense = match Self::get_carrier_sense(self) {
227 Some(v) => format!("{}", v),
228 None => "Disabled".to_owned(),
229 };
230
231 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)
232 }
233}
234
235#[repr(C)]
237#[derive(Debug, Default)]
238pub struct TXConfig {
239 common: CommonConfig,
240 tx_power: u8,
241}
242
243impl fmt::Display for TXConfig {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 let tx_power = match Self::get_tx_power(self) {
246 Ok(tx_power) => format!("{} dBm", tx_power),
247 Err(_) => format!("{:02x}", self.tx_power),
248 };
249
250 write!(f, "TXConfig: {{{}, TX Power: {}}}", self.common, tx_power)
251 }
252}
253
254const XTAL_FREQ: f32 = 26.0;
255
256fn round(value: f32, precision: u8) -> f32 {
257 let m = 10_f32.powi(precision as i32);
258 (value * m).round() / m
259}
260
261impl CommonConfig {
262 pub fn new(
272 frequency: f32,
273 modulation: Modulation,
274 baud_rate: f32,
275 deviation: Option<f32>,
276 sync_word: Option<u32>,
277 ) -> Result<CommonConfig, CC1101Error> {
278 let mut config = CommonConfig::default();
279 config.set_frequency(frequency)?;
280 config.set_modulation_and_baud_rate(modulation, baud_rate)?;
281
282 if let Some(sync_word) = sync_word {
283 config.set_sync_word(sync_word)?;
284 } else {
285 config.set_sync_word(0x00)?;
286 }
287
288 if let Some(deviation) = deviation {
289 config.set_deviation(deviation)?;
290 }
291
292 Ok(config)
293 }
294
295 fn frequency_to_config(frequency: f32) -> Result<u32, CC1101Error> {
298 if !((299.99976..=347.99994).contains(&frequency)
299 || (386.99994..=463.9998).contains(&frequency)
300 || (778.9999..=928.000000).contains(&frequency))
301 {
302 return Err(CC1101Error::Config(ConfigError::InvalidFrequency));
303 }
304
305 let f = ((frequency * 65536_f32) / XTAL_FREQ) as u32;
306 Ok(f)
307 }
308
309 fn config_to_frequency(config: u32) -> f32 {
312 (XTAL_FREQ / 2.0_f32.powi(16)) * config as f32
313 }
314
315 pub fn set_frequency(&mut self, frequency: f32) -> Result<(), CC1101Error> {
319 self.frequency = CommonConfig::frequency_to_config(frequency)?;
320 Ok(())
321 }
322
323 pub fn get_frequency(&self) -> f32 {
325 CommonConfig::config_to_frequency(self.frequency)
326 }
327
328 fn baud_rate_to_config(
332 modulation: Modulation,
333 baud_rate: f32,
334 ) -> Result<(u8, u8), CC1101Error> {
335 let valid_baud_rate = match modulation {
336 Modulation::GFSK | Modulation::OOK => (0.599742..=249.939).contains(&baud_rate),
337 Modulation::FSK2 => (0.599742..=500.0).contains(&baud_rate),
338 Modulation::FSK4 => (0.599742..=299.927).contains(&baud_rate),
339 Modulation::MSK => (25.9857..=499.878).contains(&baud_rate),
340 };
341
342 if !valid_baud_rate {
343 return Err(CC1101Error::Config(ConfigError::InvalidBaudRate));
344 }
345
346 let xtal_freq = XTAL_FREQ * 1000000.0;
347
348 let r_data = baud_rate * 1000.0;
349
350 let exponent = ((r_data * 2_f32.powi(20)) / xtal_freq).log(2.0).floor();
351 let mantissa =
352 ((r_data * 2_f32.powi(28) / (xtal_freq * 2_f32.powf(exponent))) - 256_f32).round();
353
354 let mantissa = mantissa as u8;
355 let exponent = exponent as u8;
356
357 Ok((mantissa, exponent))
358 }
359
360 fn config_to_baud_rate(mantissa: u8, exponent: u8) -> f32 {
362 let xtal_freq = XTAL_FREQ * 1000000.0;
363
364 let r_data = ((((256 + mantissa as u32) as f32) * 2_f32.powi(exponent as i32))
365 / 2_f32.powi(28))
366 * xtal_freq;
367
368 round(r_data / 1000.0, 6)
369 }
370
371 pub fn set_modulation_and_baud_rate(
384 &mut self,
385 modulation: Modulation,
386 baud_rate: f32,
387 ) -> Result<(), CC1101Error> {
388 let (mantissa, exponent) = CommonConfig::baud_rate_to_config(modulation, baud_rate)?;
389 self.modulation = modulation;
390 self.baud_rate_mantissa = mantissa;
391 self.baud_rate_exponent = exponent;
392 Ok(())
393 }
394
395 pub fn get_modulation(&self) -> Modulation {
397 self.modulation
398 }
399
400 pub fn get_baud_rate(&self) -> f32 {
402 CommonConfig::config_to_baud_rate(self.baud_rate_mantissa, self.baud_rate_exponent)
403 }
404
405 fn config_to_deviation(mantissa: u8, exponent: u8) -> f32 {
409 let xtal_freq = XTAL_FREQ * 1000000.0;
410 let dev =
411 (xtal_freq / 2_f32.powi(17)) * (mantissa + 8) as f32 * 2_f32.powi(exponent as i32);
412 round(dev / 1000.0, 6)
413 }
414
415 fn deviation_to_config(deviation: f32) -> Result<(u8, u8), CC1101Error> {
417 for mantissa in 0..8 {
418 for exponent in 0..8 {
419 #[allow(clippy::float_cmp)]
420 if CommonConfig::config_to_deviation(mantissa, exponent) == deviation {
421 return Ok((mantissa, exponent));
422 }
423 }
424 }
425 Err(CC1101Error::Config(ConfigError::InvalidDeviation))
426 }
427
428 pub fn set_deviation(&mut self, deviation: f32) -> Result<(), CC1101Error> {
430 let (mantissa, exponent) = CommonConfig::deviation_to_config(deviation)?;
431 self.deviation_mantissa = mantissa;
432 self.deviation_exponent = exponent;
433 Ok(())
434 }
435
436 pub fn get_deviation(&self) -> f32 {
438 CommonConfig::config_to_deviation(self.deviation_mantissa, self.deviation_exponent)
439 }
440
441 fn sync_word_to_config(sync_word: u32) -> Result<u32, CC1101Error> {
443 if sync_word > 0xFFFF {
444 let lsb = sync_word & 0x0000FFFF;
445 let msb = sync_word >> 16;
446
447 if lsb != msb {
448 return Err(CC1101Error::Config(ConfigError::InvalidSyncWord));
449 }
450 }
451 Ok(sync_word)
452 }
453
454 pub fn set_sync_word(&mut self, sync_word: u32) -> Result<(), CC1101Error> {
462 self.sync_word = CommonConfig::sync_word_to_config(sync_word)?;
463 Ok(())
464 }
465
466 pub fn get_sync_word(&self) -> u32 {
468 self.sync_word
469 }
470}
471
472impl RXConfig {
473 #[allow(clippy::too_many_arguments)]
485 pub fn new(
486 frequency: f32,
487 modulation: Modulation,
488 baud_rate: f32,
489 packet_length: u32,
490 deviation: Option<f32>,
491 sync_word: Option<u32>,
492 bandwidth: Option<u32>,
493 carrier_sense: Option<CarrierSense>,
494 max_lna_gain: Option<u8>,
495 max_dvga_gain: Option<u8>,
496 magn_target: Option<u8>,
497 ) -> Result<RXConfig, CC1101Error> {
498 let common = CommonConfig::new(frequency, modulation, baud_rate, deviation, sync_word)?;
499
500 let mut rx_config = RXConfig {
501 common,
502 packet_length,
503 ..RXConfig::default()
504 };
505
506 rx_config.set_carrier_sense(carrier_sense)?;
507
508 if let Some(bandwidth) = bandwidth {
509 rx_config.set_bandwidth(bandwidth)?;
510 }
511
512 if let Some(max_lna_gain) = max_lna_gain {
513 rx_config.set_max_lna_gain(max_lna_gain)?;
514 }
515
516 if let Some(max_dvga_gain) = max_dvga_gain {
517 rx_config.set_max_dvga_gain(max_dvga_gain)?;
518 }
519
520 if let Some(magn_target) = magn_target {
521 rx_config.set_magn_target(magn_target)?;
522 }
523
524 Ok(rx_config)
525 }
526
527 pub fn get_common_config(&self) -> &CommonConfig {
529 &self.common
530 }
531
532 pub fn get_common_config_mut(&mut self) -> &mut CommonConfig {
534 &mut self.common
535 }
536
537 fn config_to_bandwidth(mantissa: u8, exponent: u8) -> u32 {
541 let xtal_freq = XTAL_FREQ * 1000000.0;
542 let bw_channel = xtal_freq / (8.0 * (mantissa as f32 + 4.0) * 2_f32.powi(exponent as i32));
543 (bw_channel / 1000.0) as u32
544 }
545
546 fn bandwidth_to_config(bandwidth: u32) -> Result<(u8, u8), CC1101Error> {
548 for mantissa in 0..4 {
549 for exponent in 0..4 {
550 #[allow(clippy::float_cmp)]
551 if bandwidth == RXConfig::config_to_bandwidth(mantissa, exponent) {
552 return Ok((mantissa, exponent));
553 }
554 }
555 }
556 Err(CC1101Error::Config(ConfigError::InvalidBandwidth))
557 }
558
559 pub fn set_bandwidth(&mut self, bandwidth: u32) -> Result<(), CC1101Error> {
563 let (mantissa, exponent) = RXConfig::bandwidth_to_config(bandwidth)?;
564 self.bandwidth_mantissa = mantissa;
565 self.bandwidth_exponent = exponent;
566 Ok(())
567 }
568
569 pub fn get_bandwith(&self) -> u32 {
571 RXConfig::config_to_bandwidth(self.bandwidth_mantissa, self.bandwidth_exponent)
572 }
573
574 pub fn set_carrier_sense(
583 &mut self,
584 carrier_sense: Option<CarrierSense>,
585 ) -> Result<(), CC1101Error> {
586 match carrier_sense {
587 Some(CarrierSense::Relative(carrier_sense)) => match carrier_sense {
588 6 | 10 | 14 => {
589 self.carrier_sense_mode = CarrierSenseMode::Relative;
590 self.carrier_sense = carrier_sense;
591 }
592 _ => return Err(CC1101Error::Config(ConfigError::InvalidCarrierSense)),
593 },
594 Some(CarrierSense::Absolute(carrier_sense)) => match carrier_sense {
595 -7..=7 => {
596 self.carrier_sense_mode = CarrierSenseMode::Absolute;
597 self.carrier_sense = carrier_sense;
598 }
599 _ => return Err(CC1101Error::Config(ConfigError::InvalidCarrierSense)),
600 },
601 None => {
602 self.carrier_sense_mode = CarrierSenseMode::Disabled;
603 self.carrier_sense = 0;
604 }
605 }
606 Ok(())
607 }
608
609 pub fn get_carrier_sense(&self) -> Option<CarrierSense> {
611 match self.carrier_sense_mode {
612 CarrierSenseMode::Disabled => None,
613 CarrierSenseMode::Relative => Some(CarrierSense::Relative(self.carrier_sense)),
614 CarrierSenseMode::Absolute => Some(CarrierSense::Absolute(self.carrier_sense)),
615 }
616 }
617
618 pub fn set_max_lna_gain(&mut self, max_lna_gain: u8) -> Result<(), CC1101Error> {
621 match max_lna_gain {
622 0 | 3 | 6 | 7 | 9 | 12 | 15 | 17 => self.max_lna_gain = max_lna_gain,
623 _ => return Err(CC1101Error::Config(ConfigError::InvalidMaxLNAGain)),
624 }
625 Ok(())
626 }
627
628 pub fn get_max_lna_gain(&self) -> u8 {
630 self.max_lna_gain
631 }
632
633 pub fn set_max_dvga_gain(&mut self, max_dvga_gain: u8) -> Result<(), CC1101Error> {
636 match max_dvga_gain {
637 0 | 6 | 12 | 18 => self.max_dvga_gain = max_dvga_gain,
638 _ => return Err(CC1101Error::Config(ConfigError::InvalidMaxDVGAGain)),
639 }
640 Ok(())
641 }
642
643 pub fn get_max_dvga_gain(&self) -> u8 {
645 self.max_dvga_gain
646 }
647
648 pub fn set_magn_target(&mut self, magn_target: u8) -> Result<(), CC1101Error> {
651 match magn_target {
652 24 | 27 | 30 | 33 | 36 | 38 | 40 | 42 => self.magn_target = magn_target,
653 _ => return Err(CC1101Error::Config(ConfigError::InvalidMagnTarget)),
654 }
655 Ok(())
656 }
657
658 pub fn get_magn_target(&self) -> u8 {
660 self.magn_target
661 }
662
663 pub fn set_packet_length(&mut self, packet_length: u32) {
665 self.packet_length = packet_length
666 }
667
668 pub fn get_packet_length(&self) -> u32 {
670 self.packet_length
671 }
672}
673
674impl TXConfig {
675 fn frequency_near(frequency: f32, target_frequency: f32) -> bool {
677 (frequency - target_frequency).abs() < 1.0
678 }
679
680 fn get_power_table(frequency: f32) -> Result<&'static [(u8, f32)], CC1101Error> {
682 if Self::frequency_near(frequency, 315.0) {
683 Ok(TX_POWERS_315)
684 } else if Self::frequency_near(frequency, 433.0) {
685 Ok(TX_POWERS_433)
686 } else if Self::frequency_near(frequency, 868.0) {
687 Ok(TX_POWERS_868)
688 } else if Self::frequency_near(frequency, 915.0) {
689 Ok(TX_POWERS_915)
690 } else {
691 Err(CC1101Error::Config(ConfigError::InvalidFrequency))
692 }
693 }
694
695 pub fn new(
711 frequency: f32,
712 modulation: Modulation,
713 baud_rate: f32,
714 tx_power: f32,
715 deviation: Option<f32>,
716 sync_word: Option<u32>,
717 ) -> Result<TXConfig, CC1101Error> {
718 let common = CommonConfig::new(frequency, modulation, baud_rate, deviation, sync_word)?;
719
720 let mut tx_config = TXConfig {
721 common,
722 ..TXConfig::default()
723 };
724
725 tx_config.set_tx_power(tx_power)?;
726
727 Ok(tx_config)
728 }
729
730 pub fn get_common_config(&self) -> &CommonConfig {
732 &self.common
733 }
734
735 pub fn get_common_config_mut(&mut self) -> &mut CommonConfig {
737 &mut self.common
738 }
739
740 pub fn new_raw(
754 frequency: f32,
755 modulation: Modulation,
756 baud_rate: f32,
757 tx_power: u8,
758 deviation: Option<f32>,
759 sync_word: Option<u32>,
760 ) -> Result<TXConfig, CC1101Error> {
761 let common = CommonConfig::new(frequency, modulation, baud_rate, deviation, sync_word)?;
762 Ok(TXConfig { common, tx_power })
763 }
764
765 fn tx_power_to_config(frequency: f32, tx_power: f32) -> Result<u8, CC1101Error> {
769 let power_table = Self::get_power_table(frequency)?;
770
771 for (hex, dbm) in power_table {
772 if (dbm - tx_power).abs() < f32::EPSILON {
773 return Ok(*hex);
774 }
775 }
776
777 Err(CC1101Error::Config(ConfigError::InvalidTXPower))
778 }
779
780 fn config_to_tx_power(frequency: f32, tx_power: u8) -> Result<f32, CC1101Error> {
784 let power_table = Self::get_power_table(frequency)?;
785
786 for (hex, dbm) in power_table {
787 if *hex == tx_power {
788 return Ok(*dbm);
789 }
790 }
791
792 Err(CC1101Error::Config(ConfigError::InvalidTXPower))
793 }
794
795 pub fn set_tx_power(&mut self, tx_power: f32) -> Result<(), CC1101Error> {
799 self.tx_power = Self::tx_power_to_config(self.common.get_frequency(), tx_power)?;
800 Ok(())
801 }
802
803 pub fn get_tx_power(&self) -> Result<f32, CC1101Error> {
807 Self::config_to_tx_power(self.common.get_frequency(), self.tx_power)
808 }
809
810 pub fn set_tx_power_raw(&mut self, tx_power: u8) {
812 self.tx_power = tx_power;
813 }
814
815 pub fn get_tx_power_raw(&self) -> u8 {
817 self.tx_power
818 }
819}
820
821#[cfg(test)]
822mod tests {
823 #![allow(clippy::excessive_precision)]
824 use super::*;
825
826 #[test]
827 fn test_freq() -> Result<(), CC1101Error> {
828 assert_eq!(CommonConfig::frequency_to_config(315.0)?, 0x000C1D89);
829 assert_eq!(CommonConfig::frequency_to_config(433.0)?, 0x0010A762);
830 assert_eq!(CommonConfig::frequency_to_config(868.0)?, 0x00216276);
831 assert_eq!(CommonConfig::frequency_to_config(915.0)?, 0x0023313B);
832
833 assert_eq!(CommonConfig::frequency_to_config(299.999756)?, 0x000B89D8);
834 assert_eq!(CommonConfig::frequency_to_config(347.999939)?, 0x000D6276);
835 assert_eq!(CommonConfig::frequency_to_config(386.999939)?, 0x000EE276);
836 assert_eq!(CommonConfig::frequency_to_config(463.999786)?, 0x0011D89D);
837 assert_eq!(CommonConfig::frequency_to_config(778.999878)?, 0x001DF627);
838 assert_eq!(CommonConfig::frequency_to_config(928.000000)?, 0x0023B13B);
839
840 assert_eq!(CommonConfig::config_to_frequency(0x000B89D8), 299.999756);
841 assert_eq!(CommonConfig::config_to_frequency(0x000D6276), 347.999939);
842 assert_eq!(CommonConfig::config_to_frequency(0x000EE276), 386.999939);
843 assert_eq!(CommonConfig::config_to_frequency(0x0011D89D), 463.999786);
844 assert_eq!(CommonConfig::config_to_frequency(0x001DF627), 778.999878);
845 assert_eq!(CommonConfig::config_to_frequency(0x0023B13B), 928.000000);
846
847 assert_eq!(CommonConfig::config_to_frequency(0x000C1D89), 314.999664);
848 assert_eq!(CommonConfig::config_to_frequency(0x0010A762), 432.999817);
849 assert_eq!(CommonConfig::config_to_frequency(0x00216276), 867.999939);
850 assert_eq!(CommonConfig::config_to_frequency(0x0023313B), 915.000000);
851
852 assert!(CommonConfig::frequency_to_config(0.0).is_err());
853 assert!(CommonConfig::frequency_to_config(464.0).is_err());
854 assert!(CommonConfig::frequency_to_config(999.0).is_err());
855
856 Ok(())
857 }
858
859 #[test]
860 fn test_baud_rate() -> Result<(), CC1101Error> {
861 assert_eq!(
862 CommonConfig::baud_rate_to_config(Modulation::FSK2, 0.6)?,
863 (0x83, 0x04)
864 );
865 assert_eq!(
866 CommonConfig::baud_rate_to_config(Modulation::FSK2, 0.599742)?,
867 (0x83, 0x04)
868 );
869
870 assert_eq!(
871 CommonConfig::baud_rate_to_config(Modulation::FSK2, 26.0)?,
872 (0x06, 0x0A)
873 );
874 assert_eq!(
875 CommonConfig::baud_rate_to_config(Modulation::FSK2, 25.9857)?,
876 (0x06, 0x0A)
877 );
878
879 assert_eq!(
880 CommonConfig::baud_rate_to_config(Modulation::FSK2, 250.0)?,
881 (0x3B, 0x0D)
882 );
883 assert_eq!(
884 CommonConfig::baud_rate_to_config(Modulation::FSK2, 249.939)?,
885 (0x3B, 0x0D)
886 );
887
888 assert_eq!(
889 CommonConfig::baud_rate_to_config(Modulation::FSK2, 300.0)?,
890 (0x7A, 0x0D)
891 );
892 assert_eq!(
893 CommonConfig::baud_rate_to_config(Modulation::FSK2, 299.927)?,
894 (0x7A, 0x0D)
895 );
896
897 assert_eq!(
898 CommonConfig::baud_rate_to_config(Modulation::FSK2, 500.0)?,
899 (0x3B, 0x0E)
900 );
901 assert_eq!(
902 CommonConfig::baud_rate_to_config(Modulation::FSK2, 499.878)?,
903 (0x3B, 0x0E)
904 );
905
906 assert_eq!(
907 CommonConfig::baud_rate_to_config(Modulation::FSK2, 115.051)?,
908 (0x22, 0x0C)
909 );
910
911 assert_eq!(CommonConfig::config_to_baud_rate(0x83, 0x04), 0.599742);
912 assert_eq!(CommonConfig::config_to_baud_rate(0x06, 0x0A), 25.98572);
913 assert_eq!(CommonConfig::config_to_baud_rate(0x3B, 0x0D), 249.93896);
914 assert_eq!(CommonConfig::config_to_baud_rate(0x7A, 0x0D), 299.92676);
915 assert_eq!(CommonConfig::config_to_baud_rate(0x3B, 0x0E), 499.87793);
916 assert_eq!(CommonConfig::config_to_baud_rate(0x22, 0x0C), 115.05126);
917
918 assert!(CommonConfig::baud_rate_to_config(Modulation::FSK2, 0.0).is_err());
919 assert!(CommonConfig::baud_rate_to_config(Modulation::FSK2, 999.0).is_err());
920
921 Ok(())
922 }
923
924 #[test]
925 fn test_deviation() -> Result<(), CC1101Error> {
926 assert_eq!(CommonConfig::deviation_to_config(1.586914)?, (0x00, 0x00));
927 assert_eq!(CommonConfig::deviation_to_config(380.85938)?, (0x07, 0x07));
928 assert_eq!(CommonConfig::config_to_deviation(0x00, 0x00), 1.586914);
929 assert_eq!(CommonConfig::config_to_deviation(0x07, 0x07), 380.859375);
930 assert!(CommonConfig::deviation_to_config(0.0).is_err());
931 assert!(CommonConfig::deviation_to_config(400.0).is_err());
932
933 Ok(())
934 }
935
936 #[test]
937 fn test_sync_word() -> Result<(), CC1101Error> {
938 CommonConfig::sync_word_to_config(0x00000000)?;
939 CommonConfig::sync_word_to_config(0x0000FFFF)?;
940 CommonConfig::sync_word_to_config(0xFFFFFFFF)?;
941
942 assert!(CommonConfig::sync_word_to_config(0xFFFF0000).is_err());
943 assert!(CommonConfig::sync_word_to_config(0xAAAABBBB).is_err());
944 Ok(())
945 }
946
947 #[test]
948 fn test_bandwidth() -> Result<(), CC1101Error> {
949 assert_eq!(RXConfig::bandwidth_to_config(812)?, (0x00, 0x00));
950 assert_eq!(RXConfig::bandwidth_to_config(58)?, (0x03, 0x03));
951
952 assert_eq!(RXConfig::config_to_bandwidth(0x00, 0x00), 812);
953 assert_eq!(RXConfig::config_to_bandwidth(0x03, 0x03), 58);
954
955 assert!(RXConfig::bandwidth_to_config(0).is_err());
956 assert!(RXConfig::bandwidth_to_config(400).is_err());
957
958 Ok(())
959 }
960
961 #[test]
962 fn test_tx_power() -> Result<(), CC1101Error> {
963 assert!(TXConfig::config_to_tx_power(123.0, 0xFF).is_err());
964 assert!(TXConfig::config_to_tx_power(433.0, 0xFF).is_err());
965 assert!(TXConfig::tx_power_to_config(433.0, -1.0).is_err());
966
967 for frequency in [315.0, 433.0, 868.0, 915.0] {
968 let power_table = TXConfig::get_power_table(frequency)?;
969 for (hex, dbm) in power_table {
970 assert_eq!(TXConfig::config_to_tx_power(frequency, *hex)?, *dbm);
971 assert_eq!(TXConfig::tx_power_to_config(frequency, *dbm)?, *hex);
972 }
973 }
974
975 Ok(())
976 }
977}