Cache status value in the driver

pull/4/head
Diego Barrios Romero 2018-10-31 07:52:15 +01:00
parent d18de45f95
commit 73ca2703c9
4 changed files with 50 additions and 19 deletions

View File

@ -33,24 +33,20 @@ where
}
/// Enable the 32kHz output.
///
/// (Does not alter the device register if already enabled).
pub fn enable_32khz_output(&mut self) -> Result<(), Error<E>> {
let status = self.iface.read_register(Register::STATUS)?;
if (status & BitFlags::EN32KHZ) == 0 {
self.iface.write_register(Register::STATUS, status | BitFlags::EN32KHZ)?;
}
// avoid clearing alarm flags
let status = self.status | BitFlags::EN32KHZ | BitFlags::ALARM2F | BitFlags::ALARM1F;
self.iface.write_register(Register::STATUS, status)?;
self.status = status;
Ok(())
}
/// Disable the 32kHz output.
///
/// (Does not alter the device register if already disabled).
pub fn disable_32khz_output(&mut self) -> Result<(), Error<E>> {
let status = self.iface.read_register(Register::STATUS)?;
if (status & BitFlags::EN32KHZ) != 0 {
self.iface.write_register(Register::STATUS, status & !BitFlags::EN32KHZ)?;
}
// avoid clearing alarm flags
let status = self.status & !BitFlags::EN32KHZ | BitFlags::ALARM2F | BitFlags::ALARM1F;
self.iface.write_register(Register::STATUS, status)?;
self.status = status;
Ok(())
}

View File

@ -401,9 +401,12 @@ impl BitFlags {
const RS2 : u8 = 0b0001_0000;
const RS1 : u8 = 0b0000_1000;
const INTCN : u8 = 0b0000_0100;
const BUSY : u8 = 0b0000_0100;
const EN32KHZ : u8 = 0b0000_1000;
const OSC_STOP : u8 = 0b1000_0000;
const BB32KHZ : u8 = 0b0100_0000;
const EN32KHZ : u8 = 0b0000_1000;
const BUSY : u8 = 0b0000_0100;
const ALARM2F : u8 = 0b0000_0010;
const ALARM1F : u8 = 0b0000_0001;
}
const DEVICE_ADDRESS : u8 = 0b110_1000;
@ -426,6 +429,7 @@ use interface::{ I2cInterface, SpiInterface };
pub struct Ds323x<DI, IC> {
iface: DI,
control: u8,
status : u8,
_ic: PhantomData<IC>
}
@ -435,11 +439,13 @@ where
{
/// Create a new instance of the DS3231 device.
pub fn new_ds3231(i2c: I2C) -> Self {
const STATUS_POR_VALUE : u8 = BitFlags::OSC_STOP | BitFlags::EN32KHZ;
Ds323x {
iface: I2cInterface {
i2c,
},
control: CONTROL_POR_VALUE,
status: STATUS_POR_VALUE,
_ic: PhantomData
}
}
@ -456,11 +462,13 @@ where
{
/// Create a new instance of the DS3232 device.
pub fn new_ds3232(i2c: I2C) -> Self {
const STATUS_POR_VALUE : u8 = BitFlags::OSC_STOP | BitFlags::BB32KHZ | BitFlags::EN32KHZ;
Ds323x {
iface: I2cInterface {
i2c,
},
control: CONTROL_POR_VALUE,
status: STATUS_POR_VALUE,
_ic: PhantomData
}
}
@ -478,12 +486,14 @@ where
{
/// Create a new instance.
pub fn new_ds3234(spi: SPI, chip_select: CS) -> Self {
const STATUS_POR_VALUE : u8 = BitFlags::OSC_STOP | BitFlags::BB32KHZ | BitFlags::EN32KHZ;
Ds323x {
iface: SpiInterface {
spi,
cs: chip_select
},
control: CONTROL_POR_VALUE,
status: STATUS_POR_VALUE,
_ic: PhantomData
}
}

View File

@ -7,6 +7,10 @@ use hal::spi::{ Mock as SpiMock, Transaction as SpiTrans };
pub const DEVICE_ADDRESS : u8 = 0b110_1000;
#[allow(unused)]
pub const CONTROL_POR_VALUE: u8 = 0b0001_1100;
#[allow(unused)]
pub const DS3231_POR_STATUS: u8 = BitFlags::OSC_STOP | BitFlags::EN32KHZ;
#[allow(unused)]
pub const DS323X_POR_STATUS: u8 = BitFlags::OSC_STOP | BitFlags::BB32KHZ | BitFlags::EN32KHZ;
pub struct Register;
@ -34,9 +38,12 @@ impl BitFlags {
pub const RS2 : u8 = 0b0001_0000;
pub const RS1 : u8 = 0b0000_1000;
pub const INTCN : u8 = 0b0000_0100;
pub const BUSY : u8 = 0b0000_0100;
pub const EN32KHZ : u8 = 0b0000_1000;
pub const OSC_STOP : u8 = 0b1000_0000;
pub const BB32KHZ : u8 = 0b0100_0000;
pub const EN32KHZ : u8 = 0b0000_1000;
pub const BUSY : u8 = 0b0000_0100;
pub const ALARM2F : u8 = 0b0000_0010;
pub const ALARM1F : u8 = 0b0000_0001;
}
pub struct DummyOutputPin;

View File

@ -10,7 +10,8 @@ use ds323x::SqWFreq;
mod common;
use common::{ DEVICE_ADDRESS as DEV_ADDR, Register, new_ds3231,
new_ds3232, new_ds3234, destroy_ds3231, destroy_ds3232,
destroy_ds3234, BitFlags as BF, CONTROL_POR_VALUE };
destroy_ds3234, BitFlags as BF, CONTROL_POR_VALUE,
DS3231_POR_STATUS, DS323X_POR_STATUS };
macro_rules! call_triple_test {
($name:ident, $method:ident, $i2c_transactions:expr, $spi_transactions:expr) => {
@ -31,6 +32,19 @@ macro_rules! call_method_test {
};
}
macro_rules! call_method_status_test {
($name:ident, $method:ident, $value_ds3231:expr, $value_ds323x:expr) => {
mod $name {
use super::*;
call_test!(can_call_ds3231, $method, new_ds3231, destroy_ds3231,
[ I2cTrans::write(DEV_ADDR, vec![Register::STATUS, $value_ds3231]) ]);
call_test!(can_call_ds3232, $method, new_ds3232, destroy_ds3232,
[ I2cTrans::write(DEV_ADDR, vec![Register::STATUS, $value_ds323x]) ]);
call_test!(can_call_ds3234, $method, new_ds3234, destroy_ds3234,
[ SpiTrans::write(vec![Register::STATUS + 0x80, $value_ds323x]) ]);
}
};
}
macro_rules! change_if_necessary_test {
($name:ident, $method:ident, $register:ident, $value_enabled:expr, $value_disabled:expr) => {
@ -52,8 +66,12 @@ macro_rules! change_if_necessary_test {
call_method_test!(enable, enable, CONTROL, CONTROL_POR_VALUE & !BF::EOSC);
call_method_test!(disable, disable, CONTROL, CONTROL_POR_VALUE | BF::EOSC);
change_if_necessary_test!(en_32khz_out, enable_32khz_output, STATUS, BF::EN32KHZ, 0);
change_if_necessary_test!(dis_32khz_out, disable_32khz_output, STATUS, 0xFF & !BF::EN32KHZ, 0xFF);
call_method_status_test!(en_32khz_out, enable_32khz_output,
DS3231_POR_STATUS | BF::EN32KHZ | BF::ALARM2F | BF::ALARM1F,
DS323X_POR_STATUS | BF::EN32KHZ | BF::ALARM2F | BF::ALARM1F);
call_method_status_test!(dis_32khz_out, disable_32khz_output,
DS3231_POR_STATUS & !BF::EN32KHZ | BF::ALARM2F | BF::ALARM1F,
DS323X_POR_STATUS & !BF::EN32KHZ | BF::ALARM2F | BF::ALARM1F);
change_if_necessary_test!(clr_stop, clear_has_been_stopped_flag, STATUS, 0xFF & !BF::OSC_STOP, 0xFF);
change_if_necessary_test!(conv_temp, convert_temperature, CONTROL, CONTROL_POR_VALUE | BF::TEMP_CONV, CONTROL_POR_VALUE & !BF::TEMP_CONV);