//! All date and time-related functions will be defined here. //! //! Reading and setting single elements (seconds, hours, months) will NOT be implemented //! following the recommendations in the NXP datasheet to set and read all the seven date and time registers in one go. //! //! TO DO: As the chip may be used for devices that are clocks only, without the calendar function //! a convenient set_time() function could be added (sets only seconds, minutes and hours) use super::{DEVICE_ADDRESS, Error, PCF85063, Register, decode_bcd, encode_bcd}; use embassy_rp::rtc::DateTime; use embedded_hal_1::i2c::I2c; use time::{Date, PrimitiveDateTime, Time}; impl PCF85063 where I2C: I2c, { /// Read date and time all at once. pub fn get_datetime(&mut self) -> Result> { let mut data = [0; 7]; self.i2c .write_read(DEVICE_ADDRESS, &[Register::SECONDS], &mut data) .map_err(Error::I2C)?; Ok(PrimitiveDateTime::new( Date::from_calendar_date( 2000 + decode_bcd(data[6]) as i32, decode_bcd(data[5] & 0x1f).try_into()?, decode_bcd(data[3] & 0x3f), )?, Time::from_hms( decode_bcd(data[2] & 0x3f), decode_bcd(data[1] & 0b0111_1111), decode_bcd(data[0] & 0b0111_1111), )?, )) } /// Set date and time all at once. pub fn set_datetime(&mut self, datetime: &DateTime) -> Result<(), Error> { let payload = [ Register::SECONDS, //first register encode_bcd(datetime.second), encode_bcd(datetime.minute), encode_bcd(datetime.hour), encode_bcd(datetime.day), //Not sure if this is correct encode_bcd(datetime.day_of_week as u8), encode_bcd(datetime.month), encode_bcd((datetime.year - 2000) as u8), ]; self.i2c.write(DEVICE_ADDRESS, &payload).map_err(Error::I2C) } /// Set only the time, date remains unchanged. /// /// Will return an 'Error::InvalidInputData' if any of the parameters is out of range. pub fn set_time(&mut self, time: &Time) -> Result<(), Error> { let payload = [ Register::SECONDS, //first register encode_bcd(time.second()), encode_bcd(time.minute()), encode_bcd(time.hour()), ]; self.i2c.write(DEVICE_ADDRESS, &payload).map_err(Error::I2C) } }