2020-03-12 07:43:11 +08:00
use core ::ops ::{ Deref , DerefMut } ;
2020-03-12 06:16:48 +08:00
use byteorder ::{ BigEndian , ByteOrder } ;
use bit_field ::BitField ;
use super ::* ;
pub trait Register {
type Data : RegisterData ;
fn address ( & self ) -> u8 ;
}
2020-03-21 06:19:31 +08:00
pub trait RegisterData : Clone + Deref < Target = [ u8 ] > + DerefMut {
2020-03-12 06:16:48 +08:00
fn empty ( ) -> Self ;
}
macro_rules ! def_reg {
( $Reg : ident , $reg : ident , $addr : expr , $size : expr ) = > {
/// 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
2020-03-21 06:19:31 +08:00
#[ derive(Clone) ]
2020-03-12 06:16:48 +08:00
pub struct Data ( pub [ u8 ; $size ] ) ;
impl super ::RegisterData for Data {
/// Generate zeroed register contents
fn empty ( ) -> Self {
Data ( [ 0 ; $size ] )
}
2020-03-12 07:43:11 +08:00
}
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 ] {
2020-03-12 06:16:48 +08:00
& mut self . 0
}
}
}
} ;
( $Reg : ident , u8 , $reg : ident , $addr : expr , $size : expr ) = > {
pub struct $Reg { pub index : u8 , }
impl Register for $Reg {
type Data = $reg ::Data ;
fn address ( & self ) -> u8 {
$addr + self . index
}
}
mod $reg {
2020-03-21 06:19:31 +08:00
#[ derive(Clone) ]
2020-03-12 06:16:48 +08:00
pub struct Data ( pub [ u8 ; $size ] ) ;
impl super ::RegisterData for Data {
fn empty ( ) -> Self {
Data ( [ 0 ; $size ] )
}
2020-03-12 07:43:11 +08:00
}
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 ] {
2020-03-12 06:16:48 +08:00
& mut self . 0
}
}
}
}
}
macro_rules ! reg_bit {
( $getter : ident , $byte : expr , $bit : expr , $doc : expr ) = > {
#[ allow(unused) ]
#[ doc = $doc ]
pub fn $getter ( & self ) -> bool {
self . 0 [ $byte ] . get_bit ( $bit )
}
} ;
( $getter : ident , $setter : ident , $byte : expr , $bit : expr , $doc : expr ) = > {
#[ 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 {
( $getter : ident , $byte : expr , $bits : expr , $doc : expr ) = > {
#[ allow(unused) ]
#[ doc = $doc ]
pub fn $getter ( & self ) -> u8 {
self . 0 [ $byte ] . get_bits ( $bits )
}
} ;
( $getter : ident , $setter : ident , $byte : expr , $bits : expr , $doc : expr ) = > {
#[ 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 ) ;
}
} ;
( $getter : ident , $byte : expr , $bits : expr , $ty : ty , $doc : expr ) = > {
#[ allow(unused) ]
#[ doc = $doc ]
pub fn $getter ( & self ) -> $ty {
self . 0 [ $byte ] . get_bits ( $bits ) as $ty
}
} ;
( $getter : ident , $setter : ident , $byte : expr , $bits : expr , $ty : ty , $doc : expr ) = > {
#[ 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 {
! self . not_ready ( )
}
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 " ) ;
2020-03-20 07:45:10 +08:00
reg_bit! ( reg_error , 0 , 4 , " Register error " ) ;
}
def_reg! ( AdcMode , adc_mode , 0x01 , 2 ) ;
impl adc_mode ::Data {
2020-03-21 06:51:19 +08:00
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 " ) ;
2020-03-20 07:45:10 +08:00
reg_bit! ( ref_en , set_ref_en , 0 , 7 , " Enable internal reference, output buffered 2.5 V to REFOUT " ) ;
2020-03-21 06:51:19 +08:00
reg_bits! ( clockset , set_clocksel , 1 , 2 ..= 3 , " Clock source " ) ;
reg_bits! ( mode , set_mode , 1 , 4 ..= 6 , Mode , " Operating mode " ) ;
2020-03-12 06:16:48 +08:00
}
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 {
2020-03-20 06:39:06 +08:00
pub fn data ( & self ) -> u32 {
( u32 ::from ( self . 0 [ 0 ] ) < < 16 ) |
( u32 ::from ( self . 0 [ 1 ] ) < < 8 ) |
u32 ::from ( self . 0 [ 2 ] )
2020-03-12 06:16:48 +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 {
( ( self . 0 [ 0 ] . get_bits ( 0 ..= 1 ) < < 3 ) |
self . 0 [ 1 ] . get_bits ( 5 ..= 7 ) ) . into ( )
}
/// 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 ) ;
}
reg_bits! ( a_in_neg , set_a_in_neg , 1 , 0 ..= 4 , Input ,
" Which input is connected to negative input of this channel " ) ;
}
def_reg! ( SetupCon , u8 , setup_con , 0x20 , 2 ) ;
impl setup_con ::Data {
reg_bit! ( bipolar , set_bipolar , 0 , 4 , " Unipolar (`false`) or bipolar (`true`) coded output " ) ;
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 " ) ;
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 " ) ;
}
def_reg! ( FiltCon , u8 , filt_con , 0x28 , 2 ) ;
impl filt_con ::Data {
reg_bit! ( sinc3_map , 0 , 7 , " If set, mapping of filter register changes to directly program the decimation rate of the sinc3 filter " ) ;
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 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 , " Output data rate " ) ;
}
def_reg! ( Offset , u8 , offset , 0x30 , 3 ) ;
impl offset ::Data {
#[ allow(unused) ]
pub fn offset ( & self ) -> u32 {
( u32 ::from ( self . 0 [ 0 ] ) < < 16 ) |
( u32 ::from ( self . 0 [ 1 ] ) < < 8 ) |
u32 ::from ( self . 0 [ 2 ] )
}
#[ 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 {
( u32 ::from ( self . 0 [ 0 ] ) < < 16 ) |
( u32 ::from ( self . 0 [ 1 ] ) < < 8 ) |
u32 ::from ( self . 0 [ 2 ] )
}
#[ 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 ;
}
}