diff --git a/src/ds323x/datetime.rs b/src/ds323x/datetime.rs index 17e250d..e638f5b 100644 --- a/src/ds323x/datetime.rs +++ b/src/ds323x/datetime.rs @@ -195,6 +195,29 @@ where } } + /// Set the date and time. + /// + /// Will return an `Error::InvalidInputData` if any of the parameters is out of range. + pub fn set_datetime(&mut self, datetime: &DateTime) -> Result<(), Error> { + if datetime.year < 2000 || datetime.year > 2100 || + datetime.month < 1 || datetime.month > 12 || + datetime.day < 1 || datetime.day > 31 || + datetime.weekday < 1 || datetime.weekday > 7 || + datetime.minute > 59 || + datetime.second > 59 { + return Err(Error::InvalidInputData); + } + let (month, year) = month_year_to_registers(datetime.month, datetime.year); + let mut payload = [Register::SECONDS, + decimal_to_packed_bcd(datetime.second), + decimal_to_packed_bcd(datetime.minute), + self.get_hours_register_value(&datetime.hour)?, + decimal_to_packed_bcd(datetime.weekday), + decimal_to_packed_bcd(datetime.day), + month, year]; + self.iface.write_data(&mut payload) +} + fn write_register_decimal(&mut self, register: u8, decimal_number: u8) -> Result<(), Error> { self.iface.write_register(register, decimal_to_packed_bcd(decimal_number)) } @@ -223,6 +246,16 @@ fn year_from_registers(month: u8, year: u8) -> u16 { } } +fn month_year_to_registers(month: u8, year: u16) -> (u8, u8) { + if year > 2099 { + let month = BitFlags::CENTURY | decimal_to_packed_bcd(month); + (month, decimal_to_packed_bcd((year - 2100) as u8)) + } + else { + (decimal_to_packed_bcd(month), decimal_to_packed_bcd((year - 2000) as u8)) + } +} + fn is_24h_format(hours_data: u8) -> bool { hours_data & BitFlags::H24_H12 == 0 } diff --git a/tests/ds323x.rs b/tests/ds323x.rs index d9c6f5a..4357d3f 100644 --- a/tests/ds323x.rs +++ b/tests/ds323x.rs @@ -26,10 +26,10 @@ macro_rules! get_param_test { } macro_rules! get_param_read_array_test { - ($method:ident, $value:expr, $register1:ident, [ $( $bin:expr ),+ ], [ $( $bin2:expr ),+ ]) => { + ($method:ident, $value:expr, $register1:ident, [ $( $read_bin:expr ),+ ], [ $( $read_bin2:expr ),+ ]) => { _get_param_test!($method, $value, - [ I2cTrans::write_read(DEV_ADDR, vec![Register::$register1], vec![$( $bin ),*]) ], - [ SpiTrans::transfer(vec![Register::$register1, $( $bin2 ),*], vec![Register::$register1, $( $bin ),*]) ]); + [ I2cTrans::write_read(DEV_ADDR, vec![Register::$register1], vec![$( $read_bin ),*]) ], + [ SpiTrans::transfer(vec![Register::$register1, $( $read_bin2 ),*], vec![Register::$register1, $( $read_bin ),*]) ]); }; } @@ -49,6 +49,14 @@ macro_rules! set_param_test { }; } +macro_rules! set_param_write_array_test { + ($method:ident, $value:expr, $register:ident, [ $( $exp_bin:expr ),+ ] ) => { + _set_param_test!($method, $value, + [ I2cTrans::write(DEV_ADDR, vec![Register::$register, $( $exp_bin ),*]) ], + [ SpiTrans::write(vec![Register::$register + 0x80, $( $exp_bin ),*]) ]); + }; +} + macro_rules! read_set_param_write_two_test { ($method:ident, $value:expr, $register:ident, $binary_value1_read:expr, $bin1:expr, $bin2:expr) => { _set_param_test!($method, $value, @@ -173,9 +181,13 @@ mod year { mod datetime { use super::*; const DT : DateTime = DateTime { year: 2018, month: 8, day: 13, weekday: 2, - hour: Hours::H24(23), minute: 59, second: 58 }; + hour: Hours::H24(23), minute: 59, second: 58 }; get_param_read_array_test!(get_datetime, DT, SECONDS, [0b0101_1000, 0b0101_1001, 0b0010_0011, 0b0000_0010, 0b0001_0011, 0b0000_1000, 0b0001_1000], [0, 0, 0, 0, 0, 0, 0]); + + set_param_write_array_test!(set_datetime, &DT, SECONDS, + [0b0101_1000, 0b0101_1001, 0b0010_0011, 0b0000_0010, + 0b0001_0011, 0b0000_1000, 0b0001_1000]); }