use core::num::Wrapping;
use embedded_hal::spi;
use crate::{ll, Config, Error, Ready, Uninitialized, DW3000};
impl<SPI> DW3000<SPI, Uninitialized>
where
SPI: spi::SpiDevice<u8>,
{
pub fn new(spi: SPI) -> Self {
DW3000 {
ll: ll::DW3000::new(spi),
seq: Wrapping(0),
state: Uninitialized,
}
}
pub fn init(mut self) -> Result<DW3000<SPI, Uninitialized>, Error<SPI>> {
while self.ll.sys_status().read()?.rcinit() == 0 {}
self.ll.clk_ctrl().modify(|_, w| w.sys_clk(0))?;
self.ll.seq_ctrl().modify(|_, w| w.ainit2idle(1))?;
while self.ll.sys_status().read()?.cplock() == 0 {}
self.ll.otp_cfg().modify(|_, w| w.otp_man(1))?;
self.ll.otp_addr().modify(|_, w| w.otp_addr(0x1E))?;
self.ll.otp_cfg().modify(|_, w| w.otp_read(1))?;
let xtrim = self.ll.otp_rdata().read()?.value() & 0x7F;
if xtrim == 0 {
self.ll.xtal().modify(|_, w| w.value(0x2E))?;
}
self.ll.xtal().modify(|_, w| w.value(xtrim as u8))?;
Ok(DW3000 {
ll: self.ll,
seq: self.seq,
state: Uninitialized,
})
}
pub fn config(mut self, config: Config) -> Result<DW3000<SPI, Ready>, Error<SPI>> {
self.ll.sys_cfg().modify(|_, w| w.phr_mode(0))?;
self.ll.sys_cfg().modify(|_, w| w.phr_6m8(0))?;
self.ll.sys_cfg().modify(|_, w| w.cp_spc(config.sts_mode as u8))?;
self.ll.sys_cfg().modify(|_, w| w.pdoa_mode(0))?;
self.ll.sys_cfg().modify(|_, w| w.cp_sdc(0))?;
self.ll.otp_cfg().modify(|_, w| w.ops_sel(0x2))?;
self.ll.otp_cfg().modify(|_, w| w.ops_kick(0b1))?;
self.ll.dtune0().modify(|_, w| {
w.pac(config.preamble_length.get_recommended_pac_size())
.dt0b4(0b0)
})?;
self.ll
.sts_cfg()
.modify(|_, w| w.cps_len(config.sts_len as u8 - 1))?;
self.ll.tx_fctrl().modify(|_, w| w.fine_plen(0x0))?;
self.ll.dtune3().modify(|_, w| w.value(0xAF5F584C))?;
self.ll.chan_ctrl().modify(|_, w| {
w.rf_chan(config.channel as u8) .sfd_type(config.sfd_sequence as u8)
.tx_pcode(
config
.channel
.get_recommended_preamble_code(config.pulse_repetition_frequency),
)
.rx_pcode(
config
.channel
.get_recommended_preamble_code(config.pulse_repetition_frequency),
)
})?;
self.ll.tx_fctrl().modify(|_, w| w.txbr(0x1))?;
self.ll.tx_fctrl().modify(|_, w| w.txpsr(0x5))?;
self.ll
.rx_sfd_toc()
.modify(|_, w| w.value(config.sfd_timeout as u16))?;
self.ll
.rf_tx_ctrl_2()
.modify(|_, w| w.value(config.channel.get_recommended_rf_tx_ctrl_2()))?;
self.ll
.pll_cfg()
.modify(|_, w| w.value(config.channel.get_recommended_pll_conf()))?;
self.ll.ldo_rload().modify(|_, w| w.value(0x14))?;
self.ll.rf_tx_ctrl_1().modify(|_, w| w.value(0x0E))?;
self.ll.pll_cal().modify(|_, w| w.use_old(0x0))?;
self.ll.pll_cal().modify(|_, w| w.pll_cfg_ld(0x8))?;
self.ll.pll_cal().modify(|_, w| w.cal_en(0x0))?;
self.ll.seq_ctrl().modify(|_, w| w.ainit2idle(1))?;
self.ll.clk_ctrl().modify(|_, w| {
w.sys_clk(0b00)
.rx_clk(0b00)
.tx_clk(0b00)
.acc_clk_en(0b0)
.cia_clk_en(0b0)
.sar_clk_en(0b0)
.acc_mclk_en(0b0)
})?;
if config
.channel
.get_recommended_preamble_code(config.pulse_repetition_frequency)
>= 9
&& config
.channel
.get_recommended_preamble_code(config.pulse_repetition_frequency)
<= 24
{
self.ll.otp_cfg().modify(|_, w| w.otp_man(1))?;
self.ll.otp_addr().modify(|_, w| w.otp_addr(0x20))?;
self.ll.otp_cfg().modify(|_, w| w.otp_read(1))?;
let dgc_otp = self.ll.otp_rdata().read()?.value();
if dgc_otp == 0x10000240 {
self.ll.otp_cfg().modify(|_, w| w.dgc_kick(1))?;
self.ll.otp_cfg().modify(|_, w| w.dgc_sel(0))?;
} else {
self.ll
.dgc_lut_0()
.modify(|_, w| w.value(config.channel.get_recommended_dgc_lut_0()))?;
self.ll
.dgc_lut_1()
.modify(|_, w| w.value(config.channel.get_recommended_dgc_lut_1()))?;
self.ll
.dgc_lut_2()
.modify(|_, w| w.value(config.channel.get_recommended_dgc_lut_2()))?;
self.ll
.dgc_lut_3()
.modify(|_, w| w.value(config.channel.get_recommended_dgc_lut_3()))?;
self.ll
.dgc_lut_4()
.modify(|_, w| w.value(config.channel.get_recommended_dgc_lut_4()))?;
self.ll
.dgc_lut_5()
.modify(|_, w| w.value(config.channel.get_recommended_dgc_lut_5()))?;
self.ll
.dgc_lut_6()
.modify(|_, w| w.value(config.channel.get_recommended_dgc_lut_6()))?;
self.ll.dgc_cfg0().modify(|_, w| w.value(0x10000240))?;
self.ll.dgc_cfg1().modify(|_, w| w.value(0x1b6da489))?;
}
self.ll.dgc_cfg().modify(|_, w| w.thr_64(0x32))?;
} else {
self.ll.dgc_cfg().modify(|_, w| w.rx_tune_en(0))?;
}
let val = self.ll.ldo_ctrl().read()?.value();
self.ll.ldo_ctrl().modify(|_, w| w.value(0x105))?;
self.ll
.rx_cal()
.modify(|_, w| w.comp_dly(0x2).cal_mode(1))?;
self.ll.rx_cal().modify(|_, w| w.cal_en(1))?;
while self.ll.rx_cal_sts().read()?.value() == 0 {}
self.ll.rx_cal().modify(|_, w| w.cal_mode(0).cal_en(0))?;
self.ll.rx_cal_sts().modify(|_, w| w.value(1))?;
if self.ll.rx_cal_resi().read()?.value() == 0x1fffffff
|| self.ll.rx_cal_resq().read()?.value() == 0x1fffffff
{
return Err(Error::InvalidConfiguration);
}
self.ll.ldo_ctrl().modify(|_, w| w.value(val))?;
Ok(DW3000 {
ll: self.ll,
seq: self.seq,
state: Ready,
})
}
}