use embedded_hal::spi::SpiDevice;
use crate::{
ActuatorStatus, CntCfg, CntCount, CntSetup, DeviceStatus, ErrorStatus, FullDeviceStatus,
PinStatus, WarningStatus,
dd::{Device, DeviceError, DeviceInterface},
};
#[derive(Debug)]
pub struct IcMd<Spi> {
pub device: Device<DeviceInterface<Spi>>,
counter_config: CntCfg,
device_status: DeviceStatus,
actuator_status: ActuatorStatus,
}
impl<Spi: SpiDevice> IcMd<Spi> {
pub fn new(spi: Spi) -> Self {
Self {
device: Device::new(DeviceInterface::new(spi)),
counter_config: CntCfg::Cnt1Bit48(CntSetup::default()),
actuator_status: ActuatorStatus::default(),
device_status: DeviceStatus::default(),
}
}
pub fn init(&mut self) -> Result<(), DeviceError<Spi::Error>> {
self.device
.counter_configuration()
.write(|reg| reg.set_value(self.counter_config.into()))?;
Ok(())
}
pub fn configure_actuator_pins(
&mut self,
act0: &PinStatus,
act1: &PinStatus,
) -> Result<(), DeviceError<Spi::Error>> {
self.device.instruction_byte().write(|reg| {
reg.set_act_0(act0.into());
reg.set_act_1(act1.into());
})?;
self.actuator_status.act0 = *act0;
self.actuator_status.act1 = *act1;
Ok(())
}
pub fn get_device_status(&self) -> DeviceStatus {
self.device_status
}
pub fn get_full_device_status(&mut self) -> Result<FullDeviceStatus, DeviceError<Spi::Error>> {
let status0 = self.device.status_0().read()?;
let status1 = self.device.status_1().read()?;
let status2 = self.device.status_2().read()?;
Ok(FullDeviceStatus {
cnt0_overflow: status0.ovf_0().into(),
cnt0_aberr: status0.ab_err_0().into(),
cnt0_zero: status0.zero_0().into(),
cnt1_overflow: status1.ovf_1().into(),
cnt1_aberr: status1.ab_err_1().into(),
cnt1_zero: status1.zero_1().into(),
cnt2_overflow: status2.ovf_2().into(),
cnt2_aberr: status2.ab_err_2().into(),
cnt2_zero: status2.zero_2().into(),
power_status: status0.p_dwn().into(),
ref_reg_status: status0.r_val().into(),
upd_reg_status: status0.upd_val().into(),
ref_cnt_status: status0.ovf_ref().into(),
ext_err_status: status1.ext_err().into(),
ext_warn_status: status1.ext_warn().into(),
comm_status: status1.com_col().into(),
tp_status: status0.tp_val().into(),
tpi_status: status1.tps().into(),
ssi_enabled: status2.en_ssi().into(),
})
}
pub fn read_counter(&mut self) -> Result<CntCount, DeviceError<Spi::Error>> {
match self.counter_config {
CntCfg::Cnt1Bit24(_) => {
let res = self.device.read_cnt_cfg_0().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt1Bit24(res.cnt_0()))
}
CntCfg::Cnt2Bit24(_, _) => {
let res = self.device.read_cnt_cfg_1().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt2Bit24(res.cnt_0(), res.cnt_1()))
}
CntCfg::Cnt1Bit48(_) => {
let res = self.device.read_cnt_cfg_2().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt1Bit48(res.cnt_0()))
}
CntCfg::Cnt1Bit16(_) => {
let res = self.device.read_cnt_cfg_3().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt1Bit16(res.cnt_0()))
}
CntCfg::Cnt1Bit32(_) => {
let res = self.device.read_cnt_cfg_4().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt1Bit32(res.cnt_0()))
}
CntCfg::Cnt2Bit32Bit16(_, _) => {
let res = self.device.read_cnt_cfg_5().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt2Bit32Bit16(res.cnt_0(), res.cnt_1()))
}
CntCfg::Cnt2Bit16(_, _) => {
let res = self.device.read_cnt_cfg_6().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt2Bit16(res.cnt_0(), res.cnt_1()))
}
CntCfg::Cnt3Bit16(_, _, _) => {
let res = self.device.read_cnt_cfg_7().read()?;
self.set_device_status(res.nwarn(), res.nerr());
Ok(CntCount::Cnt3Bit16(res.cnt_0(), res.cnt_1(), res.cnt_2()))
}
}
}
pub fn reset_counters(
&mut self,
cnt0: bool,
cnt1: bool,
cnt2: bool,
) -> Result<(), DeviceError<Spi::Error>> {
let act0 = &self.actuator_status.act0;
let act1 = &self.actuator_status.act1;
self.device.instruction_byte().write(|reg| {
reg.set_ab_res_0(cnt0);
reg.set_ab_res_1(cnt1);
reg.set_ab_res_2(cnt2);
reg.set_act_0(act0.into());
reg.set_act_1(act1.into());
})?;
Ok(())
}
pub fn reset_all_counters(&mut self) -> Result<(), DeviceError<Spi::Error>> {
self.reset_counters(true, true, true)?;
Ok(())
}
pub fn touch_probe_instruction(&mut self) -> Result<(), DeviceError<Spi::Error>> {
let act0 = &self.actuator_status.act0;
let act1 = &self.actuator_status.act1;
self.device.instruction_byte().write(|reg| {
reg.set_tp(true);
reg.set_act_0(act0.into());
reg.set_act_1(act1.into());
})?;
Ok(())
}
pub fn set_counter_config(&mut self, config: CntCfg) {
self.counter_config = config;
}
fn set_device_status(&mut self, nwarn: bool, nerr: bool) {
self.device_status.warning = match nwarn {
true => WarningStatus::Ok,
false => WarningStatus::Warning,
};
self.device_status.error = match nerr {
true => ErrorStatus::Ok,
false => ErrorStatus::Error,
};
}
}