mirror of
https://github.com/hubaldv/bioz-firmware-rs.git
synced 2025-12-06 05:01:18 +00:00
Added clk config part, increased ADC clk to 32MHz.
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user