From 03a04bf789ceaf211bcc4d72f9e0e16249b9666e Mon Sep 17 00:00:00 2001 From: Hubald Verzijl Date: Thu, 14 Aug 2025 13:23:23 +0200 Subject: [PATCH] Added lineairmap to lib for sequencer. --- Cargo.lock | 1 + Cargo.toml | 2 + src/ad5940.rs | 84 ++++++++++++++++++++++++++++++++--------- src/ad5940_registers.rs | 8 ++++ src/main.rs | 19 ++++++---- 5 files changed, 88 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a251f9d..a3ef8ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,6 +74,7 @@ dependencies = [ "embassy-time", "embassy-usb", "embedded-hal 1.0.0", + "heapless 0.8.0", "libm", "panic-probe", "postcard-rpc", diff --git a/Cargo.toml b/Cargo.toml index 3961e1d..21418c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,8 @@ bioz-icd-rs = {path = "../bioz-icd-rs"} libm = { version = "0.2.15" } +heapless = { version = "0.8.0" } + cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.5" # embedded-hal = "0.2.6" diff --git a/src/ad5940.rs b/src/ad5940.rs index 9c9e3cc..f1c08c5 100644 --- a/src/ad5940.rs +++ b/src/ad5940.rs @@ -3,6 +3,8 @@ use defmt::*; use embassy_stm32::{gpio::Output, mode::Blocking, spi::Spi, spi::Error}; use embassy_time::Timer; +use heapless::LinearMap; + use crate::ad5940_registers::*; pub struct AD5940 { @@ -11,7 +13,8 @@ pub struct AD5940 { rst: Output<'static>, seq_enabled: bool, pub seq_len: usize, - pub seq_buffer: [u32; 16], + pub seq_buffer: [u32; 25], + pub seq_gen_db: LinearMap, } impl AD5940 { @@ -22,7 +25,8 @@ impl AD5940 { rst, seq_enabled: false, seq_len: 0, - seq_buffer: [0; 16], + seq_buffer: [0; 25], + seq_gen_db: LinearMap::new(), } } @@ -34,7 +38,11 @@ impl AD5940 { } pub async fn read_reg(&mut self, address: Register) -> Result { - self.read_reg_raw(address as u16).await + if self.seq_enabled { + self.sequencer_read_register(address).await + } else { + self.read_reg_raw(address as u16).await + } } pub async fn read_reg_raw(&mut self, address: u16) -> Result { @@ -129,10 +137,32 @@ impl AD5940 { } } + async fn sequencer_read_register(&mut self, address: Register) -> Result { + if address as u32 > 0x21FF { + error!("Sequencer read address out of range: 0x{:04X}", address as u32); + } + + // Read from sequencer database, if not present read default (often default) from hardware + if let Some(value) = self.seq_gen_db.get(&address) { + Ok(*value) + } else { + self.read_reg_raw(address as u16).await + } + } + async fn sequencer_write_register(&mut self, address: Register, value: u32) -> Result<(), Error> { if address as u32 > 0x21FF { error!("Sequencer write address out of range: 0x{:04X}", address as u32); } + + // Update or put in sequencer database + if self.seq_gen_db.contains_key(&address) { + *self.seq_gen_db.get_mut(&address).unwrap() = value; + } else { + self.seq_gen_db.insert(address, value).unwrap(); + } + + // Place into buffer let cmd = 0b1 << 31 | (((address as u32) >> 2) & 0x7F) << 24 | (value & 0xFF_FFFF); self.sequencer_insert(cmd).await; @@ -154,7 +184,7 @@ impl AD5940 { } async fn sequencer_insert(&mut self, cmd: u32) { - if self.seq_len >= 16 { + if self.seq_len >= self.seq_buffer.len() { error!("Sequencer buffer full, cannot insert command: 0x{:08X}", cmd); return; } @@ -263,7 +293,7 @@ impl AD5940 { } else if (ctr & SWCON::TMUXCON_MSK) == SWCON::TMUXCON_TR1 { reg &= !SWCON::TMUXCON_MSK; reg |= SWCON::TMUXCON_TR1; - } + } // NMUXCON if (ctr & SWCON::NMUXCON_MSK) == SWCON::NMUXCON_N2 { @@ -403,29 +433,43 @@ impl AD5940 { self.afecon( AFECON::DACBUFEN | AFECON::DACREFEN - | AFECON::SINC2EN - | AFECON::DFTEN - | AFECON::WAVEGENEN + // | AFECON::SINC2EN + // | AFECON::DFTEN + // | AFECON::WAVEGENEN | AFECON::TIAEN | AFECON::INAMPEN | AFECON::EXBUFEN - | AFECON::ADCCONVEN - | AFECON::ADCEN + // | AFECON::ADCCONVEN + // | AFECON::ADCEN | AFECON::DACEN, true, ) .await; // SWCON - set up switch matrix for impedance measurement - self.swcon( - SWCON::NMUXCON_N2 - | SWCON::PMUXCON_P11 - | SWCON::DMUXCON_D5).await; - // - self.write_reg_raw(0x0000_20D0, 0b1000 << 4).await.unwrap(); // 1024 OSR + // self.swcon( + // SWCON::NMUXCON_N2 + // | SWCON::PMUXCON_P11 + // | SWCON::DMUXCON_D5).await; + + let config_wgcon = WGCON::TYPESEL_SIN.bits(); + self.write_reg(Register::WGCON, config_wgcon).await.unwrap(); + + // BUFSENCON + self.write_reg(Register::BUFSENCON, 0b1).await.unwrap(); + + // DFTCON + self.write_reg(Register::DFTCON, 0b0111 << 4 | 0b1).await.unwrap(); // 1024 OSR // SINC3 = 5 --> 160000 Hz // SINC2 = 178 --> 898,8764044944Hz // ... (DFTNUM = 2048) + + // ADCCON + self.write_reg(Register::ADCCON, ADCCON::MUXSELN_TIAN.bits() | ADCCON::MUXSELP_TIAP.bits()).await?; + + // HSRTIACON: RTIACON 32pF & 5k + self.write_reg(Register::HSRTIACON, 0b10000 << 5 | 0b0010).await?; + Ok(()) } } @@ -445,7 +489,7 @@ enum Command { #[allow(dead_code)] #[allow(non_camel_case_types)] #[repr(u16)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Eq, PartialEq, Debug, defmt::Format)] pub enum Register { ADIID = 0x0000_0400, // Analog Devices Inc., identification register CHIPID = 0x0000_0404, // Chip identification register @@ -480,4 +524,8 @@ pub enum Register { SYNCEXTDEVICE = 0x0000_2054, // Sync External Device Register GP0CON = 0x0000_0000, // GPIO Port 0 Configuration Register DATAFIFORD = 0x0000_206C, // Data FIFO Read Register -} + DFTCON = 0x0000_20D0, // DFT Configuration Register + HSDACCON = 0x0000_2010, // High Speed DAC Configuration Register + HSRTIACON = 0x0000_20F0, // High Speed RTIA Configuration Register + BUFSENCON = 0x0000_2180, // HIGH POWER AND LOW POWER BUFFER CONTROL REGISTER +} \ No newline at end of file diff --git a/src/ad5940_registers.rs b/src/ad5940_registers.rs index 989ec8c..3b25a4c 100644 --- a/src/ad5940_registers.rs +++ b/src/ad5940_registers.rs @@ -71,12 +71,20 @@ bitflags! { } } +bitflags! { + // HIGH POWER AND LOW POWER BUFFER CONTROL REGISTER + // Address 0x00002180, Reset 0x00000037, Name BEFSENCON + +} + bitflags! { // ADC Configuration Register, // Address 0x000021A8, Reset: 0x00000000, Name: ADCCON pub struct ADCCON: u32 { const GNPGA_1_5 = 1 << 16; + const MUXSELN_TIAN = 0b00001 << 8; const MUXSELN_TEMP = 0b01011 << 8; + const MUXSELP_TIAP = 0b00001; const MUXSELP_TEMP = 0b01011; } } diff --git a/src/main.rs b/src/main.rs index 7b17502..2ddfc45 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,7 +88,7 @@ async fn main(spawner: Spawner) { ad5940.system_init().await.unwrap(); // ad5940.init_temperature().await.unwrap(); - ad5940.init_waveform().await.unwrap(); + // ad5940.init_waveform().await.unwrap(); ad5940.init_impedance().await.unwrap(); // // Set up I2C for ADG2128 @@ -116,22 +116,26 @@ async fn main(spawner: Spawner) { // Sequencer test ad5940.sequencer_enable(true).await; - ad5940.wgfcw(100).await; + + ad5940.wgfcw(50000).await; + let wg_amplitude = 2047; // 2047 is the maximum amplitude for a 12-bit DAC --> 1.62V peak-to-peak + ad5940.write_reg(ad5940::Register::WGAMPLITUDE, wg_amplitude).await.unwrap(); // Rcal ad5940.swcon(SWCON::DMUXCON_DR0 | SWCON::PMUXCON_PR0 | SWCON::NMUXCON_NR1 | SWCON::TMUXCON_TR1 | SWCON::T9CON).await; // RCAL0 --> ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await; ad5940.sequencer_wait(16*10).await; // 10 us ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; - ad5940.sequencer_wait(16 * 1_500_000).await; // 1.5 second + ad5940.sequencer_wait(16 * 750_000).await; // 0.75 second ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await; - + ad5940.write_reg(ad5940::Register::AFECON, 0x0000_FFFF).await.unwrap(); + // Rz - ad5940.swcon(SWCON::DMUXCON_D5 | SWCON::PMUXCON_P11 | SWCON::NMUXCON_N2 | SWCON::TMUXCON_MSK | SWCON::TMUXCON_T2).await; + ad5940.swcon(SWCON::DMUXCON_D5 | SWCON::PMUXCON_P11 | SWCON::NMUXCON_N2 | SWCON::TMUXCON_T2 | SWCON::T9CON).await; ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await; ad5940.sequencer_wait(16*10).await; // 10 us ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; - ad5940.sequencer_wait(16 * 1_500_000).await; // 1.5 second + ad5940.sequencer_wait(16 * 750_000).await; // 0.75 second ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await; // Toggle leds @@ -174,7 +178,7 @@ async fn main(spawner: Spawner) { // info!("Mainloop still running!"); - Timer::after_millis(3500).await; + Timer::after_millis(1750).await; // let test = ad5940.read_reg_raw(0x2200).await.unwrap(); // info!("FIFOCNTSTA: {}", (test>>16) & 0b111_1111_1111); @@ -222,7 +226,6 @@ async fn green_led(mut led: Output<'static>) { async fn ad5940_readout_task(mut pin: ExtiInput<'static>) { loop { pin.wait_for_falling_edge().await; - info!("AD5940 interrupt triggered!"); } }