From d17ef6c7aebdc4f64184cdcbc8ee8218fff8cd2a Mon Sep 17 00:00:00 2001 From: Hubald Verzijl Date: Mon, 18 Aug 2025 14:49:58 +0200 Subject: [PATCH] Updated library. --- src/ad5940.rs | 156 +++++++++++++++++------------- src/ad5940_registers.rs | 204 ++++++++++++++++++++++++++++++++++++---- src/communication.rs | 36 ++++--- src/impedance.rs | 50 +++++++--- src/main.rs | 16 +++- 5 files changed, 346 insertions(+), 116 deletions(-) diff --git a/src/ad5940.rs b/src/ad5940.rs index 359fe27..a9a683d 100644 --- a/src/ad5940.rs +++ b/src/ad5940.rs @@ -18,10 +18,6 @@ pub struct SwitchConfig { } impl SwitchConfig { - pub fn new() -> Self { - Self::default() - } - pub fn t9con(mut self, t9con: T9CON) -> Self { self.t9con = Some(t9con); self @@ -64,10 +60,6 @@ pub struct DspConfig { } impl DspConfig { - pub fn new() -> Self { - Self::default() - } - pub fn adc_mux_n(mut self, muxseln: MUXSELN) -> Self { self.muxseln = Some(muxseln); self @@ -119,6 +111,43 @@ impl DspConfig { } } +#[allow(dead_code)] +#[derive(Default)] +pub struct SramConfig { + datafifosrcsel: Option, + datafifoen: Option, + data_mem_size: Option, + cmd_mem_mode: Option, + cmd_mem_size: Option, +} + +impl SramConfig { + pub fn datafifosrcsel(mut self, datafifosrcsel: DATAFIFOSRCSEL) -> Self { + self.datafifosrcsel = Some(datafifosrcsel); + self + } + + pub fn datafifoen(mut self, datafifoen: DATAFIFOEN) -> Self { + self.datafifoen = Some(datafifoen); + self + } + + pub fn data_size(mut self, data_mem_size: DATA_MEM_SEL) -> Self { + self.data_mem_size = Some(data_mem_size); + self + } + + pub fn cmd_mode(mut self, cmd_mem_mode: CMDMEMMDE) -> Self { + self.cmd_mem_mode = Some(cmd_mem_mode); + self + } + + pub fn cmd_size(mut self, cmd_mem_size: CMD_MEM_SEL) -> Self { + self.cmd_mem_size = Some(cmd_mem_size); + self + } +} + pub struct Sequencer { } @@ -464,28 +493,23 @@ impl AD5940 { let mut current = self.read_reg(Register::SWCON).await?; if let Some(t9con) = config.t9con { - current &= !(0b1 << 17); - current |= (t9con as u32) << 17; + current = T9CON::apply(current, t9con as u32); } if let Some(tmuxcon) = config.tmuxcon { - current &= !(0b1111 << 12); - current |= (tmuxcon as u32) << 12; + current = TMUXCON::apply(current, tmuxcon as u32); } if let Some(nmuxcon) = config.nmuxcon { - current &= !(0b1111 << 8); - current |= (nmuxcon as u32) << 8; + current = NMUXCON::apply(current, nmuxcon as u32); } if let Some(pmuxcon) = config.pmuxcon { - current &= !(0b1111 << 4); - current |= (pmuxcon as u32) << 4; + current = PMUXCON::apply(current, pmuxcon as u32); } if let Some(dmuxcon) = config.dmuxcon { - current &= !(0b1111); - current |= dmuxcon as u32; + current = DMUXCON::apply(current, dmuxcon as u32); } self.write_reg(Register::SWCON, current).await?; @@ -498,12 +522,10 @@ impl AD5940 { let mut current = self.read_reg(Register::ADCCON).await?; if let Some(muxseln) = config.muxseln { - current &= !(0b11111 << 8); - current |= (muxseln as u32) << 8; + current = MUXSELN::apply(current, muxseln as u32); } if let Some(muxselp) = config.muxselp { - current &= !(0b11111); - current |= (muxselp as u32); + current = MUXSELP::apply(current, muxselp as u32); } self.write_reg(Register::ADCCON, current).await?; @@ -512,13 +534,11 @@ impl AD5940 { let mut current = self.read_reg(Register::HSRTIACON).await?; if let Some(ctiacon) = config.ctiacon { - current &= !(0b1111 << 5); - current |= (ctiacon as u32) << 5; + current = CTIACON::apply(current, ctiacon as u32); } if let Some(rtiacon) = config.rtiacon { - current &= !(0b1111); - current |= rtiacon as u32; + current = RTIACON::apply(current, rtiacon as u32); } self.write_reg(Register::HSRTIACON, current).await?; @@ -527,18 +547,15 @@ impl AD5940 { let mut current = self.read_reg(Register::ADCFILTERCON).await?; if let Some(sinc3osr) = config.sinc3osr{ - current &= !(0b11 << 12); - current |= (sinc3osr as u32) << 12; + current = SINC3OSR::apply(current, sinc3osr as u32); } if let Some(sinc2osr) = config.sinc2osr { - current &= !(0b1111 << 8); - current |= (sinc2osr as u32) << 8; + current = SINC2OSR::apply(current, sinc2osr as u32); } if let Some(adcsamplerate) = config.adcsamplerate { - current &= !1; - current |= adcsamplerate as u32; + current = ADCSAMPLERATE::apply(current, adcsamplerate as u32); } self.write_reg(Register::ADCFILTERCON, current).await?; @@ -547,16 +564,13 @@ impl AD5940 { let mut current = self.read_reg(Register::DFTCON).await?; if let Some(dftin) = config.dftin { - current &= !(0b11 << 20); - current |= (dftin as u32) << 20; + current = DFTINSEL::apply(current, dftin as u32); } if let Some(dftnum) = config.dftnum { - current &= !(0b1111 << 4); - current |= (dftnum as u32) << 4; + current = DFTNUM::apply(current, dftnum as u32); } if let Some(hanning) = config.hanning { - current &= !(0b1 << 0); - current |= (hanning as u32) << 0; + current = HANNING::apply(current, hanning as u32); } self.write_reg(Register::DFTCON, current).await?; @@ -603,30 +617,42 @@ impl AD5940 { self.write_reg(Register::WGFCW, sinefcw).await.unwrap(); } - pub async fn cmddatacon(&mut self) { + pub async fn apply_sram_config(&mut self, config: SramConfig) -> Result<(), Error> { // Disable sequencer - let mut reg = self.read_reg(Register::SEQCON).await.unwrap(); - reg &= !0x0000_0001; // Clear the enable bits - self.write_reg(Register::SEQCON, reg).await.unwrap(); + self.write_reg(Register::SEQCON, 0x0000_0002).await?; // Reset SEQCON - self.write_reg(Register::SEQCNT, 0x0000_0001).await.unwrap(); + self.write_reg(Register::SEQCNT, 0x0000_0001).await?; - // Disable fifo - self.write_reg(Register::FIFOCON, 0b010 << 13).await.unwrap(); - // self.write_reg(Register::FIFOCON, 0b011 << 13).await.unwrap(); + // FIFICON + let mut current_fifocon = self.read_reg(Register::FIFOCON).await?; + if let Some(datafifosrcsel) = config.datafifosrcsel { + current_fifocon = DATAFIFOSRCSEL::apply(current_fifocon, datafifosrcsel as u32); + } + current_fifocon &= !(0b1 << 11); // Disable FIFO + self.write_reg(Register::FIFOCON, current_fifocon).await?; - let cmd = 0b101 << 9 | 0b001 << 6 | 0b01 << 3 | 0b01; - self.write_reg(Register::CMDDATACON, cmd).await.unwrap(); + // CMDDATACON + let mut current = self.read_reg(Register::CMDDATACON).await?; + if let Some(size) = config.data_mem_size { + current = DATA_MEM_SEL::apply(current, size as u32); + } + if let Some(mode) = config.cmd_mem_mode { + current = CMDMEMMDE::apply(current, mode as u32); + } + if let Some(size) = config.cmd_mem_size { + current = CMD_MEM_SEL::apply(current, size as u32); + } + self.write_reg(Register::CMDDATACON, current).await?; // Enable FIFO - self.write_reg(Register::FIFOCON, 0b010 << 13 | 1 << 11 ).await.unwrap(); - // self.write_reg(Register::FIFOCON, 0b011 << 13 | 1 << 11 ).await.unwrap(); + current_fifocon |= 0b1 << 11; // Enable FIFO + self.write_reg(Register::FIFOCON, current_fifocon).await?; // Enable sequencer - let mut reg = self.read_reg(Register::SEQCON).await.unwrap(); - reg |= 0x0000_0001; // Set the enable bit - self.write_reg(Register::SEQCON, reg).await.unwrap(); + self.write_reg(Register::SEQCON, 0x0000_0003).await?; + + Ok(()) } pub async fn get_chipid(&mut self) -> u16 { @@ -682,7 +708,7 @@ impl AD5940 { self.write_reg(Register::WGCON, config_wgcon).await?; // SWCON - set up switch matri - let switch_config = SwitchConfig::new() + let switch_config = SwitchConfig::default() .nmuxcon(NMUXCON::N2Closed) .pmuxcon(PMUXCON::P11Closed) .dmuxcon(DMUXCON::D5Closed); @@ -705,8 +731,6 @@ impl AD5940 { #[allow(dead_code)] #[allow(non_camel_case_types)] - - #[repr(u8)] enum Command { SPICMD_SETADDR = 0x20, @@ -722,9 +746,9 @@ enum Command { pub enum Register { ADIID = 0x0000_0400, // Analog Devices Inc., identification register CHIPID = 0x0000_0404, // Chip identification register - TRIGSEQ = 0x0000_0430, // Trigger Sequencer Register + TRIGSEQ = 0x0000_0430, // Trigger Sequencer Register AFECON = 0x0000_2000, // Configuration Register - SEQCON = 0x0000_2004, // Sequencer Configuration Register + SEQCON = 0x0000_2004, // Sequencer Configuration Register FIFOCON = 0x0000_2008, // FIFO Configuration Register SWCON = 0x0000_200C, // Switch Matrix Configuration Register WGCON = 0x0000_2014, // Waveform Generator Configuration Register @@ -739,7 +763,7 @@ pub enum Register { SEQ0INFO = 0x0000_21CC, // Sequence 0 Information Register SEQ1INFO = 0x0000_21E8, // Sequence 1 Information Register SEQ2INFO = 0x0000_21D0, // Sequence 2 Information Register - CMDDATACON = 0x0000_21D8, // Command Data Control Register + CMDDATACON = 0x0000_21D8, // Command Data Control Register SEQ3INFO = 0x0000_21E4, // Sequence 3 Information Register AFEGENINTSTA = 0x0000_209C, // Analog Generation Interrupt Register CMDFIFOWADDR = 0x0000_21D4, // Command FIFO Write Address Register @@ -751,12 +775,12 @@ pub enum Register { SEQCRC = 0x0000_2060, // Sequencer CRC Value Register DATAFIFOTHRES = 0x0000_21E0, // Data FIFO Threshold 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 - FIFOCNTSTA = 0x0000_2200, // Command and data FIFO internal data count 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 + FIFOCNTSTA = 0x0000_2200, // Command and data FIFO internal data count register ADCFILTERCON = 0x0000_2044 // ADC Output Filters Configuration Register } \ No newline at end of file diff --git a/src/ad5940_registers.rs b/src/ad5940_registers.rs index 767d1a8..7fa97a8 100644 --- a/src/ad5940_registers.rs +++ b/src/ad5940_registers.rs @@ -1,9 +1,27 @@ use bitflags::bitflags; #[allow(dead_code)] -pub trait Resettable { +pub trait RegisterField { + /// Reset value for this field fn reset() -> Self; - // fn msk() -> u32; + + /// Bit offset of the field within the register + const BIT_OFFSET: u32; + + /// Bitmask of the field (not shifted) + const MASK: u32; + + /// Clears the field bits in the register + fn clear(reg: u32) -> u32 { + reg & !(Self::MASK << Self::BIT_OFFSET) + } + + /// Applies a new value to the field in the register + fn apply(reg: u32, val: u32) -> u32 { + let cleared = reg & !(Self::MASK << Self::BIT_OFFSET); + let shifted = (val & Self::MASK) << Self::BIT_OFFSET; + cleared | shifted + } } #[allow(dead_code)] @@ -12,13 +30,12 @@ pub enum T9CON { T9Open = 0, } -impl Resettable for T9CON { +impl RegisterField for T9CON { fn reset() -> Self { T9CON::T9Open } - // fn msk() -> u32 { - // 0b1 - // } + const BIT_OFFSET: u32 = 17; + const MASK: u32 = 0b1; } #[allow(dead_code)] @@ -35,10 +52,12 @@ pub enum TMUXCON { AllClosed = 0b1001, } -impl Resettable for TMUXCON { +impl RegisterField for TMUXCON { fn reset() -> Self { TMUXCON::AllOpen } + const BIT_OFFSET: u32 = 12; + const MASK: u32 = 0b1111; } #[allow(dead_code)] @@ -57,10 +76,12 @@ pub enum NMUXCON { AllOpen = 0b1111, } -impl Resettable for NMUXCON { +impl RegisterField for NMUXCON { fn reset() -> Self { NMUXCON::AllOpen } + const BIT_OFFSET: u32 = 8; + const MASK: u32 = 0b1111; } #[allow(dead_code)] @@ -79,10 +100,12 @@ pub enum PMUXCON { AllOpen = 0b1111, } -impl Resettable for PMUXCON { +impl RegisterField for PMUXCON { fn reset() -> Self { PMUXCON::AllOpen } + const BIT_OFFSET: u32 = 4; + const MASK: u32 = 0b1111; } #[allow(dead_code)] @@ -99,10 +122,12 @@ pub enum DMUXCON { AllClosed = 0b1001 } -impl Resettable for DMUXCON { +impl RegisterField for DMUXCON { fn reset() -> Self { DMUXCON::AllOpen } + const BIT_OFFSET: u32 = 0; + const MASK: u32 = 0b1111; } #[allow(dead_code)] @@ -110,19 +135,37 @@ impl Resettable for DMUXCON { #[derive(Copy, Clone)] pub enum MUXSELN { + Floating = 0b00000, HsTiaNeg = 0b00001, LpTiaNeg = 0b00010, AIN1 = 0b00101, } +impl RegisterField for MUXSELN { + fn reset() -> Self { + MUXSELN::Floating + } + const BIT_OFFSET: u32 = 8; + const MASK: u32 = 0b11111; +} + #[allow(dead_code)] #[repr(u32)] #[derive(Copy, Clone)] pub enum MUXSELP { + Floating = 0b00000, HsTiaPos = 0b00001, AIN1 = 0b00101, } +impl RegisterField for MUXSELP { + fn reset() -> Self { + MUXSELP::Floating + } + const BIT_OFFSET: u32 = 0; + const MASK: u32 = 0b11111; +} + #[allow(dead_code)] #[repr(u32)] #[derive(Copy, Clone)] @@ -132,10 +175,12 @@ pub enum DFTINSEL { AdcRaw = 0b10 } -impl Resettable for DFTINSEL { +impl RegisterField for DFTINSEL { fn reset() -> Self { DFTINSEL::Sinc2 } + const BIT_OFFSET: u32 = 20; + const MASK: u32 = 0b11; } #[allow(dead_code)] @@ -157,10 +202,28 @@ pub enum DFTNUM { Num16384 = 0b1100, } -impl Resettable for DFTNUM { +impl RegisterField for DFTNUM { fn reset() -> Self { DFTNUM::Num2048 } + const BIT_OFFSET: u32 = 4; + const MASK: u32 = 0b1111; +} + +#[allow(dead_code)] +#[repr(u32)] +#[derive(Copy, Clone)] +pub enum HANNING { + Disable = 0, + Enable = 1, +} + +impl RegisterField for HANNING { + fn reset() -> Self { + HANNING::Disable + } + const BIT_OFFSET: u32 = 0; + const MASK: u32 = 0b1; } #[allow(dead_code)] @@ -174,10 +237,12 @@ pub enum CTIACON { C32 = 1 << 4, } -impl Resettable for CTIACON { +impl RegisterField for CTIACON { fn reset() -> Self { CTIACON::C1 } + const BIT_OFFSET: u32 = 5; + const MASK: u32 = 0b111_1111; } #[allow(dead_code)] @@ -194,10 +259,12 @@ pub enum RTIACON { Open = 0b1111, } -impl Resettable for RTIACON { +impl RegisterField for RTIACON { fn reset() -> Self { RTIACON::Open } + const BIT_OFFSET: u32 = 0; + const MASK: u32 = 0b1111; } #[allow(dead_code)] @@ -208,10 +275,12 @@ pub enum SINC3OSR { R2 = 0b10, } -impl Resettable for SINC3OSR { +impl RegisterField for SINC3OSR { fn reset() -> Self { SINC3OSR::R5 } + const BIT_OFFSET: u32 = 12; + const MASK: u32 = 0b11; } #[allow(dead_code)] @@ -231,10 +300,12 @@ pub enum SINC2OSR { R1333 = 0b1011, } -impl Resettable for SINC2OSR { +impl RegisterField for SINC2OSR { fn reset() -> Self { SINC2OSR::R178 } + const BIT_OFFSET: u32 = 8; + const MASK: u32 = 0b1111; } #[allow(dead_code)] @@ -244,10 +315,109 @@ pub enum ADCSAMPLERATE { R1_6MHz = 0, } -impl Resettable for ADCSAMPLERATE { +impl RegisterField for ADCSAMPLERATE { fn reset() -> Self { ADCSAMPLERATE::R1_6MHz } + const BIT_OFFSET: u32 = 0; + const MASK: u32 = 0b1; +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub enum DATAMEMMDE { + FIFOMode = 0b10, + Stream = 0b11, +} + +impl RegisterField for DATAMEMMDE { + fn reset() -> Self { + DATAMEMMDE::FIFOMode + } + const BIT_OFFSET: u32 = 9; + const MASK: u32 = 0b11; +} + +#[allow(dead_code, non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum DATA_MEM_SEL { + Reserved = 0b000, + Size2kB = 0b001, + Size4kB = 0b010, + Size6kB = 0b011, +} + +impl RegisterField for DATA_MEM_SEL { + fn reset() -> Self { + DATA_MEM_SEL::Reserved + } + const BIT_OFFSET: u32 = 6; + const MASK: u32 = 0b111; +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub enum CMDMEMMDE { + MemoryMode = 0b01, + Reserved = 0b10, +} + +impl RegisterField for CMDMEMMDE { + fn reset() -> Self { + CMDMEMMDE::Reserved + } + const BIT_OFFSET: u32 = 3; + const MASK: u32 = 0b111; +} + +#[allow(dead_code, non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum CMD_MEM_SEL { + Reserved = 0x0, + Size2kB = 0x1, + Size4kB = 0x2, + Size6kB = 0x3, +} + +impl RegisterField for CMD_MEM_SEL { + fn reset() -> Self { + CMD_MEM_SEL::Reserved + } + const BIT_OFFSET: u32 = 0; + const MASK: u32 = 0b111; +} + +#[allow(dead_code)] +#[derive(Clone, Copy)] +pub enum DATAFIFOSRCSEL { + ADC = 0b000, + DFT = 0b010, + Sinc2 = 0b011, + Variance = 0b100, + Mean = 0b101, +} + +impl RegisterField for DATAFIFOSRCSEL { + fn reset() -> Self { + DATAFIFOSRCSEL::ADC + } + const BIT_OFFSET: u32 = 13; + const MASK: u32 = 0b111; +} + +#[allow(dead_code)] +#[derive(Clone, Copy)] +pub enum DATAFIFOEN { + FIFOisReset = 0b0, + Normal = 0b1, +} + +impl RegisterField for DATAFIFOEN { + fn reset() -> Self { + DATAFIFOEN::FIFOisReset + } + const BIT_OFFSET: u32 = 11; + const MASK: u32 = 0b1; } bitflags! { diff --git a/src/communication.rs b/src/communication.rs index 6eae806..523c829 100644 --- a/src/communication.rs +++ b/src/communication.rs @@ -21,7 +21,7 @@ use postcard_rpc::{ use bioz_icd_rs::{PingEndpoint, GetUniqueIdEndpoint, SetGreenLedEndpoint, StartImpedanceEndpoint, StopImpedanceEndpoint, StartImpedance, ImpedanceOutputTopic, ENDPOINT_LIST, TOPICS_IN_LIST, TOPICS_OUT_LIST}; -use crate::impedance::{IMPEDANCE_CHANNEL}; +use crate::impedance::{ImpedanceSetupType, IMPEDANCE_CHANNEL}; // Postcard RPC types type AppDriver = usb::Driver<'static, peripherals::USB>; @@ -37,15 +37,19 @@ static STORAGE: AppStorage = AppStorage::new(); pub struct Context { pub unique_id: [u8; 12], + pub impedance_setup: &'static ImpedanceSetupType, } pub struct SpawnCtx { + pub impedance_setup: &'static ImpedanceSetupType, } impl SpawnContext for Context { type SpawnCtxt = SpawnCtx; fn spawn_ctxt(&mut self) -> Self::SpawnCtxt { - SpawnCtx {} + SpawnCtx { + impedance_setup: self.impedance_setup, + } } } @@ -59,13 +63,13 @@ define_dispatch! { endpoints: { list: ENDPOINT_LIST; - | EndpointTy | kind | handler | - | ---------- | ---- | ------- | - | PingEndpoint | blocking | ping_handler | - | GetUniqueIdEndpoint | blocking | get_unique_id_handler | - | SetGreenLedEndpoint | async | set_green_led_handler | - | StartImpedanceEndpoint | spawn | start_impedance_handler | - | StopImpedanceEndpoint | async | stop_impedance_handler | + | EndpointTy | kind | handler | + | ---------- | ---- | ------- | + | PingEndpoint | blocking | ping_handler | + | GetUniqueIdEndpoint | blocking | get_unique_id_handler | + | SetGreenLedEndpoint | async | set_green_led_handler | + | StartImpedanceEndpoint | spawn | start_single_impedance_handler | + | StopImpedanceEndpoint | async | stop_single_impedance_handler | }; topics_in: { list: TOPICS_IN_LIST; @@ -111,13 +115,14 @@ async fn server_run(mut server: AppServer) { // --- -pub fn init_communication(usb_driver: Driver<'static, peripherals::USB>, spawner: Spawner) { +pub fn init_communication(usb_driver: Driver<'static, peripherals::USB>, impedance_setup: &'static ImpedanceSetupType, spawner: Spawner) { // Initialize communication peripherals let pbufs = PBUFS.take(); let config = usb_config(); let context = Context { unique_id: *uid::uid(), + impedance_setup: impedance_setup, }; let (device, tx_impl, rx_impl) = STORAGE.init(usb_driver, config, pbufs.tx_buf.as_mut_slice()); @@ -158,11 +163,16 @@ static RUNNING: Mutex = Mutex::new(false); static STOP: Mutex = Mutex::new(false); #[embassy_executor::task] -pub async fn start_impedance_handler(_context: SpawnCtx, header: VarHeader, rqst: StartImpedance, sender: Sender) { - info!("Start impedance measurement with rate {:?} Hz.", rqst.update_frequency); +pub async fn start_single_impedance_handler(context: SpawnCtx, header: VarHeader, rqst: StartImpedance, sender: Sender) { + info!("Start impedance measurement at {:?} Hz.", rqst.sinus_frequency); *RUNNING.lock().await = true; + // Init the sequencer + context.impedance_setup.lock().await.init_single_frequency_measurement(rqst.sinus_frequency).await; + // Trigger the sequencer + context.impedance_setup.lock().await.start_measurement().await; + if sender .reply::(header.seq_no, &()) .await @@ -193,7 +203,7 @@ pub async fn start_impedance_handler(_context: SpawnCtx, header: VarHeader, rqst *STOP.lock().await = false; } -pub async fn stop_impedance_handler(_context: &mut Context, _header: VarHeader, _rqst: ()) -> bool { +pub async fn stop_single_impedance_handler(_context: &mut Context, _header: VarHeader, _rqst: ()) -> bool { info!("Stop impedance measurement"); let was_busy = *RUNNING.lock().await; if was_busy { diff --git a/src/impedance.rs b/src/impedance.rs index 33b8ca2..7d80e15 100644 --- a/src/impedance.rs +++ b/src/impedance.rs @@ -3,6 +3,9 @@ use defmt::{info, error}; use embassy_stm32::spi::Error; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::channel::Channel; +use embassy_sync::mutex::Mutex; + +use static_cell::StaticCell; use crate::ad5940::*; use crate::ad5940_registers::*; @@ -11,13 +14,17 @@ use bioz_icd_rs::ImpedanceOutput; pub static IMPEDANCE_CHANNEL: Channel = Channel::new(); +pub type ImpedanceSetupType = Mutex; +pub static IMPEDANCE_SETUP: StaticCell = StaticCell::new(); + pub struct ImpedanceSetup { ad5940: AD5940, + dsp_config: Option, } impl ImpedanceSetup { pub fn new(ad5940: AD5940) -> Self { - ImpedanceSetup { ad5940 } + ImpedanceSetup { ad5940, dsp_config: None } } pub async fn init(&mut self) -> Result<(), Error> { @@ -48,10 +55,16 @@ impl ImpedanceSetup { .hanning(true); self.ad5940.apply_dsp_config(&dsp_config).await.unwrap(); + self.dsp_config = Some(dsp_config); - let test = self.ad5940.sequencer_calculate_wait_time(&dsp_config).await.unwrap(); - info!("Wait time: {:?}", test); - + // Set SRAM configuration (cmd and data sram) + let sram_config = SramConfig::default() + .datafifosrcsel(DATAFIFOSRCSEL::DFT) + .datafifoen(DATAFIFOEN::Normal) + .data_size(DATA_MEM_SEL::Size2kB) + .cmd_mode(CMDMEMMDE::MemoryMode) + .cmd_size(CMD_MEM_SEL::Size2kB); + self.ad5940.apply_sram_config(sram_config).await.unwrap(); // WGCON: set sinus output let config_wgcon = WGCON::TYPESEL_SIN.bits(); @@ -60,15 +73,24 @@ impl ImpedanceSetup { Ok(()) } - pub async fn init_measurement(&mut self) { + pub async fn init_single_frequency_measurement(&mut self, frequency: u32) { // Configure GPIOs self.ad5940.write_reg(Register::GP0CON, 0b10 << 4 | 0b10 << 2 | 0b10).await.unwrap(); self.ad5940.write_reg(Register::SYNCEXTDEVICE, 0b111).await.unwrap(); + // Calculate wait time between measurement start and stop + let mut wait_time = 0; + if let Some(dsp_config) = &self.dsp_config { + 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); + } else { + error!("DSP configuration not set, cannot calculate wait time"); + } + // Configure sequencer self.ad5940.sequencer_enable(true).await; - self.ad5940.wgfcw(50000).await; + self.ad5940.wgfcw(frequency).await; let wg_amplitude = 557; // 2047 is the maximum amplitude for a 12-bit DAC --> 1.62V peak-to-peak self.ad5940.write_reg(Register::WGAMPLITUDE, wg_amplitude).await.unwrap(); @@ -83,9 +105,8 @@ impl ImpedanceSetup { self.ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await; self.ad5940.sequencer_wait(16*10).await; // 10 us self.ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; - // self.ad5940.sequencer_wait(16 * 102_400).await; // 0.75 second // 0,0512 - self.ad5940.sequencer_wait(16 * 12_800).await; // 0.75 second // 0,0512 - self.ad5940.sequencer_wait(16*20).await; // 0.75 second // 0,0512 + self.ad5940.sequencer_wait(wait_time).await; // Determined above + self.ad5940.sequencer_wait(16*20).await; // 10 us self.ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await; // Rz @@ -99,9 +120,8 @@ impl ImpedanceSetup { self.ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await; self.ad5940.sequencer_wait(16*10).await; // 10 us self.ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await; - // self.ad5940.sequencer_wait(16 * 102_400).await; // 0.75 second - self.ad5940.sequencer_wait(16 * 12_800).await; // 0.75 second // 0,0512 - self.ad5940.sequencer_wait(16*20).await; // 0.75 second // 0,0512 + self.ad5940.sequencer_wait(wait_time).await; // Determined above + self.ad5940.sequencer_wait(16*20).await; // 10 us self.ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await; // Toggle leds @@ -111,13 +131,13 @@ impl ImpedanceSetup { self.ad5940.sequencer_enable(false).await; - // // Configure the sequencer cmd data sram - self.ad5940.cmddatacon().await; - + // Write sequence to SRAM let start_address = 0; self.ad5940.sequencer_cmd_write(start_address).await; self.ad5940.sequencer_info_configure(0, self.ad5940.seq_len, start_address).await; + + self.start_measurement().await; } pub async fn start_measurement(&mut self) { diff --git a/src/main.rs b/src/main.rs index d69e3b5..40bb8bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_stm32::exti::ExtiInput; +use embassy_sync::mutex::Mutex; use embassy_time::{Timer, Duration}; use embassy_futures::{select::select, select::Either}; use embassy_stm32::gpio::{Level, Output, Speed}; @@ -37,7 +38,7 @@ use communication::{init_communication, LED_FREQUENCY_SIGNAL}; use impedance::IMPEDANCE_CHANNEL; mod impedance; -use impedance::ImpedanceSetup; +use impedance::{ImpedanceSetup, ImpedanceSetupType, IMPEDANCE_SETUP}; bind_interrupts!(struct Irqs { USB_DRD_FS => usb::InterruptHandler; @@ -93,7 +94,9 @@ async fn main(spawner: Spawner) { // ad5940.init_waveform().await.unwrap(); let mut impedance_setup = ImpedanceSetup::new(ad5940); impedance_setup.init().await.unwrap(); - impedance_setup.init_measurement().await; + let mut impedance_setup = IMPEDANCE_SETUP.init(Mutex::new(impedance_setup)); + + // impedance_setup.lock().await.init_single_frequency_measurement().await; // // Set up I2C for ADG2128 // let i2c = i2c::I2c::new_blocking( @@ -117,13 +120,13 @@ async fn main(spawner: Spawner) { // Create USB driver and start postcard-rpc server let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); - init_communication(driver, spawner); + init_communication(driver, impedance_setup, spawner); // Green led task // spawner.must_spawn(green_led(led)); // Trigger the sequencer - impedance_setup.start_measurement().await; + // impedance_setup.start_measurement().await; // Set up interrupt at GPIO for AD5940 let ad5940_gpio_0 = ExtiInput::new(p.PC8, p.EXTI8, embassy_stm32::gpio::Pull::Up); @@ -169,11 +172,14 @@ async fn green_led(mut led: Output<'static>) { } #[embassy_executor::task] -async fn impedance_setup_readout_task(mut pin: ExtiInput<'static>, mut impedance_setup: ImpedanceSetup) { +async fn impedance_setup_readout_task(mut pin: ExtiInput<'static>, impedance_setup: &'static ImpedanceSetupType) { loop { // Wait untill sequence is done pin.wait_for_rising_edge().await; + // Lock the impedance setup + let mut impedance_setup = impedance_setup.lock().await; + // Trigger the sequencer again impedance_setup.start_measurement().await;