A personal rust firmware for the Badger 2040 W
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
9use super::{DEVICE_ADDRESS, Error, PCF85063, Register, decode_bcd, encode_bcd};
10use embassy_rp::rtc::DateTime;
11use embedded_hal_1::i2c::I2c;
12use time::{Date, PrimitiveDateTime, Time};
13
14impl<I2C, E> PCF85063<I2C>
15where
16 I2C: I2c<Error = E>,
17{
18 /// Read date and time all at once.
19 pub fn get_datetime(&mut self) -> Result<PrimitiveDateTime, Error<E>> {
20 let mut data = [0; 7];
21 self.i2c
22 .write_read(DEVICE_ADDRESS, &[Register::SECONDS], &mut data)
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 fn set_datetime(&mut self, datetime: &DateTime) -> 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 //Not sure if this is correct
48 encode_bcd(datetime.day_of_week as u8),
49 encode_bcd(datetime.month),
50 encode_bcd((datetime.year - 2000) as u8),
51 ];
52 self.i2c.write(DEVICE_ADDRESS, &payload).map_err(Error::I2C)
53 }
54
55 /// Set only the time, date remains unchanged.
56 ///
57 /// Will return an 'Error::InvalidInputData' if any of the parameters is out of range.
58 pub fn set_time(&mut self, time: &Time) -> Result<(), Error<E>> {
59 let payload = [
60 Register::SECONDS, //first register
61 encode_bcd(time.second()),
62 encode_bcd(time.minute()),
63 encode_bcd(time.hour()),
64 ];
65 self.i2c.write(DEVICE_ADDRESS, &payload).map_err(Error::I2C)
66 }
67}