2024-01-16 16:18:39 +08:00
|
|
|
use core::ops::{Deref, DerefMut};
|
2024-04-23 17:09:26 +08:00
|
|
|
|
2024-01-16 16:18:39 +08:00
|
|
|
use bit_field::BitField;
|
2024-04-23 17:09:26 +08:00
|
|
|
use byteorder::{BigEndian, ByteOrder};
|
2024-01-16 16:18:39 +08:00
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
pub trait Register {
|
|
|
|
type Data: RegisterData;
|
|
|
|
fn address(&self) -> u8;
|
|
|
|
}
|
|
|
|
|
2024-04-23 17:09:26 +08:00
|
|
|
pub trait RegisterData: Clone + Deref<Target = [u8]> + DerefMut {
|
2024-01-16 16:18:39 +08:00
|
|
|
fn empty() -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! def_reg {
|
2024-04-23 17:09:26 +08:00
|
|
|
($Reg:ident, $reg:ident, $addr:expr, $size:expr) => {
|
2024-01-16 16:18:39 +08:00
|
|
|
/// AD7172 register
|
|
|
|
pub struct $Reg;
|
|
|
|
impl Register for $Reg {
|
|
|
|
/// Register contents
|
|
|
|
type Data = $reg::Data;
|
|
|
|
/// Register address
|
|
|
|
fn address(&self) -> u8 {
|
|
|
|
$addr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mod $reg {
|
|
|
|
/// Register contents
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Data(pub [u8; $size]);
|
|
|
|
impl super::RegisterData for Data {
|
|
|
|
/// Generate zeroed register contents
|
|
|
|
fn empty() -> Self {
|
|
|
|
Data([0; $size])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl core::ops::Deref for Data {
|
|
|
|
type Target = [u8];
|
|
|
|
fn deref(&self) -> &[u8] {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl core::ops::DerefMut for Data {
|
|
|
|
fn deref_mut(&mut self) -> &mut [u8] {
|
|
|
|
&mut self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
($Reg:ident,u8, $reg:ident, $addr:expr, $size:expr) => {
|
|
|
|
pub struct $Reg {
|
|
|
|
pub index: u8,
|
|
|
|
}
|
2024-01-16 16:18:39 +08:00
|
|
|
impl Register for $Reg {
|
|
|
|
type Data = $reg::Data;
|
|
|
|
fn address(&self) -> u8 {
|
|
|
|
$addr + self.index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mod $reg {
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Data(pub [u8; $size]);
|
|
|
|
impl super::RegisterData for Data {
|
|
|
|
fn empty() -> Self {
|
|
|
|
Data([0; $size])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl core::ops::Deref for Data {
|
|
|
|
type Target = [u8];
|
|
|
|
fn deref(&self) -> &[u8] {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl core::ops::DerefMut for Data {
|
|
|
|
fn deref_mut(&mut self) -> &mut [u8] {
|
|
|
|
&mut self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-04-23 17:09:26 +08:00
|
|
|
};
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! reg_bit {
|
2024-04-23 17:09:26 +08:00
|
|
|
($getter:ident, $byte:expr, $bit:expr, $doc:expr) => {
|
2024-01-16 16:18:39 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $getter(&self) -> bool {
|
|
|
|
self.0[$byte].get_bit($bit)
|
|
|
|
}
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
($getter:ident, $setter:ident, $byte:expr, $bit:expr, $doc:expr) => {
|
2024-01-16 16:18:39 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $getter(&self) -> bool {
|
|
|
|
self.0[$byte].get_bit($bit)
|
|
|
|
}
|
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $setter(&mut self, value: bool) {
|
|
|
|
self.0[$byte].set_bit($bit, value);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! reg_bits {
|
2024-04-23 17:09:26 +08:00
|
|
|
($getter:ident, $byte:expr, $bits:expr, $doc:expr) => {
|
2024-01-16 16:18:39 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $getter(&self) -> u8 {
|
|
|
|
self.0[$byte].get_bits($bits)
|
|
|
|
}
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
($getter:ident, $setter:ident, $byte:expr, $bits:expr, $doc:expr) => {
|
2024-01-16 16:18:39 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $getter(&self) -> u8 {
|
|
|
|
self.0[$byte].get_bits($bits)
|
|
|
|
}
|
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $setter(&mut self, value: u8) {
|
|
|
|
self.0[$byte].set_bits($bits, value);
|
|
|
|
}
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
($getter:ident, $byte:expr, $bits:expr, $ty:ty, $doc:expr) => {
|
2024-01-16 16:18:39 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $getter(&self) -> $ty {
|
|
|
|
self.0[$byte].get_bits($bits) as $ty
|
|
|
|
}
|
|
|
|
};
|
2024-04-23 17:09:26 +08:00
|
|
|
($getter:ident, $setter:ident, $byte:expr, $bits:expr, $ty:ty, $doc:expr) => {
|
2024-01-16 16:18:39 +08:00
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $getter(&self) -> $ty {
|
|
|
|
self.0[$byte].get_bits($bits).into()
|
|
|
|
}
|
|
|
|
#[allow(unused)]
|
|
|
|
#[doc = $doc]
|
|
|
|
pub fn $setter(&mut self, value: $ty) {
|
|
|
|
self.0[$byte].set_bits($bits, value as u8);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(Status, status, 0x00, 1);
|
|
|
|
impl status::Data {
|
|
|
|
/// Is there new data to read?
|
|
|
|
pub fn ready(&self) -> bool {
|
2024-04-23 17:09:26 +08:00
|
|
|
!self.not_ready()
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
reg_bit!(not_ready, 0, 7, "No data ready indicator");
|
|
|
|
reg_bits!(channel, 0, 0..=1, "Channel for which data is ready");
|
|
|
|
reg_bit!(adc_error, 0, 6, "ADC error");
|
|
|
|
reg_bit!(crc_error, 0, 5, "SPI CRC error");
|
|
|
|
reg_bit!(reg_error, 0, 4, "Register error");
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(AdcMode, adc_mode, 0x01, 2);
|
|
|
|
impl adc_mode::Data {
|
|
|
|
reg_bits!(delay, set_delay, 0, 0..=2, "Delay after channel switch");
|
|
|
|
reg_bit!(sing_cyc, set_sing_cyc, 0, 5, "Can only used with single channel");
|
|
|
|
reg_bit!(hide_delay, set_hide_delay, 0, 6, "Hide delay");
|
2024-04-23 17:09:26 +08:00
|
|
|
reg_bit!(
|
|
|
|
ref_en,
|
|
|
|
set_ref_en,
|
|
|
|
0,
|
|
|
|
7,
|
|
|
|
"Enable internal reference, output buffered 2.5 V to REFOUT"
|
|
|
|
);
|
2024-01-16 16:18:39 +08:00
|
|
|
reg_bits!(clockset, set_clocksel, 1, 2..=3, "Clock source");
|
|
|
|
reg_bits!(mode, set_mode, 1, 4..=6, Mode, "Operating mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(IfMode, if_mode, 0x02, 2);
|
|
|
|
impl if_mode::Data {
|
|
|
|
reg_bits!(crc, set_crc, 1, 2..=3, ChecksumMode, "SPI checksum mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(Data, data, 0x04, 3);
|
|
|
|
impl data::Data {
|
|
|
|
pub fn data(&self) -> u32 {
|
2024-04-23 17:09:26 +08:00
|
|
|
(u32::from(self.0[0]) << 16) | (u32::from(self.0[1]) << 8) | u32::from(self.0[2])
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(GpioCon, gpio_con, 0x06, 2);
|
|
|
|
impl gpio_con::Data {
|
|
|
|
reg_bit!(sync_en, set_sync_en, 0, 3, "Enables the SYNC/ERROR pin as a sync input");
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(Id, id, 0x07, 2);
|
|
|
|
impl id::Data {
|
|
|
|
pub fn id(&self) -> u16 {
|
|
|
|
BigEndian::read_u16(&self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(Channel, u8, channel, 0x10, 2);
|
|
|
|
impl channel::Data {
|
|
|
|
reg_bit!(enabled, set_enabled, 0, 7, "Channel enabled");
|
|
|
|
reg_bits!(setup, set_setup, 0, 4..=5, "Setup number");
|
|
|
|
|
|
|
|
/// Which input is connected to positive input of this channel
|
|
|
|
#[allow(unused)]
|
|
|
|
pub fn a_in_pos(&self) -> Input {
|
2024-04-23 17:09:26 +08:00
|
|
|
((self.0[0].get_bits(0..=1) << 3) | self.0[1].get_bits(5..=7)).into()
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
/// Set which input is connected to positive input of this channel
|
|
|
|
#[allow(unused)]
|
|
|
|
pub fn set_a_in_pos(&mut self, value: Input) {
|
|
|
|
let value = value as u8;
|
|
|
|
self.0[0].set_bits(0..=1, value >> 3);
|
|
|
|
self.0[1].set_bits(5..=7, value & 0x7);
|
|
|
|
}
|
2024-04-23 17:09:26 +08:00
|
|
|
reg_bits!(
|
|
|
|
a_in_neg,
|
|
|
|
set_a_in_neg,
|
|
|
|
1,
|
|
|
|
0..=4,
|
|
|
|
Input,
|
|
|
|
"Which input is connected to negative input of this channel"
|
|
|
|
);
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(SetupCon, u8, setup_con, 0x20, 2);
|
|
|
|
impl setup_con::Data {
|
2024-04-23 17:09:26 +08:00
|
|
|
reg_bit!(
|
|
|
|
bipolar,
|
|
|
|
set_bipolar,
|
|
|
|
0,
|
|
|
|
4,
|
|
|
|
"Unipolar (`false`) or bipolar (`true`) coded output"
|
|
|
|
);
|
2024-01-16 16:18:39 +08:00
|
|
|
reg_bit!(refbuf_pos, set_refbuf_pos, 0, 3, "Enable REF+ input buffer");
|
|
|
|
reg_bit!(refbuf_neg, set_refbuf_neg, 0, 2, "Enable REF- input buffer");
|
|
|
|
reg_bit!(ainbuf_pos, set_ainbuf_pos, 0, 1, "Enable AIN+ input buffer");
|
|
|
|
reg_bit!(ainbuf_neg, set_ainbuf_neg, 0, 0, "Enable AIN- input buffer");
|
2024-04-23 17:09:26 +08:00
|
|
|
reg_bit!(
|
|
|
|
burnout_en,
|
|
|
|
1,
|
|
|
|
7,
|
|
|
|
"enables a 10 µA current source on the positive analog input selected and a 10 µA current sink on the \
|
|
|
|
negative analog input selected"
|
|
|
|
);
|
|
|
|
reg_bits!(
|
|
|
|
ref_sel,
|
|
|
|
set_ref_sel,
|
|
|
|
1,
|
|
|
|
4..=5,
|
|
|
|
RefSource,
|
|
|
|
"Select reference source for conversion"
|
|
|
|
);
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(FiltCon, u8, filt_con, 0x28, 2);
|
|
|
|
impl filt_con::Data {
|
2024-04-23 17:09:26 +08:00
|
|
|
reg_bit!(
|
|
|
|
sinc3_map,
|
|
|
|
set_sinc3_map,
|
|
|
|
0,
|
|
|
|
7,
|
|
|
|
"If set, Sinc3 Filter's notch frequency rejection position can be fine tuned with FiltCon[14:0]. Best to be \
|
|
|
|
used with Single Channel Enabled"
|
|
|
|
);
|
|
|
|
reg_bit!(
|
|
|
|
enh_filt_en,
|
|
|
|
set_enh_filt_en,
|
|
|
|
0,
|
|
|
|
3,
|
|
|
|
"Enable postfilters for enhanced 50Hz and 60Hz rejection"
|
|
|
|
);
|
|
|
|
reg_bits!(
|
|
|
|
enh_filt,
|
|
|
|
set_enh_filt,
|
|
|
|
0,
|
|
|
|
0..=2,
|
|
|
|
PostFilter,
|
|
|
|
"Select postfilters output data rate for enhanced 50Hz and 60Hz rejection"
|
|
|
|
);
|
|
|
|
reg_bits!(
|
|
|
|
order,
|
|
|
|
set_order,
|
|
|
|
1,
|
|
|
|
5..=6,
|
|
|
|
DigitalFilterOrder,
|
|
|
|
"order of the digital filter that processes the modulator data"
|
|
|
|
);
|
|
|
|
reg_bits!(
|
|
|
|
odr,
|
|
|
|
set_odr,
|
|
|
|
1,
|
|
|
|
0..=4,
|
|
|
|
SingleChODR,
|
|
|
|
"Output data rate for normal Sin5c + Sinc1 and Sinc3 filter with SING_CYC = 0 and Single Channel Enabled"
|
|
|
|
);
|
|
|
|
reg_bits!(
|
|
|
|
sinc3_map_fine_odr_msb,
|
|
|
|
set_sinc3_map_fine_odr_msb,
|
|
|
|
0,
|
|
|
|
0..=6,
|
|
|
|
"MSB Byte Sinc3 Fine Output Config"
|
|
|
|
);
|
|
|
|
reg_bits!(
|
|
|
|
sinc3_map_fine_odr_lsb,
|
|
|
|
set_sinc3_map_fine_odr_lsb,
|
|
|
|
1,
|
|
|
|
0..=7,
|
|
|
|
"LSB Byte Sinc3 Fine Output Config"
|
|
|
|
);
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(Offset, u8, offset, 0x30, 3);
|
|
|
|
impl offset::Data {
|
|
|
|
#[allow(unused)]
|
|
|
|
pub fn offset(&self) -> u32 {
|
2024-04-23 17:09:26 +08:00
|
|
|
(u32::from(self.0[0]) << 16) | (u32::from(self.0[1]) << 8) | u32::from(self.0[2])
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
#[allow(unused)]
|
|
|
|
pub fn set_offset(&mut self, value: u32) {
|
|
|
|
self.0[0] = (value >> 16) as u8;
|
|
|
|
self.0[1] = (value >> 8) as u8;
|
|
|
|
self.0[2] = value as u8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def_reg!(Gain, u8, gain, 0x38, 3);
|
|
|
|
impl gain::Data {
|
|
|
|
#[allow(unused)]
|
|
|
|
pub fn gain(&self) -> u32 {
|
2024-04-23 17:09:26 +08:00
|
|
|
(u32::from(self.0[0]) << 16) | (u32::from(self.0[1]) << 8) | u32::from(self.0[2])
|
2024-01-16 16:18:39 +08:00
|
|
|
}
|
|
|
|
#[allow(unused)]
|
|
|
|
pub fn set_gain(&mut self, value: u32) {
|
|
|
|
self.0[0] = (value >> 16) as u8;
|
|
|
|
self.0[1] = (value >> 8) as u8;
|
|
|
|
self.0[2] = value as u8;
|
|
|
|
}
|
|
|
|
}
|