Added lineairmap to lib for sequencer.

This commit is contained in:
2025-08-14 13:23:23 +02:00
parent f1015ee00d
commit 03a04bf789
5 changed files with 88 additions and 26 deletions

1
Cargo.lock generated
View File

@@ -74,6 +74,7 @@ dependencies = [
"embassy-time", "embassy-time",
"embassy-usb", "embassy-usb",
"embedded-hal 1.0.0", "embedded-hal 1.0.0",
"heapless 0.8.0",
"libm", "libm",
"panic-probe", "panic-probe",
"postcard-rpc", "postcard-rpc",

View File

@@ -24,6 +24,8 @@ bioz-icd-rs = {path = "../bioz-icd-rs"}
libm = { version = "0.2.15" } 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 = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.5" cortex-m-rt = "0.7.5"
# embedded-hal = "0.2.6" # embedded-hal = "0.2.6"

View File

@@ -3,6 +3,8 @@ use defmt::*;
use embassy_stm32::{gpio::Output, mode::Blocking, spi::Spi, spi::Error}; use embassy_stm32::{gpio::Output, mode::Blocking, spi::Spi, spi::Error};
use embassy_time::Timer; use embassy_time::Timer;
use heapless::LinearMap;
use crate::ad5940_registers::*; use crate::ad5940_registers::*;
pub struct AD5940 { pub struct AD5940 {
@@ -11,7 +13,8 @@ pub struct AD5940 {
rst: Output<'static>, rst: Output<'static>,
seq_enabled: bool, seq_enabled: bool,
pub seq_len: usize, pub seq_len: usize,
pub seq_buffer: [u32; 16], pub seq_buffer: [u32; 25],
pub seq_gen_db: LinearMap<Register, u32, 16>,
} }
impl AD5940 { impl AD5940 {
@@ -22,7 +25,8 @@ impl AD5940 {
rst, rst,
seq_enabled: false, seq_enabled: false,
seq_len: 0, 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<u32, Error> { pub async fn read_reg(&mut self, address: Register) -> Result<u32, Error> {
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<u32, Error> { pub async fn read_reg_raw(&mut self, address: u16) -> Result<u32, Error> {
@@ -129,10 +137,32 @@ impl AD5940 {
} }
} }
async fn sequencer_read_register(&mut self, address: Register) -> Result<u32, Error> {
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> { async fn sequencer_write_register(&mut self, address: Register, value: u32) -> Result<(), Error> {
if address as u32 > 0x21FF { if address as u32 > 0x21FF {
error!("Sequencer write address out of range: 0x{:04X}", address as u32); 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); let cmd = 0b1 << 31 | (((address as u32) >> 2) & 0x7F) << 24 | (value & 0xFF_FFFF);
self.sequencer_insert(cmd).await; self.sequencer_insert(cmd).await;
@@ -154,7 +184,7 @@ impl AD5940 {
} }
async fn sequencer_insert(&mut self, cmd: u32) { 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); error!("Sequencer buffer full, cannot insert command: 0x{:08X}", cmd);
return; return;
} }
@@ -403,29 +433,43 @@ impl AD5940 {
self.afecon( self.afecon(
AFECON::DACBUFEN AFECON::DACBUFEN
| AFECON::DACREFEN | AFECON::DACREFEN
| AFECON::SINC2EN // | AFECON::SINC2EN
| AFECON::DFTEN // | AFECON::DFTEN
| AFECON::WAVEGENEN // | AFECON::WAVEGENEN
| AFECON::TIAEN | AFECON::TIAEN
| AFECON::INAMPEN | AFECON::INAMPEN
| AFECON::EXBUFEN | AFECON::EXBUFEN
| AFECON::ADCCONVEN // | AFECON::ADCCONVEN
| AFECON::ADCEN // | AFECON::ADCEN
| AFECON::DACEN, | AFECON::DACEN,
true, true,
) )
.await; .await;
// SWCON - set up switch matrix for impedance measurement // SWCON - set up switch matrix for impedance measurement
self.swcon( // self.swcon(
SWCON::NMUXCON_N2 // SWCON::NMUXCON_N2
| SWCON::PMUXCON_P11 // | SWCON::PMUXCON_P11
| SWCON::DMUXCON_D5).await; // | SWCON::DMUXCON_D5).await;
//
self.write_reg_raw(0x0000_20D0, 0b1000 << 4).await.unwrap(); // 1024 OSR 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 // SINC3 = 5 --> 160000 Hz
// SINC2 = 178 --> 898,8764044944Hz // SINC2 = 178 --> 898,8764044944Hz
// ... (DFTNUM = 2048) // ... (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(()) Ok(())
} }
} }
@@ -445,7 +489,7 @@ enum Command {
#[allow(dead_code)] #[allow(dead_code)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[repr(u16)] #[repr(u16)]
#[derive(Clone, Copy)] #[derive(Clone, Copy, Eq, PartialEq, Debug, defmt::Format)]
pub enum Register { pub enum Register {
ADIID = 0x0000_0400, // Analog Devices Inc., identification register ADIID = 0x0000_0400, // Analog Devices Inc., identification register
CHIPID = 0x0000_0404, // Chip identification register CHIPID = 0x0000_0404, // Chip identification register
@@ -480,4 +524,8 @@ pub enum Register {
SYNCEXTDEVICE = 0x0000_2054, // Sync External Device Register SYNCEXTDEVICE = 0x0000_2054, // Sync External Device Register
GP0CON = 0x0000_0000, // GPIO Port 0 Configuration Register GP0CON = 0x0000_0000, // GPIO Port 0 Configuration Register
DATAFIFORD = 0x0000_206C, // Data FIFO Read 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
} }

View File

@@ -71,12 +71,20 @@ bitflags! {
} }
} }
bitflags! {
// HIGH POWER AND LOW POWER BUFFER CONTROL REGISTER
// Address 0x00002180, Reset 0x00000037, Name BEFSENCON
}
bitflags! { bitflags! {
// ADC Configuration Register, // ADC Configuration Register,
// Address 0x000021A8, Reset: 0x00000000, Name: ADCCON // Address 0x000021A8, Reset: 0x00000000, Name: ADCCON
pub struct ADCCON: u32 { pub struct ADCCON: u32 {
const GNPGA_1_5 = 1 << 16; const GNPGA_1_5 = 1 << 16;
const MUXSELN_TIAN = 0b00001 << 8;
const MUXSELN_TEMP = 0b01011 << 8; const MUXSELN_TEMP = 0b01011 << 8;
const MUXSELP_TIAP = 0b00001;
const MUXSELP_TEMP = 0b01011; const MUXSELP_TEMP = 0b01011;
} }
} }

View File

@@ -88,7 +88,7 @@ async fn main(spawner: Spawner) {
ad5940.system_init().await.unwrap(); ad5940.system_init().await.unwrap();
// ad5940.init_temperature().await.unwrap(); // ad5940.init_temperature().await.unwrap();
ad5940.init_waveform().await.unwrap(); // ad5940.init_waveform().await.unwrap();
ad5940.init_impedance().await.unwrap(); ad5940.init_impedance().await.unwrap();
// // Set up I2C for ADG2128 // // Set up I2C for ADG2128
@@ -116,22 +116,26 @@ async fn main(spawner: Spawner) {
// Sequencer test // Sequencer test
ad5940.sequencer_enable(true).await; 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 // Rcal
ad5940.swcon(SWCON::DMUXCON_DR0 | SWCON::PMUXCON_PR0 | SWCON::NMUXCON_NR1 | SWCON::TMUXCON_TR1 | SWCON::T9CON).await; // RCAL0 --> 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.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await;
ad5940.sequencer_wait(16*10).await; // 10 us ad5940.sequencer_wait(16*10).await; // 10 us
ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; 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.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
ad5940.write_reg(ad5940::Register::AFECON, 0x0000_FFFF).await.unwrap();
// Rz // 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.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await;
ad5940.sequencer_wait(16*10).await; // 10 us ad5940.sequencer_wait(16*10).await; // 10 us
ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; 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.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
// Toggle leds // Toggle leds
@@ -174,7 +178,7 @@ async fn main(spawner: Spawner) {
// info!("Mainloop still running!"); // info!("Mainloop still running!");
Timer::after_millis(3500).await; Timer::after_millis(1750).await;
// let test = ad5940.read_reg_raw(0x2200).await.unwrap(); // let test = ad5940.read_reg_raw(0x2200).await.unwrap();
// info!("FIFOCNTSTA: {}", (test>>16) & 0b111_1111_1111); // 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>) { async fn ad5940_readout_task(mut pin: ExtiInput<'static>) {
loop { loop {
pin.wait_for_falling_edge().await; pin.wait_for_falling_edge().await;
info!("AD5940 interrupt triggered!");
} }
} }