mirror of
https://github.com/hubaldv/bioz-firmware-rs.git
synced 2025-12-06 05:01:18 +00:00
Started writing nice library.
This commit is contained in:
346
src/ad5940.rs
346
src/ad5940.rs
@@ -7,6 +7,134 @@ use heapless::LinearMap;
|
|||||||
|
|
||||||
use crate::ad5940_registers::*;
|
use crate::ad5940_registers::*;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct SwitchConfig {
|
||||||
|
t9con: Option<T9CON>,
|
||||||
|
tmuxcon: Option<TMUXCON>,
|
||||||
|
nmuxcon: Option<NMUXCON>,
|
||||||
|
pmuxcon: Option<PMUXCON>,
|
||||||
|
dmuxcon: Option<DMUXCON>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SwitchConfig {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn t9con(mut self, t9con: T9CON) -> Self {
|
||||||
|
self.t9con = Some(t9con);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tmuxcon(mut self, tmuxcon: TMUXCON) -> Self {
|
||||||
|
self.tmuxcon = Some(tmuxcon);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nmuxcon(mut self, nmuxcon: NMUXCON) -> Self {
|
||||||
|
self.nmuxcon = Some(nmuxcon);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pmuxcon(mut self, pmuxcon: PMUXCON) -> Self {
|
||||||
|
self.pmuxcon = Some(pmuxcon);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dmuxcon(mut self, dmuxcon: DMUXCON) -> Self {
|
||||||
|
self.dmuxcon = Some(dmuxcon);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DspConfig {
|
||||||
|
muxseln: Option<MUXSELN>,
|
||||||
|
muxselp: Option<MUXSELP>,
|
||||||
|
ctiacon: Option<CTIACON>,
|
||||||
|
rtiacon: Option<RTIACON>,
|
||||||
|
sinc3osr: Option<SINC3OSR>,
|
||||||
|
sinc2osr: Option<SINC2OSR>,
|
||||||
|
adcsamplerate: Option<ADCSAMPLERATE>,
|
||||||
|
dftin: Option<DFTINSEL>,
|
||||||
|
dftnum: Option<DFTNUM>,
|
||||||
|
hanning: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DspConfig {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn adc_mux_n(mut self, muxseln: MUXSELN) -> Self {
|
||||||
|
self.muxseln = Some(muxseln);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn adc_mux_p(mut self, muxselp: MUXSELP) -> Self {
|
||||||
|
self.muxselp = Some(muxselp);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ctiacon(mut self, ctiacon: CTIACON) -> Self {
|
||||||
|
self.ctiacon = Some(ctiacon);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rtiacon(mut self, rtiacon: RTIACON) -> Self {
|
||||||
|
self.rtiacon = Some(rtiacon);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sinc3osr(mut self, sinc3osr: SINC3OSR) -> Self {
|
||||||
|
self.sinc3osr = Some(sinc3osr);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sinc2osr(mut self, sinc2osr: SINC2OSR) -> Self {
|
||||||
|
self.sinc2osr = Some(sinc2osr);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn adcsamplerate(mut self, adcsamplerate: ADCSAMPLERATE) -> Self {
|
||||||
|
self.adcsamplerate = Some(adcsamplerate);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dftin_sel(mut self, dftin: DFTINSEL) -> Self {
|
||||||
|
self.dftin = Some(dftin);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dftnum(mut self, dftnum: DFTNUM) -> Self {
|
||||||
|
self.dftnum = Some(dftnum);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hanning(mut self, hanning: bool) -> Self {
|
||||||
|
self.hanning = Some(hanning);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sequencer {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sequencer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Sequencer {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn configure(&mut self, ad5940: &mut AD5940) -> Result<(), Error> {
|
||||||
|
// Configure the sequencer here if needed
|
||||||
|
// This is a placeholder for future sequencer configuration logic
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AD5940 {
|
pub struct AD5940 {
|
||||||
spi: Spi<'static, Blocking>,
|
spi: Spi<'static, Blocking>,
|
||||||
cs: Output<'static>,
|
cs: Output<'static>,
|
||||||
@@ -231,14 +359,110 @@ impl AD5940 {
|
|||||||
error!("Sequencers from 0 till 3 are allows, now: seq={}", seq);
|
error!("Sequencers from 0 till 3 are allows, now: seq={}", seq);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// for _ in 0..100 {
|
pub async fn apply_switch_config(&mut self, config: SwitchConfig) -> Result<(), Error> {
|
||||||
// let test = self.read_reg_raw(0x206C).await.unwrap();
|
// SWCON
|
||||||
// info!("DATAFIFORD: 0x{:08X}", test);
|
let mut current = self.read_reg(Register::SWCON).await?;
|
||||||
// }
|
|
||||||
|
if let Some(t9con) = config.t9con {
|
||||||
// let test = self.read_reg_raw(0x2200).await.unwrap();
|
current &= !(0b1 << 17);
|
||||||
// info!("FIFOCNTSTA: {}", (test>>16) & 0b111_1111_1111);
|
current |= (t9con as u32) << 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(tmuxcon) = config.tmuxcon {
|
||||||
|
current &= !(0b1111 << 12);
|
||||||
|
current |= (tmuxcon as u32) << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(nmuxcon) = config.nmuxcon {
|
||||||
|
current &= !(0b1111 << 8);
|
||||||
|
current |= (nmuxcon as u32) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(pmuxcon) = config.pmuxcon {
|
||||||
|
current &= !(0b1111 << 4);
|
||||||
|
current |= (pmuxcon as u32) << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dmuxcon) = config.dmuxcon {
|
||||||
|
current &= !(0b1111);
|
||||||
|
current |= dmuxcon as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_reg(Register::SWCON, current).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn apply_dsp_config(&mut self, config: DspConfig) -> Result<(), Error> {
|
||||||
|
// ADCCON
|
||||||
|
let mut current = self.read_reg(Register::ADCCON).await?;
|
||||||
|
|
||||||
|
if let Some(muxseln) = config.muxseln {
|
||||||
|
current &= !(0b11111 << 8);
|
||||||
|
current |= (muxseln as u32) << 8;
|
||||||
|
}
|
||||||
|
if let Some(muxselp) = config.muxselp {
|
||||||
|
current &= !(0b11111);
|
||||||
|
current |= muxselp as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_reg(Register::ADCCON, current).await?;
|
||||||
|
|
||||||
|
// HSRTIACON
|
||||||
|
let mut current = self.read_reg(Register::HSRTIACON).await?;
|
||||||
|
|
||||||
|
if let Some(ctiacon) = config.ctiacon {
|
||||||
|
current &= !(0b1111 << 5);
|
||||||
|
current |= (ctiacon as u32) << 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(rtiacon) = config.rtiacon {
|
||||||
|
current &= !(0b1111);
|
||||||
|
current |= rtiacon as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_reg(Register::HSRTIACON, current).await?;
|
||||||
|
|
||||||
|
// ADCFILTERCON
|
||||||
|
let mut current = self.read_reg(Register::ADCFILTERCON).await?;
|
||||||
|
|
||||||
|
if let Some(sinc3osr) = config.sinc3osr{
|
||||||
|
current &= !(0b11 << 12);
|
||||||
|
current |= (sinc3osr as u32) << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(sinc2osr) = config.sinc2osr {
|
||||||
|
current &= !(0b1111 << 8);
|
||||||
|
current |= (sinc2osr as u32) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(adcsamplerate) = config.adcsamplerate {
|
||||||
|
current &= !1;
|
||||||
|
current |= adcsamplerate as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_reg(Register::ADCFILTERCON, current).await?;
|
||||||
|
|
||||||
|
// DFTCON
|
||||||
|
let mut current = self.read_reg(Register::DFTCON).await?;
|
||||||
|
|
||||||
|
if let Some(dftin) = config.dftin {
|
||||||
|
current &= !(0b11 << 20);
|
||||||
|
current |= (dftin as u32) << 20;
|
||||||
|
}
|
||||||
|
if let Some(dftnum) = config.dftnum {
|
||||||
|
current &= !(0b1111 << 4);
|
||||||
|
current |= (dftnum as u32) << 4;
|
||||||
|
}
|
||||||
|
if let Some(hanning) = config.hanning {
|
||||||
|
current &= !(0b1 << 0);
|
||||||
|
current |= (hanning as u32) << 0;
|
||||||
|
}
|
||||||
|
self.write_reg(Register::DFTCON, current).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn afecon(&mut self, ctr: AFECON, state: bool) {
|
pub async fn afecon(&mut self, ctr: AFECON, state: bool) {
|
||||||
@@ -275,62 +499,6 @@ impl AD5940 {
|
|||||||
self.write_reg(Register::AFECON, reg.bits()).await.unwrap();
|
self.write_reg(Register::AFECON, reg.bits()).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn swcon(&mut self, ctr: SWCON) {
|
|
||||||
let reg = self.read_reg(Register::SWCON).await.unwrap();
|
|
||||||
let mut reg = SWCON::from_bits_truncate(reg);
|
|
||||||
|
|
||||||
// T9CON
|
|
||||||
if ctr.contains(SWCON::T9CON) {
|
|
||||||
reg |= SWCON::T9CON;
|
|
||||||
} else {
|
|
||||||
reg &= !SWCON::T9CON;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TMUXCON
|
|
||||||
if (ctr & SWCON::TMUXCON_MSK) == SWCON::TMUXCON_T2 {
|
|
||||||
reg &= !SWCON::TMUXCON_MSK;
|
|
||||||
reg |= SWCON::TMUXCON_T2;
|
|
||||||
} 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 {
|
|
||||||
reg &= !SWCON::NMUXCON_MSK;
|
|
||||||
reg |= SWCON::NMUXCON_N2;
|
|
||||||
} else if (ctr & SWCON::NMUXCON_MSK) == SWCON::NMUXCON_N5 {
|
|
||||||
reg &= !SWCON::NMUXCON_MSK;
|
|
||||||
reg |= SWCON::NMUXCON_N5;
|
|
||||||
} else if (ctr & SWCON::NMUXCON_MSK) == SWCON::NMUXCON_NR1 {
|
|
||||||
reg &= !SWCON::NMUXCON_MSK;
|
|
||||||
reg |= SWCON::NMUXCON_NR1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PMUXCON
|
|
||||||
if (ctr & SWCON::PMUXCON_MSK) == SWCON::PMUXCON_P2 {
|
|
||||||
reg &= !SWCON::PMUXCON_MSK;
|
|
||||||
reg |= SWCON::PMUXCON_P2;
|
|
||||||
} else if (ctr & SWCON::PMUXCON_MSK) == SWCON::PMUXCON_P11 {
|
|
||||||
reg &= !SWCON::PMUXCON_MSK;
|
|
||||||
reg |= SWCON::PMUXCON_P11;
|
|
||||||
} else if (ctr & SWCON::PMUXCON_MSK) == SWCON::PMUXCON_PR0 {
|
|
||||||
reg &= !SWCON::PMUXCON_MSK;
|
|
||||||
reg |= SWCON::PMUXCON_PR0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DMUXCON
|
|
||||||
if (ctr & SWCON::DMUXCON_MSK) == SWCON::DMUXCON_D5 {
|
|
||||||
reg &= !SWCON::DMUXCON_MSK;
|
|
||||||
reg |= SWCON::DMUXCON_D5;
|
|
||||||
} else if { ctr & SWCON::DMUXCON_MSK } == SWCON::DMUXCON_DR0 {
|
|
||||||
reg &= !SWCON::DMUXCON_MSK;
|
|
||||||
reg |= SWCON::DMUXCON_DR0;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.write_reg(Register::SWCON, reg.bits()).await.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn wgfcw(&mut self, frequency: u32) {
|
pub async fn wgfcw(&mut self, frequency: u32) {
|
||||||
let sinefcw = (frequency as f64) * (1_073_741_824.0 / 16_000_000.0);
|
let sinefcw = (frequency as f64) * (1_073_741_824.0 / 16_000_000.0);
|
||||||
let sinefcw = 0x00FFFFFF & sinefcw as u32;
|
let sinefcw = 0x00FFFFFF & sinefcw as u32;
|
||||||
@@ -415,12 +583,13 @@ impl AD5940 {
|
|||||||
let config_wgcon = WGCON::TYPESEL_SIN.bits();
|
let config_wgcon = WGCON::TYPESEL_SIN.bits();
|
||||||
self.write_reg(Register::WGCON, config_wgcon).await?;
|
self.write_reg(Register::WGCON, config_wgcon).await?;
|
||||||
|
|
||||||
// SWCON - set up switch matrix
|
// SWCON - set up switch matri
|
||||||
self.swcon(
|
let switch_config = SwitchConfig::new()
|
||||||
SWCON::NMUXCON_N2
|
.nmuxcon(NMUXCON::N2Closed)
|
||||||
| SWCON::PMUXCON_P11
|
.pmuxcon(PMUXCON::P11Closed)
|
||||||
| SWCON::DMUXCON_D5).await;
|
.dmuxcon(DMUXCON::D5Closed);
|
||||||
|
self.apply_switch_config(switch_config).await?;
|
||||||
|
|
||||||
// AFECON:
|
// AFECON:
|
||||||
self.afecon(
|
self.afecon(
|
||||||
AFECON::DACREFEN
|
AFECON::DACREFEN
|
||||||
@@ -441,42 +610,33 @@ impl AD5940 {
|
|||||||
AFECON::DACBUFEN
|
AFECON::DACBUFEN
|
||||||
| AFECON::DACREFEN
|
| AFECON::DACREFEN
|
||||||
| AFECON::SINC2EN
|
| AFECON::SINC2EN
|
||||||
// | AFECON::DFTEN
|
|
||||||
// | AFECON::WAVEGENEN
|
|
||||||
| AFECON::TIAEN
|
| AFECON::TIAEN
|
||||||
| AFECON::INAMPEN
|
| AFECON::INAMPEN
|
||||||
| AFECON::EXBUFEN
|
| AFECON::EXBUFEN
|
||||||
// | AFECON::ADCCONVEN
|
|
||||||
// | AFECON::ADCEN
|
|
||||||
| AFECON::DACEN,
|
| AFECON::DACEN,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// SWCON - set up switch matrix for impedance measurement
|
// Set DSP configuration
|
||||||
// self.swcon(
|
let dsp_config = DspConfig::default()
|
||||||
// SWCON::NMUXCON_N2
|
.adc_mux_n(MUXSELN::HsTiaNeg)
|
||||||
// | SWCON::PMUXCON_P11
|
.adc_mux_p(MUXSELP::HsTiaPos)
|
||||||
// | SWCON::DMUXCON_D5).await;
|
.ctiacon(CTIACON::C32)
|
||||||
|
.rtiacon(RTIACON::R5k)
|
||||||
|
.sinc3osr(SINC3OSR::R5)
|
||||||
|
.sinc2osr(SINC2OSR::R178)
|
||||||
|
.adcsamplerate(ADCSAMPLERATE::R800Hz)
|
||||||
|
.dftin_sel(DFTINSEL::GainOffset)
|
||||||
|
.dftnum(DFTNUM::Num16384)
|
||||||
|
.hanning(true);
|
||||||
|
|
||||||
|
self.apply_dsp_config(dsp_config).await.unwrap();
|
||||||
|
|
||||||
|
// WGCON: set sinus output
|
||||||
let config_wgcon = WGCON::TYPESEL_SIN.bits();
|
let config_wgcon = WGCON::TYPESEL_SIN.bits();
|
||||||
self.write_reg(Register::WGCON, config_wgcon).await.unwrap();
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,241 @@
|
|||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
|
||||||
|
pub trait Resettable {
|
||||||
|
fn reset() -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum T9CON {
|
||||||
|
T9Closed = 1,
|
||||||
|
T9Open = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for T9CON {
|
||||||
|
fn reset() -> Self {
|
||||||
|
T9CON::T9Open
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum TMUXCON {
|
||||||
|
AllOpen = 0b1111,
|
||||||
|
T1Closed = 0b0001,
|
||||||
|
T2Closed = 0b0010,
|
||||||
|
T3Closed = 0b0011,
|
||||||
|
T4Closed = 0b0100,
|
||||||
|
T5Closed = 0b0101,
|
||||||
|
T6Closed = 0b0110,
|
||||||
|
T7Closed = 0b0111,
|
||||||
|
TR1Closed = 0b1000,
|
||||||
|
AllClosed = 0b1001,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for TMUXCON {
|
||||||
|
fn reset() -> Self {
|
||||||
|
TMUXCON::AllOpen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum NMUXCON {
|
||||||
|
NLClosed = 0b0000,
|
||||||
|
N1Closed = 0b0001,
|
||||||
|
N2Closed = 0b0010,
|
||||||
|
N3Closed = 0b0011,
|
||||||
|
N4Closed = 0b0100,
|
||||||
|
N5Closed = 0b0101,
|
||||||
|
N6Closed = 0b0110,
|
||||||
|
N7Closed = 0b0111,
|
||||||
|
N9Closed = 0b1001,
|
||||||
|
NR1Closed = 0b1010,
|
||||||
|
NL1Closed = 0b1011,
|
||||||
|
AllOpen = 0b1111,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for NMUXCON {
|
||||||
|
fn reset() -> Self {
|
||||||
|
NMUXCON::AllOpen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum PMUXCON {
|
||||||
|
PLClosed = 0b0000,
|
||||||
|
PR0Closed = 0b0001,
|
||||||
|
P2Closed = 0b0010,
|
||||||
|
P3Closed = 0b0011,
|
||||||
|
P4Closed = 0b0100,
|
||||||
|
P5Closed = 0b0101,
|
||||||
|
P6Closed = 0b0110,
|
||||||
|
P7Closed = 0b0111,
|
||||||
|
P9Closed = 0b1001,
|
||||||
|
P11Closed = 0b1011,
|
||||||
|
PL2Closed = 0b1110,
|
||||||
|
AllOpen = 0b1111,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for PMUXCON {
|
||||||
|
fn reset() -> Self {
|
||||||
|
PMUXCON::AllOpen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum DMUXCON {
|
||||||
|
AllOpen = 0b1111,
|
||||||
|
DR0Closed = 0b0001,
|
||||||
|
D2Closed = 0b0010,
|
||||||
|
D3Closed = 0b0011,
|
||||||
|
D4Closed = 0b0100,
|
||||||
|
D5Closed = 0b0101,
|
||||||
|
D6Closed = 0b0110,
|
||||||
|
D7Closed = 0b0111,
|
||||||
|
P8Closed = 0b1000,
|
||||||
|
AllClosed = 0b1001
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for DMUXCON {
|
||||||
|
fn reset() -> Self {
|
||||||
|
DMUXCON::AllOpen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum MUXSELN
|
||||||
|
{
|
||||||
|
HsTiaNeg = 0b00001,
|
||||||
|
LpTiaNeg = 0b00010,
|
||||||
|
AIN1 = 0b00101,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum MUXSELP {
|
||||||
|
HsTiaPos = 0b00001,
|
||||||
|
AIN1 = 0b00101,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum DFTINSEL {
|
||||||
|
Sinc2 = 0b00,
|
||||||
|
GainOffset = 0b01,
|
||||||
|
AdcRaw = 0b10
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for DFTINSEL {
|
||||||
|
fn reset() -> Self {
|
||||||
|
DFTINSEL::Sinc2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum DFTNUM {
|
||||||
|
Num4 = 0b0000,
|
||||||
|
Num8 = 0b0001,
|
||||||
|
Num16 = 0b0010,
|
||||||
|
Num32 = 0b0011,
|
||||||
|
Num64 = 0b0100,
|
||||||
|
Num128 = 0b0101,
|
||||||
|
Num256 = 0b0110,
|
||||||
|
Num512 = 0b0111,
|
||||||
|
Num1024 = 0b1000,
|
||||||
|
Num2048 = 0b1001,
|
||||||
|
Num4096 = 0b1010,
|
||||||
|
Num8192 = 0b1011,
|
||||||
|
Num16384 = 0b1100,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for DFTNUM {
|
||||||
|
fn reset() -> Self {
|
||||||
|
DFTNUM::Num2048
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum CTIACON {
|
||||||
|
C1 = 0,
|
||||||
|
C2 = 1 << 0,
|
||||||
|
C4 = 1 << 1,
|
||||||
|
C8 = 1 << 2,
|
||||||
|
C16 = 1 << 3,
|
||||||
|
C32 = 1 << 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for CTIACON {
|
||||||
|
fn reset() -> Self {
|
||||||
|
CTIACON::C1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum RTIACON {
|
||||||
|
R200 = 0b0000,
|
||||||
|
R1k = 0b0001,
|
||||||
|
R5k = 0b0010,
|
||||||
|
R10k = 0b0011,
|
||||||
|
R20k = 0b0100,
|
||||||
|
R40k = 0b0101,
|
||||||
|
R80k = 0b0110,
|
||||||
|
R160k = 0b0111,
|
||||||
|
Open = 0b1111,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for RTIACON {
|
||||||
|
fn reset() -> Self {
|
||||||
|
RTIACON::Open
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum SINC3OSR {
|
||||||
|
R5 = 0b00,
|
||||||
|
R4 = 0b01,
|
||||||
|
R2 = 0b10,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for SINC3OSR {
|
||||||
|
fn reset() -> Self {
|
||||||
|
SINC3OSR::R5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum SINC2OSR {
|
||||||
|
R22 = 0b0000,
|
||||||
|
R44 = 0b0001,
|
||||||
|
R89 = 0b0010,
|
||||||
|
R178 = 0b0011,
|
||||||
|
R267 = 0b0100,
|
||||||
|
R533 = 0b0101,
|
||||||
|
R640 = 0b0110,
|
||||||
|
R667 = 0b0111,
|
||||||
|
R800 = 0b1000,
|
||||||
|
R889 = 0b1001,
|
||||||
|
R1067 = 0b1010,
|
||||||
|
R1333 = 0b1011,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for SINC2OSR {
|
||||||
|
fn reset() -> Self {
|
||||||
|
SINC2OSR::R178
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum ADCSAMPLERATE {
|
||||||
|
R800Hz = 1,
|
||||||
|
R1_6MHz = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resettable for ADCSAMPLERATE {
|
||||||
|
fn reset() -> Self {
|
||||||
|
ADCSAMPLERATE::R1_6MHz
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
// Configuration Register
|
// Configuration Register
|
||||||
// Address 0x00002000, Reset: 0x00080000, Name: AFECON
|
// Address 0x00002000, Reset: 0x00080000, Name: AFECON
|
||||||
@@ -22,30 +258,6 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
// Switch Matrix Configuration Register
|
|
||||||
// Address 0x0000200C, Reset: 0x00000000, Name: SWCON
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
pub struct SWCON: u32 {
|
|
||||||
const T9CON = 1 << 17; // T9 switch // RTIA switch
|
|
||||||
const TMUXCON_MSK = 0b1111 << 12;
|
|
||||||
const TMUXCON_T2 = 0b0010 << 12; // T2 switch
|
|
||||||
const TMUXCON_TR1 = 0b1000 << 12; // TR1 switch
|
|
||||||
const NMUXCON_MSK = 0b1111 << 8;
|
|
||||||
const NMUXCON_N2 = 0b0010 << 8; // N2 switch
|
|
||||||
const NMUXCON_N5 = 0b0101 << 8; // N5 switch
|
|
||||||
const NMUXCON_NR1 = 0b1010 << 8; // NR1 switch
|
|
||||||
const PMUXCON_MSK = 0b1111 << 4;
|
|
||||||
const PMUXCON_PR0 = 0b0001 << 4; // PR0 switch
|
|
||||||
const PMUXCON_P2 = 0b0010 << 4; // P2 switch
|
|
||||||
const PMUXCON_P11 = 0b1011 << 4; // P11 switch
|
|
||||||
const DMUXCON_MSK = 0b1111;
|
|
||||||
const DMUXCON_DR0 = 0b0001; // DR0 switch
|
|
||||||
const DMUXCON_D5 = 0b0101; // D5 switch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
// Waveform Generator Configuration Register
|
// Waveform Generator Configuration Register
|
||||||
// Address 0x00002014, Reset: 0x00000030, Name: WGCON
|
// Address 0x00002014, Reset: 0x00000030, Name: WGCON
|
||||||
@@ -71,6 +283,30 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
// DFT Configuration Register
|
||||||
|
// Address 0x000020D0, Reset: 0x00000090, Name: DFTCON
|
||||||
|
pub struct DFTCON: u32 {
|
||||||
|
const DFTINSEL_SINC2 = 0b00 << 20;
|
||||||
|
const DFTINSEL_GAIN_ANDOFFSET = 0b01 << 20;
|
||||||
|
const ADC_RAW = 0b10 << 20;
|
||||||
|
const DFTNUM_4 = 0b0000 << 4;
|
||||||
|
const DFTNUM_8 = 0b0001 << 4;
|
||||||
|
const DFTNUM_16 = 0b0010 << 4;
|
||||||
|
const DFTNUM_32 = 0b0011 << 4;
|
||||||
|
const DFTNUM_64 = 0b0100 << 4;
|
||||||
|
const DFTNUM_128 = 0b0101 << 4;
|
||||||
|
const DFTNUM_256 = 0b0110 << 4;
|
||||||
|
const DFTNUM_512 = 0b0111 << 4;
|
||||||
|
const DFTNUM_1024 = 0b1000 << 4;
|
||||||
|
const DFTNUM_2048 = 0b1001 << 4;
|
||||||
|
const DFTNUM_4096 = 0b1010 << 4;
|
||||||
|
const DFTNUM_8192 = 0b1011 << 4;
|
||||||
|
const DFTNUM_16384 = 0b1100 << 4;
|
||||||
|
const HANNINGEN = 0b1 << 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
// HIGH POWER AND LOW POWER BUFFER CONTROL REGISTER
|
// HIGH POWER AND LOW POWER BUFFER CONTROL REGISTER
|
||||||
// Address 0x00002180, Reset 0x00000037, Name BEFSENCON
|
// Address 0x00002180, Reset 0x00000037, Name BEFSENCON
|
||||||
|
|||||||
@@ -189,12 +189,12 @@ pub async fn start_impedance_handler(context: SpawnCtx, header: VarHeader, rqst:
|
|||||||
// phase: impedance.phase,
|
// phase: impedance.phase,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
let data = IMPEDANCE_CHANNEL.receive().await;
|
let msg = IMPEDANCE_CHANNEL.receive().await;
|
||||||
|
|
||||||
let msg = Impedance {
|
// let msg = Impedance {
|
||||||
magnitude: data,
|
// magnitude: data,
|
||||||
phase: data,
|
// phase: data,
|
||||||
};
|
// };
|
||||||
|
|
||||||
if sender
|
if sender
|
||||||
.publish::<ImpedanceTopic>(seq.into(), &msg)
|
.publish::<ImpedanceTopic>(seq.into(), &msg)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use bioz_icd_rs::Impedance;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||||
use embassy_sync::channel::Channel;
|
use embassy_sync::channel::Channel;
|
||||||
@@ -8,7 +9,7 @@ use libm::{sinf, cosf};
|
|||||||
use core::f32::consts::PI;
|
use core::f32::consts::PI;
|
||||||
|
|
||||||
pub static IMPEDANCE_TEST: StaticCell<Mutex<ThreadModeRawMutex, ImpedanceTest>> = StaticCell::new();
|
pub static IMPEDANCE_TEST: StaticCell<Mutex<ThreadModeRawMutex, ImpedanceTest>> = StaticCell::new();
|
||||||
pub static IMPEDANCE_CHANNEL: Channel<ThreadModeRawMutex, f32, 2000> = Channel::new();
|
pub static IMPEDANCE_CHANNEL: Channel<ThreadModeRawMutex, Impedance, 2000> = Channel::new();
|
||||||
pub struct ImpedanceTest {
|
pub struct ImpedanceTest {
|
||||||
time: embassy_time::Instant,
|
time: embassy_time::Instant,
|
||||||
pub magnitude: f32,
|
pub magnitude: f32,
|
||||||
|
|||||||
74
src/main.rs
74
src/main.rs
@@ -10,10 +10,13 @@ use embassy_stm32::gpio::{Level, Output, Speed};
|
|||||||
use embassy_stm32::{i2c, spi, Config};
|
use embassy_stm32::{i2c, spi, Config};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
|
|
||||||
use crate::ad5940_registers::{ADCCON, AFECON, SWCON};
|
|
||||||
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
use crate::ad5940::*;
|
||||||
|
use crate::ad5940_registers::*;
|
||||||
|
|
||||||
|
use bioz_icd_rs::Impedance;
|
||||||
|
|
||||||
mod ad5940;
|
mod ad5940;
|
||||||
use ad5940::AD5940;
|
use ad5940::AD5940;
|
||||||
|
|
||||||
@@ -119,24 +122,38 @@ 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
|
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();
|
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 -->
|
let switch_config = SwitchConfig::default()
|
||||||
|
.t9con(T9CON::T9Closed)
|
||||||
|
.tmuxcon(TMUXCON::TR1Closed)
|
||||||
|
.nmuxcon(NMUXCON::NR1Closed)
|
||||||
|
.pmuxcon(PMUXCON::PR0Closed)
|
||||||
|
.dmuxcon(DMUXCON::DR0Closed);
|
||||||
|
ad5940.apply_switch_config(switch_config).await.unwrap();
|
||||||
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 * 750_000).await; // 0.75 second
|
ad5940.sequencer_wait(16 * 102_400).await; // 0.75 second // 0,0512
|
||||||
|
ad5940.sequencer_wait(16*20).await; // 0.75 second // 0,0512
|
||||||
ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
|
ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
|
||||||
|
|
||||||
// Rz
|
// Rz
|
||||||
ad5940.swcon(SWCON::DMUXCON_D5 | SWCON::PMUXCON_P11 | SWCON::NMUXCON_N2 | SWCON::TMUXCON_T2 | SWCON::T9CON).await;
|
let switch_config = SwitchConfig::default()
|
||||||
|
.t9con(T9CON::T9Closed)
|
||||||
|
.tmuxcon(TMUXCON::T2Closed)
|
||||||
|
.nmuxcon(NMUXCON::N2Closed)
|
||||||
|
.pmuxcon(PMUXCON::P11Closed)
|
||||||
|
.dmuxcon(DMUXCON::D5Closed);
|
||||||
|
ad5940.apply_switch_config(switch_config).await.unwrap();
|
||||||
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 * 750_000).await; // 0.75 second
|
ad5940.sequencer_wait(16 * 102_400).await; // 0.75 second
|
||||||
|
ad5940.sequencer_wait(16*20).await; // 0.75 second // 0,0512
|
||||||
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
|
||||||
@@ -161,23 +178,6 @@ async fn main(spawner: Spawner) {
|
|||||||
// Green led task
|
// Green led task
|
||||||
// spawner.must_spawn(green_led(led));
|
// spawner.must_spawn(green_led(led));
|
||||||
|
|
||||||
// ad5940.sequencer_trigger(0).await;
|
|
||||||
|
|
||||||
// Set inputs
|
|
||||||
// ad5940.write_reg(ad5940::Register::ADCCON, 0b00101 << 8 | 0b011001).await.unwrap();
|
|
||||||
// ad5940.write_reg(ad5940::Register::ADCCON, ADCCON::MUXSELN_TIAN.bits() | ADCCON::MUXSELP_TIAP.bits()).await.unwrap();
|
|
||||||
|
|
||||||
// ad5940.wgfcw(10).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();
|
|
||||||
// ad5940.swcon(SWCON::DMUXCON_D5 | SWCON::PMUXCON_P11 | SWCON::NMUXCON_N2 | SWCON::TMUXCON_T2 | SWCON::T9CON).await;
|
|
||||||
// ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN | AFECON::ADCCONVEN, true).await;
|
|
||||||
|
|
||||||
ad5940.write_reg(ad5940::Register::ADCFILTERCON, 0x00000301 | 1 << 4).await.unwrap();
|
|
||||||
|
|
||||||
ad5940.write_reg(ad5940::Register::HSRTIACON, 0b010000 << 5 | 0b0010).await.unwrap();
|
|
||||||
|
|
||||||
let mut counter = 0;
|
|
||||||
loop {
|
loop {
|
||||||
// Read chip id
|
// Read chip id
|
||||||
// let chip_id = ad5940.get_chipid().await;
|
// let chip_id = ad5940.get_chipid().await;
|
||||||
@@ -196,11 +196,12 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
// info!("Mainloop still running!");
|
// info!("Mainloop still running!");
|
||||||
|
|
||||||
Timer::after_millis(2500).await;
|
Timer::after_micros((102_400.0 * 3.0) as u64).await;
|
||||||
|
|
||||||
let count = ad5940.get_fifo_count().await.unwrap();
|
let count = ad5940.get_fifo_count().await.unwrap();
|
||||||
info!("FIFOCNTSTA: {}", count);
|
info!("FIFOCNTSTA: {}", count);
|
||||||
|
|
||||||
|
|
||||||
// for _ in 0..count {
|
// for _ in 0..count {
|
||||||
// let mut data = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
// let mut data = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
||||||
|
|
||||||
@@ -220,18 +221,25 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
// info!("Counter: {}", counter);
|
// info!("Counter: {}", counter);
|
||||||
|
|
||||||
let mut data: [u32; 4] = [0; 4];
|
if count >= 4 {
|
||||||
data[0] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
let mut data: [u32; 4] = [0; 4];
|
||||||
data[1] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
data[0] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
||||||
data[2] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
data[1] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
||||||
data[3] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
data[2] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
||||||
|
data[3] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
|
||||||
|
|
||||||
let result = calculate_impedance(data);
|
let result = calculate_impedance(data);
|
||||||
|
|
||||||
// You’ll need to implement your own logging or send this over serial in embedded
|
// You’ll need to implement your own logging or send this over serial in embedded
|
||||||
info!("Impedance: Magnitude = {} Ω, Phase = {} rad", result.magnitude, result.phase);
|
info!("Impedance: Magnitude = {} Ω, Phase = {} rad", result.magnitude, result.phase);
|
||||||
|
|
||||||
|
let data = Impedance {
|
||||||
|
magnitude: result.magnitude,
|
||||||
|
phase: result.phase,
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPEDANCE_CHANNEL.try_send(data).ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user