···1+//! All date and time-related functions will be defined here.
2+//!
3+//! Reading and setting single elements (seconds, hours, months) will NOT be implemented
4+//! following the recommendations in the NXP datasheet to set and read all the seven date and time registers in one go.
5+//!
6+//! TO DO: As the chip may be used for devices that are clocks only, without the calendar function
7+//! a convenient set_time() function could be added (sets only seconds, minutes and hours)
8+9+use super::{DEVICE_ADDRESS, Error, PCF85063, Register, decode_bcd, encode_bcd};
10+use embedded_hal_async::i2c::I2c;
11+use time::{Date, PrimitiveDateTime, Time};
12+13+impl<I2C, E> PCF85063<I2C>
14+where
15+ I2C: I2c<Error = E>,
16+{
17+ /// Read date and time all at once.
18+ pub async fn get_datetime(&mut self) -> Result<PrimitiveDateTime, Error<E>> {
19+ let mut data = [0; 7];
20+ self.i2c
21+ .write_read(DEVICE_ADDRESS, &[Register::SECONDS], &mut data)
22+ .await
23+ .map_err(Error::I2C)?;
24+25+ Ok(PrimitiveDateTime::new(
26+ Date::from_calendar_date(
27+ 2000 + decode_bcd(data[6]) as i32,
28+ decode_bcd(data[5] & 0x1f).try_into()?,
29+ decode_bcd(data[3] & 0x3f),
30+ )?,
31+ Time::from_hms(
32+ decode_bcd(data[2] & 0x3f),
33+ decode_bcd(data[1] & 0b0111_1111),
34+ decode_bcd(data[0] & 0b0111_1111),
35+ )?,
36+ ))
37+ }
38+39+ /// Set date and time all at once.
40+ pub async fn set_datetime(&mut self, datetime: &PrimitiveDateTime) -> Result<(), Error<E>> {
41+ let payload = [
42+ Register::SECONDS, //first register
43+ encode_bcd(datetime.second()),
44+ encode_bcd(datetime.minute()),
45+ encode_bcd(datetime.hour()),
46+ encode_bcd(datetime.day()),
47+ encode_bcd(datetime.weekday().number_days_from_sunday()),
48+ encode_bcd(datetime.month().into()),
49+ encode_bcd((datetime.year() - 2000) as u8),
50+ ];
51+ self.i2c
52+ .write(DEVICE_ADDRESS, &payload)
53+ .await
54+ .map_err(Error::I2C)
55+ }
56+57+ /// Set only the time, date remains unchanged.
58+ ///
59+ /// Will return an 'Error::InvalidInputData' if any of the parameters is out of range.
60+ pub async fn set_time(&mut self, time: &Time) -> Result<(), Error<E>> {
61+ let payload = [
62+ Register::SECONDS, //first register
63+ encode_bcd(time.second()),
64+ encode_bcd(time.minute()),
65+ encode_bcd(time.hour()),
66+ ];
67+ self.i2c
68+ .write(DEVICE_ADDRESS, &payload)
69+ .await
70+ .map_err(Error::I2C)
71+ }
72+}