From 8dbf62167971a56b71d777f824be76afe689687b Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 31 Aug 2020 17:43:15 +0800 Subject: [PATCH] scpi: implement tst --- src/attenuator.rs | 39 +++++++++++++++++++++++++++++++++++++ src/config_register.rs | 14 +++++++++++++- src/dds.rs | 44 ++++++++++++++++++++++-------------------- src/lib.rs | 16 ++++++++++++++- src/scpi.rs | 12 ++++++++++++ 5 files changed, 102 insertions(+), 23 deletions(-) diff --git a/src/attenuator.rs b/src/attenuator.rs index 8532501..d4b5294 100644 --- a/src/attenuator.rs +++ b/src/attenuator.rs @@ -78,6 +78,45 @@ where Err(e) => Err(e), } } + + /* + * Test method for Attenuators. + * Return the number of test failed. + */ + pub fn test(&mut self) -> Result> { + // Test attenuators by getting back the attenuation + let mut error_count = 0; + // Convert cached SPI data into attenuation floats + let att_floats :[f32; 4] = [ + ((self.data[3] ^ 0xFC) as f32) / 8.0, + ((self.data[2] ^ 0xFC) as f32) / 8.0, + ((self.data[1] ^ 0xFC) as f32) / 8.0, + ((self.data[0] ^ 0xFC) as f32) / 8.0, + ]; + // Set the attenuation to an arbitrary value, then read the attenuation + self.set_attenuation([ + 3.5, 9.5, 20.0, 28.5 + ])?; + match self.get_attenuation() { + Ok(arr) => { + if arr[0] != 3.5 { + error_count += 1; + } + if arr[1] != 9.5 { + error_count += 1; + } + if arr[2] != 20.0 { + error_count += 1; + } + if arr[3] != 28.5 { + error_count += 1; + } + }, + Err(_) => return Err(Error::AttenuatorError), + }; + self.set_attenuation(att_floats)?; + Ok(error_count) + } } impl Transfer for Attenuator diff --git a/src/config_register.rs b/src/config_register.rs index a3ce61d..3557217 100644 --- a/src/config_register.rs +++ b/src/config_register.rs @@ -97,7 +97,19 @@ where pub fn get_all_status(&mut self) -> Result> { return self.set_all_configurations(); } - + + /* + * Test method for Configuration Register. + * Return the number of test failed. + */ + pub fn test(&mut self) -> Result> { + // Test configuration register by getting PROTO_KEY. + match self.get_status(StatusMask::PROTO_KEY) { + Ok(8) => Ok(0), + Ok(_) => Ok(1), + Err(_) => Err(Error::ConfigRegisterError), + } + } } impl Transfer for ConfigRegister diff --git a/src/dds.rs b/src/dds.rs index f003a3c..0f181fa 100644 --- a/src/dds.rs +++ b/src/dds.rs @@ -147,26 +147,6 @@ where // panic!("Invalid divider value for PLL!"); return Err(Error::DDSCLKError); } - // // Select a VCO - // let vco = if divider == 1 { - // 6 // Bypass PLL if no frequency division needed - // } else if f_sys_clk > 1_150_000_000 { - // panic!("Invalid divider value for PLL!") - // } else if f_sys_clk > 820_000_000 { - // 5 - // } else if f_sys_clk > 700_000_000 { - // 4 - // } else if f_sys_clk > 600_000_000 { - // 3 - // } else if f_sys_clk > 500_000_000 { - // 2 - // } else if f_sys_clk > 420_000_000 { - // 1 - // } else if f_sys_clk > 370_000_000 { - // 0 - // } else { - // 7 // Bypass PLL if f_sys_clk is too low - // }; let vco = self.get_VCO_no(f_sys_clk, divider as u8)?; self.set_configurations(&mut [ @@ -366,7 +346,29 @@ where ((ftw >> 8 ) & 0xFF) as u8, ((ftw >> 0 ) & 0xFF) as u8, ]) - } + } + + + /* + * Test method for DDS. + * Return the number of test failed. + */ + pub fn test(&mut self) -> Result> { + // Test configuration register by getting SDIO_IN_ONLY and LSB_FIRST. + let mut error_count = 0; + let mut config_checks = [ + (DDSCFRMask::SDIO_IN_ONLY, 0), + (DDSCFRMask::LSB_FIRST, 0) + ]; + self.get_configurations(&mut config_checks)?; + if config_checks[0].1 == 0 { + error_count += 1; + } + if config_checks[1].1 == 1 { + error_count += 1; + } + Ok(error_count) + } } diff --git a/src/lib.rs b/src/lib.rs index a6a4c69..e168ac6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ use crate::cpld::DoOnGetRefMutData; pub mod config_register; use crate::config_register::ConfigRegister; use crate::config_register::CFGMask; +use crate::config_register::StatusMask; pub mod attenuator; use crate::attenuator::Attenuator; @@ -117,10 +118,23 @@ where // Clock tree reset. CPLD divides clock frequency by 4 by default. for chip_no in 0..4 { - self.dds[chip_no].set_ref_clk_frequency(25_000_000); + self.dds[chip_no].set_ref_clk_frequency(25_000_000)?; } Ok(()) } + + /* + * Test method fo Urukul. + * Return the number of test failed. + */ + pub fn test(&mut self) -> Result> { + let mut count = self.config_register.test()?; + count += self.attenuator.test()?; + for chip_no in 0..4 { + count += self.dds[chip_no].test()?; + } + Ok(count) + } } // /* diff --git a/src/scpi.rs b/src/scpi.rs index aed4305..822cd60 100644 --- a/src/scpi.rs +++ b/src/scpi.rs @@ -68,6 +68,18 @@ where )) } } + + fn tst(&mut self) -> Result<()> { + match self.test() { + Ok(0) => Ok(()), + Ok(_) => Err(Error::new( + ErrorCode::SelfTestFailed + )), + Err(_) => Err(Error::new( + ErrorCode::SelfTestFailed + )), + } + } } pub const TREE: &Node = scpi_tree![