diff --git a/README.md b/README.md index 5dc8e13..08b4433 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ This driver allows you to: - Read/write the hours in 24h or AM/PM format. - Read/write the weekday. - Read/write the day. +- Read/write the month. ## The devices diff --git a/src/ds323x/datetime.rs b/src/ds323x/datetime.rs index 4f22e75..9d1fbd7 100644 --- a/src/ds323x/datetime.rs +++ b/src/ds323x/datetime.rs @@ -17,7 +17,7 @@ pub enum Hours { impl Ds323x where - DI: ReadRegister + DI: ReadRegister + WriteRegister { /// Read the seconds. pub fn get_seconds(&mut self) -> Result> { @@ -57,16 +57,18 @@ where self.read_register_decimal(Register::DOM) } + /// Read the month [1-12]. + pub fn get_month(&mut self) -> Result> { + let data = self.iface.read_register(Register::MONTH)?; + let value = data & !BitFlags::CENTURY; + Ok(packed_bcd_to_decimal(value)) + } + fn read_register_decimal(&mut self, register: u8) -> Result> { let data = self.iface.read_register(register)?; Ok(packed_bcd_to_decimal(data)) } -} -impl Ds323x -where - DI: WriteRegister -{ /// Set the seconds [0-59]. /// /// Will return an `Error::InvalidInputData` if the seconds are out of range. @@ -128,6 +130,19 @@ where self.iface.write_register(Register::DOM, day) } + /// Set the month [1-12]. + /// + /// Will return an `Error::InvalidInputData` if the month is out of range. + pub fn set_month(&mut self, month: u8) -> Result<(), Error> { + if month < 1 || month > 12 { + return Err(Error::InvalidInputData); + } + // keep the century bit + let data = self.iface.read_register(Register::MONTH)?; + let value = (data & BitFlags::CENTURY) | decimal_to_packed_bcd(month); + self.iface.write_register(Register::MONTH, value) + } + fn write_register_decimal(&mut self, register: u8, decimal_number: u8) -> Result<(), Error> { self.iface.write_register(register, decimal_to_packed_bcd(decimal_number)) } diff --git a/src/lib.rs b/src/lib.rs index c691cb9..768a3d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ //! - Read/write the hours in 24h or AM/PM format. //! - Read/write the weekday. //! - Read/write the day. +//! - Read/write the month. //! //! ## The devices //! @@ -185,6 +186,7 @@ impl Register { const HOURS : u8 = 0x02; const DOW : u8 = 0x03; const DOM : u8 = 0x04; + const MONTH : u8 = 0x05; } struct BitFlags; @@ -192,6 +194,7 @@ struct BitFlags; impl BitFlags { const H24_H12 : u8 = 0b0100_0000; const AM_PM : u8 = 0b0010_0000; + const CENTURY : u8 = 0b1000_0000; } const DEVICE_ADDRESS: u8 = 0b110_1000; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index a0614cc..e9d8be4 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -14,6 +14,7 @@ impl Register { pub const HOURS : u8 = 0x02; pub const DOW : u8 = 0x03; pub const DOM : u8 = 0x04; + pub const MONTH : u8 = 0x05; } pub struct DummyOutputPin; diff --git a/tests/ds323x.rs b/tests/ds323x.rs index 01866f4..7a67c33 100644 --- a/tests/ds323x.rs +++ b/tests/ds323x.rs @@ -34,6 +34,20 @@ macro_rules! set_param_test { [ SpiTrans::write(vec![Register::$register + 0x80, $binary_value]) ]); }; } + +macro_rules! read_set_param_test { + ($method:ident, $register:ident, $value:expr, $binary_value_read:expr, $binary_value_write:expr) => { + set_test!(can_read_set_ds3231, $method, new_ds3231, $value, + [ I2cTrans::write_read(DEV_ADDR, vec![Register::$register], vec![$binary_value_read]), + I2cTrans::write(DEV_ADDR, vec![Register::$register, $binary_value_write]) ]); + + set_test!(can_read_set_ds3232, $method, new_ds3232, $value, + [ I2cTrans::write_read(DEV_ADDR, vec![Register::$register], vec![$binary_value_read]), + I2cTrans::write(DEV_ADDR, vec![Register::$register, $binary_value_write]) ]); + + set_test!(can_read_set_ds3234, $method, new_ds3234, $value, + [ SpiTrans::transfer(vec![Register::$register, 0], vec![Register::$register, $binary_value_read]), + SpiTrans::write(vec![Register::$register + 0x80, $binary_value_write]) ]); }; } @@ -107,3 +121,16 @@ mod day { set_param_test!(set_day, DOM, 1, 1); set_invalid_param_range_test!(set_day, 0, 8); } + +mod month { + use super::*; + get_param_test!(get_month, MONTH, 1, 1); + read_set_param_test!(set_month, MONTH, 12, 0b0000_0010, 0b0001_0010); + set_invalid_param_range_test!(set_month, 0, 13); + + mod keeps_century { + use super::*; + get_param_test!(get_month, MONTH, 12, 0b1001_0010); + read_set_param_test!(set_month, MONTH, 12, 0b1000_0010, 0b1001_0010); + } +}