diff --git a/src/dds.rs b/src/dds.rs index 2114a4c..550b039 100644 --- a/src/dds.rs +++ b/src/dds.rs @@ -253,7 +253,12 @@ where } // Finally, try enabling PLL else { - self.enable_pll(f_sys_clk) + self.enable_pll(f_sys_clk)?; + if self.f_sys_clk == self.get_sys_clk_frequency()? { + Ok(()) + } else { + Err(Error::WaitRetry) + } } } @@ -844,6 +849,32 @@ where pub fn get_f_sys_clk(&mut self) -> f64 { self.f_sys_clk } + + // Acquire real f_sys_clk + pub fn get_sys_clk_frequency(&mut self) -> Result> { + // Calculate the new system clock frequency, examine the clock tree + let mut configuration_queries = [ + // Acquire PLL status + (DDSCFRMask::PLL_ENABLE, 0), + // Acquire N-divider, to adjust VCO if necessary + (DDSCFRMask::N, 0), + // Acquire REF_CLK divider bypass + (DDSCFRMask::REFCLK_IN_DIV_BYPASS, 0) + ]; + + self.get_configurations(&mut configuration_queries)?; + if configuration_queries[0].1 == 1 { + // Recalculate sys_clk + let divider :f64 = configuration_queries[1].1.into(); + Ok(self.f_ref_clk * divider) + } + else if configuration_queries[2].1 == 0 { + Ok(self.f_ref_clk / 2.0) + } + else { + Ok(self.f_ref_clk) + } + } } // Strong check for bytes passed to a register diff --git a/src/urukul.rs b/src/urukul.rs index e97157f..101d6b1 100644 --- a/src/urukul.rs +++ b/src/urukul.rs @@ -30,6 +30,16 @@ pub enum Error { MqttCommandError, VectorOutOfSpace, StringOutOfSpace, + WaitRetry, // Prompt driver to just wait and retry +} + +impl Error { + pub fn is_wait_retry(&self) -> bool { + match self { + Error::WaitRetry => true, + _ => false, + } + } } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -330,16 +340,39 @@ where } pub fn set_channel_sys_clk(&mut self, channel: u8, f_sys_clk: f64) -> Result<(), Error> { - self.dds[usize::from(channel)].set_sys_clk_frequency(f_sys_clk).map(|_| ()) + loop { + if let Err(e) = self.dds[usize::from(channel)].set_sys_clk_frequency(f_sys_clk).map(|_| ()) { + if e.is_wait_retry() { + cortex_m::asm::delay(400_000); + } else { + return Err(e); + } + } else { + break; + } + } + Ok(()) } pub fn get_channel_sys_clk(&mut self, channel: u8) -> Result> { Ok(self.dds[usize::from(channel)].get_f_sys_clk()) } + pub fn get_channel_calculated_sys_clk(&mut self, channel: u8) -> Result> { + self.dds[usize::from(channel)].get_sys_clk_frequency() + } + + pub fn borrow_dds(&mut self, channel: u8) -> &mut DDS { + &mut self.dds[usize::from(channel)] + } + + pub fn borrow_config_register(&mut self) -> &mut ConfigRegister { + &mut self.config_register + } + // Multi-dds channel functions // Do not allow reading of DDS registers - // Make sure only 1 SPI transaction is compelted per function call + // Make sure only 1 SPI transaction is completed per function call // Setup NU_MASK in configuration register // This selects the DDS channels that will be covered by multi_channel DDS (spi3)