Added clk config part, increased ADC clk to 32MHz.

This commit is contained in:
2025-09-09 13:04:15 +02:00
parent 83731f77e0
commit b53e58ec31
3 changed files with 216 additions and 12 deletions

View File

@@ -7,6 +7,30 @@ use heapless::LinearMap;
use crate::ad5940_registers::*; use crate::ad5940_registers::*;
#[allow(dead_code)]
#[derive(Default)]
pub struct ClkConfig {
adcclkdiv: Option<ADCCLKDIV>,
sysclkdiv: Option<SYSCLKDIV>,
clk32mhzen: Option<CLK32MHZEN>,
}
impl ClkConfig {
pub fn adcclkdiv(mut self, adcclkdiv: ADCCLKDIV) -> Self {
self.adcclkdiv = Some(adcclkdiv);
self
}
pub fn sysclkdiv(mut self, sysclkdiv: SYSCLKDIV) -> Self {
self.sysclkdiv = Some(sysclkdiv);
self
}
pub fn clk32mhzen(mut self, clk32mhzen: CLK32MHZEN) -> Self {
self.clk32mhzen = Some(clk32mhzen);
self
}
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Default)] #[derive(Default)]
pub struct SwitchConfig { pub struct SwitchConfig {
@@ -57,6 +81,9 @@ pub struct DspConfig {
dftin: Option<DFTINSEL>, dftin: Option<DFTINSEL>,
dftnum: Option<DFTNUM>, dftnum: Option<DFTNUM>,
hanning: Option<bool>, hanning: Option<bool>,
pub fsys: Option<u32>,
pub fadc: Option<u32>,
ratio_sys2adc_clk: Option<f32>,
} }
impl DspConfig { impl DspConfig {
@@ -109,6 +136,13 @@ impl DspConfig {
self.hanning = Some(hanning); self.hanning = Some(hanning);
self self
} }
pub fn set_clks(mut self, fsys: u32, fadc: u32) -> Self {
self.fsys = Some(fsys);
self.fadc = Some(fadc);
self.ratio_sys2adc_clk = Some(fsys as f32 / fadc as f32);
self
}
} }
#[allow(dead_code)] #[allow(dead_code)]
@@ -482,9 +516,17 @@ impl AD5940 {
// When ACLK = 16MHz, ADC samplerate is 800kHz // When ACLK = 16MHz, ADC samplerate is 800kHz
// When ACLK = 32MHz, ADC samplerate is 1.6MHz // When ACLK = 32MHz, ADC samplerate is 1.6MHz
// --> Always per ADC sample 20 cycles // If ACLK == SYSCLK --> Always per ADC sample 20 cycles
// If ACLK != SYSCLK --> Always per ADC sample 20*(SYSCLK/ACLK) cycles
// When SYSCLK is lower, the wait cycles to wait are less becasuse the ADC samples at higher rate
wait_time *= 20; wait_time *= 20;
if let Some(ratio) = config.ratio_sys2adc_clk {
wait_time = (wait_time as f32 * ratio) as u32;
} else {
return None; // Ratio must be set
}
Some(wait_time) Some(wait_time)
} }
@@ -517,6 +559,35 @@ impl AD5940 {
Ok(()) Ok(())
} }
pub async fn apply_clk_config(&mut self, config: &ClkConfig) -> Result<(), Error> {
// PMBW
let mut current = self.read_reg(Register::PMBW).await?;
current |= 0b1;
self.write_reg(Register::PMBW, current).await?;
// CLKCON0
let mut current = self.read_reg(Register::CLKCON0).await?;
if let Some(adcclkdiv) = config.adcclkdiv {
current = ADCCLKDIV::apply(current, adcclkdiv as u32);
}
if let Some(sysclkdiv) = config.sysclkdiv {
current = SYSCLKDIV::apply(current, sysclkdiv as u32);
}
self.write_reg(Register::CLKCON0, current).await?;
// HSOSCCON
let mut current = self.read_reg(Register::HSOSCCON).await?;
if let Some(clk32mhzen) = config.clk32mhzen {
current = CLK32MHZEN::apply(current, clk32mhzen as u32);
}
self.write_reg(Register::HSOSCCON, current).await?;
Ok(())
}
pub async fn apply_dsp_config(&mut self, config: &DspConfig) -> Result<(), Error> { pub async fn apply_dsp_config(&mut self, config: &DspConfig) -> Result<(), Error> {
// ADCCON // ADCCON
let mut current = self.read_reg(Register::ADCCON).await?; let mut current = self.read_reg(Register::ADCCON).await?;
@@ -782,5 +853,7 @@ pub enum Register {
HSRTIACON = 0x0000_20F0, // High Speed RTIA Configuration Register HSRTIACON = 0x0000_20F0, // High Speed RTIA Configuration Register
BUFSENCON = 0x0000_2180, // HIGH POWER AND LOW POWER BUFFER CONTROL REGISTER BUFSENCON = 0x0000_2180, // HIGH POWER AND LOW POWER BUFFER CONTROL REGISTER
FIFOCNTSTA = 0x0000_2200, // Command and data FIFO internal data count register FIFOCNTSTA = 0x0000_2200, // Command and data FIFO internal data count register
ADCFILTERCON = 0x0000_2044 // ADC Output Filters Configuration Register ADCFILTERCON = 0x0000_2044, // ADC Output Filters Configuration Register
CLKCON0 = 0x0000_0408, // Clock Divider Configuration Register
HSOSCCON = 0x0000_20BC, // High Power Oscillator Configuration Register
} }

View File

@@ -420,6 +420,128 @@ impl RegisterField for DATAFIFOEN {
const MASK: u32 = 0b1; const MASK: u32 = 0b1;
} }
#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum ADCCLKDIV {
DIV1 = 0b01,
DIV2 = 0b10,
}
impl RegisterField for ADCCLKDIV {
fn reset() -> Self {
Self::DIV1
}
const BIT_OFFSET: u32 = 6;
const MASK: u32 = 0b1111;
}
#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum SYSCLKDIV {
DIV1 = 1,
DIV2,
DIV3,
DIV4,
DIV5,
DIV6,
DIV7,
DIV8,
DIV9,
DIV10,
DIV11,
DIV12,
DIV13,
DIV14,
DIV15,
DIV16,
DIV17,
DIV18,
DIV19,
DIV20,
DIV21,
DIV22,
DIV23,
DIV24,
DIV25,
DIV26,
DIV27,
DIV28,
DIV29,
DIV30,
DIV31,
}
impl TryFrom<u8> for SYSCLKDIV {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
1 => Ok(SYSCLKDIV::DIV1),
2 => Ok(SYSCLKDIV::DIV2),
3 => Ok(SYSCLKDIV::DIV3),
4 => Ok(SYSCLKDIV::DIV4),
5 => Ok(SYSCLKDIV::DIV5),
6 => Ok(SYSCLKDIV::DIV6),
7 => Ok(SYSCLKDIV::DIV7),
8 => Ok(SYSCLKDIV::DIV8),
9 => Ok(SYSCLKDIV::DIV9),
10 => Ok(SYSCLKDIV::DIV10),
11 => Ok(SYSCLKDIV::DIV11),
12 => Ok(SYSCLKDIV::DIV12),
13 => Ok(SYSCLKDIV::DIV13),
14 => Ok(SYSCLKDIV::DIV14),
15 => Ok(SYSCLKDIV::DIV15),
16 => Ok(SYSCLKDIV::DIV16),
17 => Ok(SYSCLKDIV::DIV17),
18 => Ok(SYSCLKDIV::DIV18),
19 => Ok(SYSCLKDIV::DIV19),
20 => Ok(SYSCLKDIV::DIV20),
21 => Ok(SYSCLKDIV::DIV21),
22 => Ok(SYSCLKDIV::DIV22),
23 => Ok(SYSCLKDIV::DIV23),
24 => Ok(SYSCLKDIV::DIV24),
25 => Ok(SYSCLKDIV::DIV25),
26 => Ok(SYSCLKDIV::DIV26),
27 => Ok(SYSCLKDIV::DIV27),
28 => Ok(SYSCLKDIV::DIV28),
29 => Ok(SYSCLKDIV::DIV29),
30 => Ok(SYSCLKDIV::DIV30),
31 => Ok(SYSCLKDIV::DIV31),
_ => Err("Invalid SYSCLKDIV value"),
}
}
}
impl SYSCLKDIV {
pub fn div(value: u8) -> Self {
SYSCLKDIV::try_from(value).unwrap_or(SYSCLKDIV::DIV1)
}
}
impl RegisterField for SYSCLKDIV {
fn reset() -> Self {
SYSCLKDIV::DIV1
}
const BIT_OFFSET: u32 = 0;
const MASK: u32 = 0b1_1111;
}
#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum CLK32MHZEN {
MHz32 = 0b0,
Mhz16 = 0b1,
}
impl RegisterField for CLK32MHZEN {
fn reset() -> Self {
CLK32MHZEN::Mhz16
}
const BIT_OFFSET: u32 = 2;
const MASK: u32 = 0b1;
}
bitflags! { bitflags! {
// Configuration Register // Configuration Register
// Address 0x00002000, Reset: 0x00080000, Name: AFECON // Address 0x00002000, Reset: 0x00080000, Name: AFECON

View File

@@ -42,18 +42,27 @@ impl ImpedanceSetup {
) )
.await; .await;
// Set CLK configuration
let clk_config = ClkConfig::default()
.adcclkdiv(ADCCLKDIV::DIV1) // ADCCLK = 32MHz
.sysclkdiv(SYSCLKDIV::DIV2) // SYSCLK = 16MHz
.clk32mhzen(CLK32MHZEN::MHz32);
self.ad5940.apply_clk_config(&clk_config).await.unwrap();
// Set DSP configuration // Set DSP configuration
let dsp_config = DspConfig::default() let dsp_config = DspConfig::default()
.adc_mux_n(MUXSELN::HsTiaNeg) .adc_mux_n(MUXSELN::HsTiaNeg)
.adc_mux_p(MUXSELP::HsTiaPos) .adc_mux_p(MUXSELP::HsTiaPos)
.ctiacon(CTIACON::C32) .ctiacon(CTIACON::C32)
.rtiacon(RTIACON::R1k) .rtiacon(RTIACON::R1k)
.sinc3osr(SINC3OSR::R5) .sinc3osr(SINC3OSR::R4)
.sinc2osr(SINC2OSR::R178) .sinc2osr(SINC2OSR::R178)
.adcsamplerate(ADCSAMPLERATE::R800kHz) .adcsamplerate(ADCSAMPLERATE::R1_6MHz)
.dftin_sel(DFTINSEL::GainOffset) .dftin_sel(DFTINSEL::GainOffset)
.dftnum(DFTNUM::Num2048) .dftnum(DFTNUM::Num4096)
.hanning(true); .hanning(true)
.set_clks(16_000_000, 32_000_000); // Check clk_config: In this case SYSCLK = 16MHz and ADCCLK = 32MHz
self.ad5940.apply_dsp_config(&dsp_config).await.unwrap(); self.ad5940.apply_dsp_config(&dsp_config).await.unwrap();
self.dsp_config = Some(dsp_config); self.dsp_config = Some(dsp_config);
@@ -83,7 +92,7 @@ impl ImpedanceSetup {
let mut wait_time = 0; let mut wait_time = 0;
if let Some(dsp_config) = &self.dsp_config { if let Some(dsp_config) = &self.dsp_config {
wait_time = self.ad5940.sequencer_calculate_wait_time(dsp_config).await.unwrap(); wait_time = self.ad5940.sequencer_calculate_wait_time(dsp_config).await.unwrap();
info!("Sinus periods per DFT: {}", wait_time as f32 / 16e6 * frequency as f32); info!("Sinus periods per DFT: {}", wait_time as f32 / dsp_config.fsys.unwrap() as f32 * frequency as f32);
} else { } else {
error!("DSP configuration not set, cannot calculate wait time"); error!("DSP configuration not set, cannot calculate wait time");
} }
@@ -104,10 +113,10 @@ impl ImpedanceSetup {
.dmuxcon(DMUXCON::DR0Closed); .dmuxcon(DMUXCON::DR0Closed);
self.ad5940.apply_switch_config(switch_config).await.unwrap(); self.ad5940.apply_switch_config(switch_config).await.unwrap();
self.ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await; self.ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await;
self.ad5940.sequencer_wait(16*10).await; // 10 us self.ad5940.sequencer_wait(16*10).await; // 10 us based on SYSCLK = 16MHz
self.ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; self.ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await;
self.ad5940.sequencer_wait(wait_time).await; // Determined above self.ad5940.sequencer_wait(wait_time).await; // Determined above
self.ad5940.sequencer_wait(16*20).await; // 10 us self.ad5940.sequencer_wait(16*20).await; // 20 us based on SYSCLK = 16MHz
self.ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await; self.ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
// Rz // Rz
@@ -119,15 +128,15 @@ impl ImpedanceSetup {
.dmuxcon(DMUXCON::D5Closed); .dmuxcon(DMUXCON::D5Closed);
self.ad5940.apply_switch_config(switch_config).await.unwrap(); self.ad5940.apply_switch_config(switch_config).await.unwrap();
self.ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await; self.ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await;
self.ad5940.sequencer_wait(16*10).await; // 10 us self.ad5940.sequencer_wait(16*10).await; // 10 us based on SYSCLK = 16MHz
self.ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; self.ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await;
self.ad5940.sequencer_wait(wait_time).await; // Determined above self.ad5940.sequencer_wait(wait_time).await; // Determined above
self.ad5940.sequencer_wait(16*20).await; // 10 us self.ad5940.sequencer_wait(16*20).await; // 20 us based on SYSCLK = 16MHz
self.ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await; self.ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
// Toggle leds // Toggle leds
self.ad5940.write_reg(Register::SYNCEXTDEVICE, 0b010).await.unwrap(); self.ad5940.write_reg(Register::SYNCEXTDEVICE, 0b010).await.unwrap();
self.ad5940.sequencer_wait(16 * 1_000).await; // 0.025 second self.ad5940.sequencer_wait(16 * 1_000).await; // 1ms based on SYSCLK = 16MHz
self.ad5940.write_reg(Register::SYNCEXTDEVICE, 0b111).await.unwrap(); self.ad5940.write_reg(Register::SYNCEXTDEVICE, 0b111).await.unwrap();
self.ad5940.sequencer_enable(false).await; self.ad5940.sequencer_enable(false).await;