extern crate num as num_renamed;
use crate::create_register;
use crate::fields::*;
use num_renamed::FromPrimitive;
use num_renamed::ToPrimitive;
use paste::paste;
pub mod helpers {
#[inline]
pub fn get_mask(start_index: u8, width: u8) -> u8 {
((1u8 << width) - 1u8) << start_index
}
}
pub struct Register;
impl Register {
pub const ALS_CONTR: u8 = 0x80;
pub const ALS_MEAS_RATE: u8 = 0x85;
pub const PART_ID: u8 = 0x86;
pub const MANUFAC_ID: u8 = 0x87;
pub const ALS_DATA_CH1_0: u8 = 0x88;
pub const ALS_DATA_CH1_1: u8 = 0x89;
pub const ALS_DATA_CH0_0: u8 = 0x8A;
pub const ALS_DATA_CH0_1: u8 = 0x8B;
pub const ALS_STATUS: u8 = 0x8C;
pub const INTERRUPT: u8 = 0x8F;
pub const ALS_THRES_UP_0: u8 = 0x97;
pub const ALS_THRES_UP_1: u8 = 0x98;
pub const ALS_THRES_LOW_0: u8 = 0x99;
pub const ALS_THRES_LOW_1: u8 = 0x9A;
pub const INTERRUPT_PERSIST: u8 = 0x9E;
}
pub struct Field<T> {
pub start_index: u8,
pub width: u8,
pub value: T,
}
impl<T> Field<T>
where
T: ToPrimitive,
{
pub fn bits(self) -> u8 {
let mask: u8 = self::helpers::get_mask(self.start_index, self.width);
let val: u8 = num_renamed::ToPrimitive::to_u8(&self.value).unwrap();
let tmp: u8 = (val << self.start_index) & mask;
tmp
}
}
#[macro_export]
macro_rules! create_register {
($reg_name:ident, {$($element: ident: $ty: ty),*}) => {
pub struct $reg_name { $(pub $element: Field<$ty>),* }
paste! {
impl $reg_name {
pub fn value(self) -> u8 {
let mut temp: u8 = 0x00;
$(
temp |= self.$element.bits();
)*
temp
}
$(
pub fn [<with_ $element>] (self, paste!{[<new_ $element>]}: $ty) -> Self {
let mut tmp = $reg_name{..self};
tmp.$element.value = paste!{[<new_ $element>]};
tmp
}
)*
}
}
paste! {
impl From<u8> for $reg_name {
fn from(val: u8) -> Self {
let new_reg = $reg_name::default();
$(
let [<$element _mask>] = self::helpers::get_mask(new_reg.$element.start_index, new_reg.$element.width);
let [<$element _val>] = FromPrimitive::from_u8( (val & [<$element _mask>]) >> new_reg.$element.start_index ).unwrap();
let new_reg = new_reg.[<with_ $element>]([<$element _val>]);
)*
new_reg
}
}
}
}
}
create_register!(ControlRegister, {mode: Mode, gain: Gain, sw_reset: ResetStatus});
impl Default for ControlRegister {
fn default() -> Self {
ControlRegister {
mode: Field {
start_index: 0,
width: 1,
value: Mode::STANDBY,
},
gain: Field {
start_index: 2,
width: 3,
value: Gain::Gain1x,
},
sw_reset: Field {
start_index: 1,
width: 1,
value: ResetStatus::Idle,
},
}
}
}
create_register!(MeasRateRegister, {measurement_rate: MeasurementRate, integration_time: IntegrationTime});
impl Default for MeasRateRegister {
fn default() -> Self {
MeasRateRegister {
measurement_rate: Field {
start_index: 0,
width: 3,
value: MeasurementRate::Ms500,
},
integration_time: Field {
start_index: 3,
width: 3,
value: IntegrationTime::Ms100,
},
}
}
}
create_register!(InterruptRegister, {interrupt_mode: ISRMode, interrupt_polarity: ISRPol});
impl Default for InterruptRegister {
fn default() -> Self {
InterruptRegister {
interrupt_mode: Field {
start_index: 1,
width: 1,
value: ISRMode::INACTIVE,
},
interrupt_polarity: Field {
start_index: 2,
width: 1,
value: ISRPol::ActiveLow,
},
}
}
}
create_register!(StatusRegister, {data_valid: DataValidity, gain: Gain, int_status: IntStatus, data_status: DataStatus});
impl Default for StatusRegister {
fn default() -> Self {
StatusRegister {
data_valid: Field {
start_index: 7,
width: 1,
value: DataValidity::DataValid,
},
gain: Field {
start_index: 4,
width: 3,
value: Gain::Gain1x,
},
int_status: Field {
start_index: 3,
width: 1,
value: IntStatus::Inactive,
},
data_status: Field {
start_index: 2,
width: 1,
value: DataStatus::Old,
},
}
}
}