diff --git a/src/ds323x/configuration.rs b/src/ds323x/configuration.rs index d0b12c0..7973f9e 100644 --- a/src/ds323x/configuration.rs +++ b/src/ds323x/configuration.rs @@ -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> { - 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> { - 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(()) } diff --git a/src/lib.rs b/src/lib.rs index 56da0e1..8f8e292 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { iface: DI, control: u8, + status : u8, _ic: PhantomData } @@ -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 } } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 07509ad..43c876d 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -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; diff --git a/tests/configuration.rs b/tests/configuration.rs index e2ac1be..e9f6a88 100644 --- a/tests/configuration.rs +++ b/tests/configuration.rs @@ -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);