use crate::Error;
use embedded_hal::{blocking::spi, digital::v2::OutputPin};
use num_enum::TryFromPrimitive;
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TxConfig {
pub bitrate: BitRate,
pub ranging_enable: bool,
pub pulse_repetition_frequency: PulseRepetitionFrequency,
pub preamble_length: PreambleLength,
pub channel: UwbChannel,
pub sfd_sequence: SfdSequence,
pub append_crc: bool,
}
impl Default for TxConfig {
fn default() -> Self {
TxConfig {
bitrate: Default::default(),
ranging_enable: false,
pulse_repetition_frequency: Default::default(),
preamble_length: Default::default(),
channel: Default::default(),
sfd_sequence: Default::default(),
append_crc: true,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct RxConfig {
pub bitrate: BitRate,
pub frame_filtering: bool,
pub pulse_repetition_frequency: PulseRepetitionFrequency,
pub expected_preamble_length: PreambleLength,
pub channel: UwbChannel,
pub sfd_sequence: SfdSequence,
pub append_crc: bool,
}
impl Default for RxConfig {
fn default() -> Self {
Self {
bitrate: Default::default(),
frame_filtering: true,
pulse_repetition_frequency: Default::default(),
expected_preamble_length: Default::default(),
channel: Default::default(),
sfd_sequence: Default::default(),
append_crc: true,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TryFromPrimitive)]
#[repr(u8)]
pub enum BitRate {
Kbps110 = 0b00,
Kbps850 = 0b01,
Kbps6800 = 0b10,
}
impl Default for BitRate {
fn default() -> Self {
BitRate::Kbps6800
}
}
impl BitRate {
pub fn get_recommended_drx_tune0b(&self, sfd_sequence: SfdSequence) -> u16 {
match (self, sfd_sequence) {
(BitRate::Kbps110, SfdSequence::IEEE) => 0x000A,
(BitRate::Kbps110, _) => 0x0016,
(BitRate::Kbps850, SfdSequence::IEEE) => 0x0001,
(BitRate::Kbps850, _) => 0x0006,
(BitRate::Kbps6800, SfdSequence::IEEE) => 0x0001,
(BitRate::Kbps6800, _) => 0x0002,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TryFromPrimitive)]
#[repr(u8)]
pub enum PulseRepetitionFrequency {
Mhz16 = 0b01,
Mhz64 = 0b10,
}
impl Default for PulseRepetitionFrequency {
fn default() -> Self {
PulseRepetitionFrequency::Mhz16
}
}
impl PulseRepetitionFrequency {
pub fn get_recommended_drx_tune1a(&self) -> u16 {
match self {
PulseRepetitionFrequency::Mhz16 => 0x0087,
PulseRepetitionFrequency::Mhz64 => 0x008D,
}
}
pub fn get_recommended_drx_tune2<SPI, CS>(&self, pac_size: u8) -> Result<u32, Error<SPI, CS>>
where
SPI: spi::Transfer<u8> + spi::Write<u8>,
CS: OutputPin,
{
match (self, pac_size) {
(PulseRepetitionFrequency::Mhz16, 8) => Ok(0x311A002D),
(PulseRepetitionFrequency::Mhz64, 8) => Ok(0x313B006B),
(PulseRepetitionFrequency::Mhz16, 16) => Ok(0x331A0052),
(PulseRepetitionFrequency::Mhz64, 16) => Ok(0x333B00BE),
(PulseRepetitionFrequency::Mhz16, 32) => Ok(0x351A009A),
(PulseRepetitionFrequency::Mhz64, 32) => Ok(0x353B015E),
(PulseRepetitionFrequency::Mhz16, 64) => Ok(0x371A011D),
(PulseRepetitionFrequency::Mhz64, 64) => Ok(0x373B0296),
_ => Err(Error::InvalidConfiguration),
}
}
pub fn get_recommended_lde_cfg2(&self) -> u16 {
match self {
PulseRepetitionFrequency::Mhz16 => 0x1607,
PulseRepetitionFrequency::Mhz64 => 0x0607,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TryFromPrimitive)]
#[repr(u8)]
pub enum PreambleLength {
Symbols64 = 0b0100,
Symbols128 = 0b0101,
Symbols256 = 0b0110,
Symbols512 = 0b0111,
Symbols1024 = 0b1000,
Symbols1536 = 0b1001,
Symbols2048 = 0b1010,
Symbols4096 = 0b1100,
}
impl Default for PreambleLength {
fn default() -> Self {
PreambleLength::Symbols128
}
}
impl PreambleLength {
pub fn get_recommended_pac_size(&self) -> u8 {
match self {
PreambleLength::Symbols64 => 8,
PreambleLength::Symbols128 => 8,
PreambleLength::Symbols256 => 16,
PreambleLength::Symbols512 => 16,
PreambleLength::Symbols1024 => 32,
PreambleLength::Symbols1536 => 64,
PreambleLength::Symbols2048 => 64,
PreambleLength::Symbols4096 => 64,
}
}
pub fn get_recommended_drx_tune1b<SPI, CS>(
&self,
bitrate: BitRate,
) -> Result<u16, Error<SPI, CS>>
where
SPI: spi::Transfer<u8> + spi::Write<u8>,
CS: OutputPin,
{
match (self, bitrate) {
(PreambleLength::Symbols64, BitRate::Kbps6800) => Ok(0x0010),
(PreambleLength::Symbols128, BitRate::Kbps6800) => Ok(0x0020),
(PreambleLength::Symbols256, BitRate::Kbps6800) => Ok(0x0020),
(PreambleLength::Symbols512, BitRate::Kbps6800) => Ok(0x0020),
(PreambleLength::Symbols1024, BitRate::Kbps6800) => Ok(0x0020),
(PreambleLength::Symbols128, BitRate::Kbps850) => Ok(0x0020),
(PreambleLength::Symbols256, BitRate::Kbps850) => Ok(0x0020),
(PreambleLength::Symbols512, BitRate::Kbps850) => Ok(0x0020),
(PreambleLength::Symbols1024, BitRate::Kbps850) => Ok(0x0020),
(PreambleLength::Symbols1536, BitRate::Kbps110) => Ok(0x0064),
(PreambleLength::Symbols2048, BitRate::Kbps110) => Ok(0x0064),
(PreambleLength::Symbols4096, BitRate::Kbps110) => Ok(0x0064),
_ => Err(Error::InvalidConfiguration),
}
}
pub fn get_recommended_dxr_tune4h(&self) -> u16 {
match self {
PreambleLength::Symbols64 => 0x0010,
_ => 0x0028,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TryFromPrimitive)]
#[repr(u8)]
pub enum SfdSequence {
IEEE,
Decawave,
DecawaveAlt,
User,
}
impl Default for SfdSequence {
fn default() -> Self {
SfdSequence::IEEE
}
}
impl SfdSequence {
pub fn get_rxpacc_adjustment(&self, bit_rate: BitRate) -> i8 {
match self {
SfdSequence::IEEE => {
match bit_rate {
BitRate::Kbps110 => 64, BitRate::Kbps850 | BitRate::Kbps6800 => -5, }
}
SfdSequence::Decawave => {
match bit_rate {
BitRate::Kbps110 => 82, BitRate::Kbps850 => -10, BitRate::Kbps6800 => 0, }
}
SfdSequence::DecawaveAlt => {
match bit_rate {
BitRate::Kbps110 => 82, BitRate::Kbps850 => -18, BitRate::Kbps6800 => 0, }
}
SfdSequence::User => 0, }
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TryFromPrimitive)]
#[repr(u8)]
pub enum UwbChannel {
Channel1 = 1,
Channel2 = 2,
Channel3 = 3,
Channel4 = 4,
Channel5 = 5,
Channel7 = 7,
}
impl Default for UwbChannel {
fn default() -> Self {
UwbChannel::Channel5
}
}
impl UwbChannel {
pub fn get_recommended_preamble_code(&self, prf_value: PulseRepetitionFrequency) -> u8 {
match (self, prf_value) {
(UwbChannel::Channel1, PulseRepetitionFrequency::Mhz16) => 1,
(UwbChannel::Channel2, PulseRepetitionFrequency::Mhz16) => 3,
(UwbChannel::Channel3, PulseRepetitionFrequency::Mhz16) => 5,
(UwbChannel::Channel4, PulseRepetitionFrequency::Mhz16) => 7,
(UwbChannel::Channel5, PulseRepetitionFrequency::Mhz16) => 4,
(UwbChannel::Channel7, PulseRepetitionFrequency::Mhz16) => 8,
(UwbChannel::Channel1, PulseRepetitionFrequency::Mhz64) => 9,
(UwbChannel::Channel2, PulseRepetitionFrequency::Mhz64) => 10,
(UwbChannel::Channel3, PulseRepetitionFrequency::Mhz64) => 11,
(UwbChannel::Channel4, PulseRepetitionFrequency::Mhz64) => 17,
(UwbChannel::Channel5, PulseRepetitionFrequency::Mhz64) => 12,
(UwbChannel::Channel7, PulseRepetitionFrequency::Mhz64) => 18,
}
}
pub fn get_recommended_lde_repc_value(
&self,
pulse_repetition_frequency: PulseRepetitionFrequency,
bitrate: BitRate,
) -> u16 {
const VALUES: [u16; 24] = [
0x5998, 0x5998, 0x51EA, 0x428E, 0x451E, 0x2E14, 0x8000, 0x51EA, 0x28F4, 0x3332, 0x3AE0,
0x3D70, 0x3AE0, 0x35C2, 0x2B84, 0x35C2, 0x3332, 0x35C2, 0x35C2, 0x47AE, 0x3AE0, 0x3850,
0x30A2, 0x3850,
];
let pcode = self.get_recommended_preamble_code(pulse_repetition_frequency);
let value = VALUES[pcode as usize];
if bitrate != BitRate::Kbps110 {
value
} else {
value / 8
}
}
pub fn get_recommended_rf_txctrl(&self) -> u32 {
match self {
UwbChannel::Channel1 => 0x00005C40,
UwbChannel::Channel2 => 0x00045CA0,
UwbChannel::Channel3 => 0x00086CC0,
UwbChannel::Channel4 => 0x00045C80,
UwbChannel::Channel5 => 0x001E3FE0,
UwbChannel::Channel7 => 0x001E7DE0,
}
}
pub fn get_recommended_tc_pgdelay(&self) -> u8 {
match self {
UwbChannel::Channel1 => 0xC9,
UwbChannel::Channel2 => 0xC2,
UwbChannel::Channel3 => 0xC5,
UwbChannel::Channel4 => 0x95,
UwbChannel::Channel5 => 0xC0,
UwbChannel::Channel7 => 0x93,
}
}
pub fn get_recommended_fs_pllcfg(&self) -> u32 {
match self {
UwbChannel::Channel1 => 0x09000407,
UwbChannel::Channel2 | UwbChannel::Channel4 => 0x08400508,
UwbChannel::Channel3 => 0x08401009,
UwbChannel::Channel5 | UwbChannel::Channel7 => 0x0800041D,
}
}
pub fn get_recommended_fs_plltune(&self) -> u8 {
match self {
UwbChannel::Channel1 => 0x1E,
UwbChannel::Channel2 | UwbChannel::Channel4 => 0x26,
UwbChannel::Channel3 => 0x56,
UwbChannel::Channel5 | UwbChannel::Channel7 => 0xBE,
}
}
pub fn get_recommended_rf_rxctrlh(&self) -> u8 {
match self {
UwbChannel::Channel1
| UwbChannel::Channel2
| UwbChannel::Channel3
| UwbChannel::Channel5 => 0xD8,
UwbChannel::Channel4 | UwbChannel::Channel7 => 0xBC,
}
}
}