Skip to main content

pcf8563_dd/
driver.rs

1use super::{I2c, RegisterInterface, bisync, only_async, only_sync};
2use crate::{
3    Alarm, ClkoutFrequency, DateTime, PCF8563_I2C_ADDR, Pcf8563Interface, Pcf8563LowLevel,
4    RtcError, Time, TimerFrequency, bcd_to_dec, dec_to_bcd,
5};
6#[cfg(feature = "rtcc")]
7#[only_sync]
8use rtcc::{
9    Datelike as RtccDatelike, Hours as RtccHours, NaiveDate as RtccNaiveDate,
10    NaiveDateTime as RtccNaiveDateTime, NaiveTime as RtccNaiveTime, Timelike as RtccTimelike,
11};
12
13#[bisync]
14impl<I2CBus, E> RegisterInterface for Pcf8563Interface<I2CBus>
15where
16    I2CBus: I2c<Error = E>,
17    E: core::fmt::Debug,
18{
19    type AddressType = u8;
20    type Error = RtcError<E>;
21    async fn read_register(
22        &mut self,
23        address: u8,
24        _size_bits: u32,
25        data: &mut [u8],
26    ) -> Result<(), Self::Error> {
27        self.i2c_bus
28            .write_read(PCF8563_I2C_ADDR, &[address], data)
29            .await
30            .map_err(RtcError::I2c)
31    }
32    async fn write_register(
33        &mut self,
34        address: u8,
35        _size_bits: u32,
36        data: &[u8],
37    ) -> Result<(), Self::Error> {
38        let mut buffer = [0u8; 9]; // Max: address + 8 bytes for datetime
39        if (1 + data.len()) > buffer.len() {
40            return Err(RtcError::InvalidInputData);
41        }
42        buffer[0] = address;
43        buffer[1..1 + data.len()].copy_from_slice(data);
44        self.i2c_bus
45            .write(PCF8563_I2C_ADDR, &buffer[..1 + data.len()])
46            .await
47            .map_err(RtcError::I2c)
48    }
49}
50
51pub struct Pcf8563<
52    I2CImpl: RegisterInterface<AddressType = u8, Error = RtcError<I2CBusErr>>,
53    I2CBusErr: core::fmt::Debug,
54> {
55    pub ll: Pcf8563LowLevel<I2CImpl>,
56    _marker: core::marker::PhantomData<I2CBusErr>,
57}
58
59impl<I2CBus, E> Pcf8563<Pcf8563Interface<I2CBus>, E>
60where
61    I2CBus: I2c<Error = E>,
62    E: core::fmt::Debug,
63{
64    pub fn new(i2c: I2CBus) -> Self {
65        Self {
66            ll: Pcf8563LowLevel::new(Pcf8563Interface::new(i2c)),
67            _marker: core::marker::PhantomData,
68        }
69    }
70}
71
72include!("bisync_helpers.rs");
73
74impl<I2CImpl, I2CBusErr> Pcf8563<I2CImpl, I2CBusErr>
75where
76    I2CImpl: RegisterInterface<AddressType = u8, Error = RtcError<I2CBusErr>>,
77    I2CBusErr: core::fmt::Debug,
78{
79    // =========================================================================
80    // Date and Time
81    // =========================================================================
82
83    /// Get the current date and time
84    ///
85    /// Reads all 7 time/date registers in one operation as recommended by datasheet.
86    #[bisync]
87    pub async fn get_datetime(&mut self) -> Result<DateTime, RtcError<I2CBusErr>> {
88        let mut op_sec = self.ll.seconds();
89        let seconds_reg = read_internal(&mut op_sec).await?;
90
91        let mut op_min = self.ll.minutes();
92        let minutes_reg = read_internal(&mut op_min).await?;
93
94        let mut op_hr = self.ll.hours();
95        let hours_reg = read_internal(&mut op_hr).await?;
96
97        let mut op_day = self.ll.days();
98        let days_reg = read_internal(&mut op_day).await?;
99
100        let mut op_wd = self.ll.weekdays();
101        let weekdays_reg = read_internal(&mut op_wd).await?;
102
103        let mut op_mon = self.ll.century_months();
104        let months_reg = read_internal(&mut op_mon).await?;
105
106        let mut op_yr = self.ll.years();
107        let years_reg = read_internal(&mut op_yr).await?;
108
109        Ok(DateTime {
110            seconds: bcd_to_dec(
111                (seconds_reg.seconds_ten() << 4) as u8 | seconds_reg.seconds_unit() as u8,
112            ),
113            minutes: bcd_to_dec(
114                (minutes_reg.minutes_ten() << 4) as u8 | minutes_reg.minutes_unit() as u8,
115            ),
116            hours: bcd_to_dec((hours_reg.hours_ten() << 4) as u8 | hours_reg.hours_unit() as u8),
117            day: bcd_to_dec((days_reg.days_ten() << 4) as u8 | days_reg.days_unit() as u8),
118            weekday: weekdays_reg.weekday() as u8,
119            month: bcd_to_dec(
120                (months_reg.months_ten() << 4) as u8 | months_reg.months_unit() as u8,
121            ),
122            year: bcd_to_dec((years_reg.years_ten() << 4) as u8 | years_reg.years_unit() as u8),
123        })
124    }
125
126    /// Set the date and time
127    ///
128    /// Sets all 7 time/date registers in sequence. Also clears the VL flag.
129    #[bisync]
130    pub async fn set_datetime(&mut self, dt: &DateTime) -> Result<(), RtcError<I2CBusErr>> {
131        // Validate input
132        if dt.year > 99
133            || dt.month < 1
134            || dt.month > 12
135            || dt.weekday > 6
136            || dt.day < 1
137            || dt.day > 31
138            || dt.hours > 23
139            || dt.minutes > 59
140            || dt.seconds > 59
141        {
142            return Err(RtcError::InvalidInputData);
143        }
144
145        let seconds_bcd = dec_to_bcd(dt.seconds);
146        let minutes_bcd = dec_to_bcd(dt.minutes);
147        let hours_bcd = dec_to_bcd(dt.hours);
148        let days_bcd = dec_to_bcd(dt.day);
149        let months_bcd = dec_to_bcd(dt.month);
150        let years_bcd = dec_to_bcd(dt.year);
151
152        // Write seconds (also clears VL flag)
153        let mut op_sec = self.ll.seconds();
154        write_internal(&mut op_sec, |r| {
155            r.set_vl(false);
156            r.set_seconds_ten(seconds_bcd >> 4);
157            r.set_seconds_unit(seconds_bcd & 0x0F);
158        })
159        .await?;
160
161        let mut op_min = self.ll.minutes();
162        write_internal(&mut op_min, |r| {
163            r.set_minutes_ten(minutes_bcd >> 4);
164            r.set_minutes_unit(minutes_bcd & 0x0F);
165        })
166        .await?;
167
168        let mut op_hr = self.ll.hours();
169        write_internal(&mut op_hr, |r| {
170            r.set_hours_ten(hours_bcd >> 4);
171            r.set_hours_unit(hours_bcd & 0x0F);
172        })
173        .await?;
174
175        let mut op_day = self.ll.days();
176        write_internal(&mut op_day, |r| {
177            r.set_days_ten(days_bcd >> 4);
178            r.set_days_unit(days_bcd & 0x0F);
179        })
180        .await?;
181
182        let mut op_wd = self.ll.weekdays();
183        write_internal(&mut op_wd, |r| {
184            r.set_weekday(dt.weekday);
185        })
186        .await?;
187
188        let mut op_mon = self.ll.century_months();
189        write_internal(&mut op_mon, |r| {
190            r.set_months_ten(months_bcd >> 4);
191            r.set_months_unit(months_bcd & 0x0F);
192        })
193        .await?;
194
195        let mut op_yr = self.ll.years();
196        write_internal(&mut op_yr, |r| {
197            r.set_years_ten(years_bcd >> 4);
198            r.set_years_unit(years_bcd & 0x0F);
199        })
200        .await?;
201
202        Ok(())
203    }
204
205    /// Set only the time (hours, minutes, seconds)
206    #[bisync]
207    pub async fn set_time(&mut self, time: &Time) -> Result<(), RtcError<I2CBusErr>> {
208        if time.hours > 23 || time.minutes > 59 || time.seconds > 59 {
209            return Err(RtcError::InvalidInputData);
210        }
211
212        let seconds_bcd = dec_to_bcd(time.seconds);
213        let minutes_bcd = dec_to_bcd(time.minutes);
214        let hours_bcd = dec_to_bcd(time.hours);
215
216        let mut op_sec = self.ll.seconds();
217        write_internal(&mut op_sec, |r| {
218            r.set_vl(false);
219            r.set_seconds_ten(seconds_bcd >> 4);
220            r.set_seconds_unit(seconds_bcd & 0x0F);
221        })
222        .await?;
223
224        let mut op_min = self.ll.minutes();
225        write_internal(&mut op_min, |r| {
226            r.set_minutes_ten(minutes_bcd >> 4);
227            r.set_minutes_unit(minutes_bcd & 0x0F);
228        })
229        .await?;
230
231        let mut op_hr = self.ll.hours();
232        write_internal(&mut op_hr, |r| {
233            r.set_hours_ten(hours_bcd >> 4);
234            r.set_hours_unit(hours_bcd & 0x0F);
235        })
236        .await?;
237
238        Ok(())
239    }
240
241    // =========================================================================
242    // Clock Integrity (Voltage Low Detection)
243    // =========================================================================
244
245    /// Check if clock integrity is guaranteed
246    ///
247    /// Returns `false` if the VL (Voltage Low) flag is set, indicating
248    /// the clock data may be invalid due to power loss.
249    #[bisync]
250    pub async fn is_clock_valid(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
251        let mut op = self.ll.seconds();
252        let reg = read_internal(&mut op).await?;
253        Ok(!reg.vl())
254    }
255
256    /// Clear the voltage-low flag
257    ///
258    /// Should be called after setting the time to indicate clock is valid.
259    #[bisync]
260    pub async fn clear_voltage_low_flag(&mut self) -> Result<(), RtcError<I2CBusErr>> {
261        let mut op = self.ll.seconds();
262        modify_internal(&mut op, |r| r.set_vl(false)).await
263    }
264
265    // =========================================================================
266    // Century Flag
267    // =========================================================================
268
269    /// Get the century flag
270    ///
271    /// Returns `true` if century is X+1 (e.g., 2100s), `false` if century is X (e.g., 2000s)
272    #[bisync]
273    pub async fn get_century_flag(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
274        let mut op = self.ll.century_months();
275        let reg = read_internal(&mut op).await?;
276        Ok(reg.century())
277    }
278
279    /// Set the century flag
280    #[bisync]
281    pub async fn set_century_flag(&mut self, century: bool) -> Result<(), RtcError<I2CBusErr>> {
282        let mut op = self.ll.century_months();
283        modify_internal(&mut op, |r| r.set_century(century)).await
284    }
285
286    // =========================================================================
287    // Clock Control
288    // =========================================================================
289
290    /// Start or stop the RTC clock
291    #[bisync]
292    pub async fn set_clock_running(&mut self, running: bool) -> Result<(), RtcError<I2CBusErr>> {
293        let mut op = self.ll.control_status_1();
294        modify_internal(&mut op, |r| r.set_stop(!running)).await
295    }
296
297    /// Check if the RTC clock is running
298    #[bisync]
299    pub async fn is_clock_running(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
300        let mut op = self.ll.control_status_1();
301        let reg = read_internal(&mut op).await?;
302        Ok(!reg.stop())
303    }
304
305    // =========================================================================
306    // Alarm
307    // =========================================================================
308
309    /// Get the current alarm configuration
310    #[bisync]
311    pub async fn get_alarm(&mut self) -> Result<Alarm, RtcError<I2CBusErr>> {
312        let mut op_min = self.ll.minute_alarm();
313        let min_reg = read_internal(&mut op_min).await?;
314
315        let mut op_hr = self.ll.hour_alarm();
316        let hr_reg = read_internal(&mut op_hr).await?;
317
318        let mut op_day = self.ll.day_alarm();
319        let day_reg = read_internal(&mut op_day).await?;
320
321        let mut op_wd = self.ll.weekday_alarm();
322        let wd_reg = read_internal(&mut op_wd).await?;
323
324        Ok(Alarm {
325            minute: if min_reg.ae_m() {
326                None
327            } else {
328                Some(bcd_to_dec(
329                    (min_reg.minute_alarm_ten() << 4) as u8 | min_reg.minute_alarm_unit() as u8,
330                ))
331            },
332            hour: if hr_reg.ae_h() {
333                None
334            } else {
335                Some(bcd_to_dec(
336                    (hr_reg.hour_alarm_ten() << 4) as u8 | hr_reg.hour_alarm_unit() as u8,
337                ))
338            },
339            day: if day_reg.ae_d() {
340                None
341            } else {
342                Some(bcd_to_dec(
343                    (day_reg.day_alarm_ten() << 4) as u8 | day_reg.day_alarm_unit() as u8,
344                ))
345            },
346            weekday: if wd_reg.ae_w() {
347                None
348            } else {
349                Some(wd_reg.weekday_alarm() as u8)
350            },
351        })
352    }
353
354    /// Set the alarm configuration
355    ///
356    /// Set a field to `Some(value)` to enable that alarm component,
357    /// or `None` to disable it.
358    #[bisync]
359    pub async fn set_alarm(&mut self, alarm: &Alarm) -> Result<(), RtcError<I2CBusErr>> {
360        // Minute alarm
361        let mut op_min = self.ll.minute_alarm();
362        write_internal(&mut op_min, |r| {
363            if let Some(min) = alarm.minute {
364                let bcd = dec_to_bcd(min);
365                r.set_ae_m(false); // Enable
366                r.set_minute_alarm_ten(bcd >> 4);
367                r.set_minute_alarm_unit(bcd & 0x0F);
368            } else {
369                r.set_ae_m(true); // Disable
370            }
371        })
372        .await?;
373
374        // Hour alarm
375        let mut op_hr = self.ll.hour_alarm();
376        write_internal(&mut op_hr, |r| {
377            if let Some(hr) = alarm.hour {
378                let bcd = dec_to_bcd(hr);
379                r.set_ae_h(false); // Enable
380                r.set_hour_alarm_ten(bcd >> 4);
381                r.set_hour_alarm_unit(bcd & 0x0F);
382            } else {
383                r.set_ae_h(true); // Disable
384            }
385        })
386        .await?;
387
388        // Day alarm
389        let mut op_day = self.ll.day_alarm();
390        write_internal(&mut op_day, |r| {
391            if let Some(day) = alarm.day {
392                let bcd = dec_to_bcd(day);
393                r.set_ae_d(false); // Enable
394                r.set_day_alarm_ten(bcd >> 4);
395                r.set_day_alarm_unit(bcd & 0x0F);
396            } else {
397                r.set_ae_d(true); // Disable
398            }
399        })
400        .await?;
401
402        // Weekday alarm
403        let mut op_wd = self.ll.weekday_alarm();
404        write_internal(&mut op_wd, |r| {
405            if let Some(wd) = alarm.weekday {
406                r.set_ae_w(false); // Enable
407                r.set_weekday_alarm(wd);
408            } else {
409                r.set_ae_w(true); // Disable
410            }
411        })
412        .await?;
413
414        Ok(())
415    }
416
417    /// Disable all alarm components
418    #[bisync]
419    pub async fn disable_alarm(&mut self) -> Result<(), RtcError<I2CBusErr>> {
420        self.set_alarm(&Alarm::default()).await
421    }
422
423    /// Check if alarm flag is set (alarm has triggered)
424    #[bisync]
425    pub async fn get_alarm_flag(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
426        let mut op = self.ll.control_status_2();
427        let reg = read_internal(&mut op).await?;
428        Ok(reg.af())
429    }
430
431    /// Clear the alarm flag
432    #[bisync]
433    pub async fn clear_alarm_flag(&mut self) -> Result<(), RtcError<I2CBusErr>> {
434        let mut op = self.ll.control_status_2();
435        modify_internal(&mut op, |r| r.set_af(false)).await
436    }
437
438    /// Enable or disable alarm interrupt
439    #[bisync]
440    pub async fn set_alarm_interrupt(&mut self, enable: bool) -> Result<(), RtcError<I2CBusErr>> {
441        let mut op = self.ll.control_status_2();
442        modify_internal(&mut op, |r| r.set_aie(enable)).await
443    }
444
445    /// Check if alarm interrupt is enabled
446    #[bisync]
447    pub async fn is_alarm_interrupt_enabled(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
448        let mut op = self.ll.control_status_2();
449        let reg = read_internal(&mut op).await?;
450        Ok(reg.aie())
451    }
452
453    // =========================================================================
454    // Timer
455    // =========================================================================
456
457    /// Set the timer countdown value (0-255)
458    #[bisync]
459    pub async fn set_timer_value(&mut self, value: u8) -> Result<(), RtcError<I2CBusErr>> {
460        let mut op = self.ll.timer();
461        write_internal(&mut op, |r| r.set_timer_value(value)).await
462    }
463
464    /// Get the current timer countdown value
465    #[bisync]
466    pub async fn get_timer_value(&mut self) -> Result<u8, RtcError<I2CBusErr>> {
467        let mut op = self.ll.timer();
468        let reg = read_internal(&mut op).await?;
469        Ok(reg.timer_value() as u8)
470    }
471
472    /// Set the timer source clock frequency
473    #[bisync]
474    pub async fn set_timer_frequency(
475        &mut self,
476        freq: TimerFrequency,
477    ) -> Result<(), RtcError<I2CBusErr>> {
478        let mut op = self.ll.timer_control();
479        modify_internal(&mut op, |r| r.set_td(freq)).await
480    }
481
482    /// Get the timer source clock frequency
483    #[bisync]
484    pub async fn get_timer_frequency(&mut self) -> Result<TimerFrequency, RtcError<I2CBusErr>> {
485        let mut op = self.ll.timer_control();
486        let reg = read_internal(&mut op).await?;
487        Ok(reg.td())
488    }
489
490    /// Enable or disable the timer
491    #[bisync]
492    pub async fn set_timer_enabled(&mut self, enable: bool) -> Result<(), RtcError<I2CBusErr>> {
493        let mut op = self.ll.timer_control();
494        modify_internal(&mut op, |r| r.set_te(enable)).await
495    }
496
497    /// Check if timer is enabled
498    #[bisync]
499    pub async fn is_timer_enabled(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
500        let mut op = self.ll.timer_control();
501        let reg = read_internal(&mut op).await?;
502        Ok(reg.te())
503    }
504
505    /// Check if timer flag is set (timer has triggered)
506    #[bisync]
507    pub async fn get_timer_flag(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
508        let mut op = self.ll.control_status_2();
509        let reg = read_internal(&mut op).await?;
510        Ok(reg.tf())
511    }
512
513    /// Clear the timer flag
514    #[bisync]
515    pub async fn clear_timer_flag(&mut self) -> Result<(), RtcError<I2CBusErr>> {
516        let mut op = self.ll.control_status_2();
517        modify_internal(&mut op, |r| r.set_tf(false)).await
518    }
519
520    /// Enable or disable timer interrupt
521    #[bisync]
522    pub async fn set_timer_interrupt(&mut self, enable: bool) -> Result<(), RtcError<I2CBusErr>> {
523        let mut op = self.ll.control_status_2();
524        modify_internal(&mut op, |r| r.set_tie(enable)).await
525    }
526
527    /// Check if timer interrupt is enabled
528    #[bisync]
529    pub async fn is_timer_interrupt_enabled(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
530        let mut op = self.ll.control_status_2();
531        let reg = read_internal(&mut op).await?;
532        Ok(reg.tie())
533    }
534
535    /// Set timer interrupt mode (level or pulse)
536    #[bisync]
537    pub async fn set_timer_interrupt_pulse_mode(
538        &mut self,
539        pulse: bool,
540    ) -> Result<(), RtcError<I2CBusErr>> {
541        let mut op = self.ll.control_status_2();
542        modify_internal(&mut op, |r| r.set_ti_tp(pulse)).await
543    }
544
545    // =========================================================================
546    // Clock Output
547    // =========================================================================
548
549    /// Enable or disable the CLKOUT output
550    #[bisync]
551    pub async fn set_clkout_enabled(&mut self, enable: bool) -> Result<(), RtcError<I2CBusErr>> {
552        let mut op = self.ll.clkout_control();
553        modify_internal(&mut op, |r| r.set_fe(enable)).await
554    }
555
556    /// Check if CLKOUT is enabled
557    #[bisync]
558    pub async fn is_clkout_enabled(&mut self) -> Result<bool, RtcError<I2CBusErr>> {
559        let mut op = self.ll.clkout_control();
560        let reg = read_internal(&mut op).await?;
561        Ok(reg.fe())
562    }
563
564    /// Set the CLKOUT frequency
565    #[bisync]
566    pub async fn set_clkout_frequency(
567        &mut self,
568        freq: ClkoutFrequency,
569    ) -> Result<(), RtcError<I2CBusErr>> {
570        let mut op = self.ll.clkout_control();
571        modify_internal(&mut op, |r| r.set_fd(freq)).await
572    }
573
574    /// Get the CLKOUT frequency setting
575    #[bisync]
576    pub async fn get_clkout_frequency(&mut self) -> Result<ClkoutFrequency, RtcError<I2CBusErr>> {
577        let mut op = self.ll.clkout_control();
578        let reg = read_internal(&mut op).await?;
579        Ok(reg.fd())
580    }
581
582    // =========================================================================
583    // Initialization
584    // =========================================================================
585
586    /// Initialize the RTC with default settings
587    ///
588    /// - Clears all control bits
589    /// - Clears voltage-low flag
590    /// - Disables all alarms
591    /// - Sets timer to lowest frequency (1/60 Hz) for power saving
592    #[bisync]
593    pub async fn init(&mut self) -> Result<(), RtcError<I2CBusErr>> {
594        // Clear control status 1
595        let mut op1 = self.ll.control_status_1();
596        write_internal(&mut op1, |r| {
597            r.set_test1(false);
598            r.set_stop(false);
599            r.set_testc(false);
600        })
601        .await?;
602
603        // Clear control status 2
604        let mut op2 = self.ll.control_status_2();
605        write_internal(&mut op2, |r| {
606            r.set_ti_tp(false);
607            r.set_af(false);
608            r.set_tf(false);
609            r.set_aie(false);
610            r.set_tie(false);
611        })
612        .await?;
613
614        // Clear voltage-low flag
615        self.clear_voltage_low_flag().await?;
616
617        // Disable all alarms
618        self.disable_alarm().await?;
619
620        // Set timer to lowest frequency for power saving
621        self.set_timer_frequency(TimerFrequency::Freq160Hz).await?;
622
623        Ok(())
624    }
625}
626
627#[cfg(feature = "rtcc")]
628#[only_sync]
629impl<I2CImpl, I2CBusErr> rtcc::DateTimeAccess for Pcf8563<I2CImpl, I2CBusErr>
630where
631    I2CImpl: RegisterInterface<AddressType = u8, Error = RtcError<I2CBusErr>>,
632    I2CBusErr: core::fmt::Debug,
633{
634    type Error = RtcError<I2CBusErr>;
635
636    fn datetime(&mut self) -> Result<RtccNaiveDateTime, Self::Error> {
637        let dt = self.get_datetime()?;
638        let century_flag = self.get_century_flag()?;
639        let base_year = if century_flag { 1900 } else { 2000 };
640
641        let date =
642            RtccNaiveDate::from_ymd_opt(base_year + dt.year as i32, dt.month as u32, dt.day as u32)
643                .ok_or(RtcError::InvalidInputData)?;
644        let time =
645            RtccNaiveTime::from_hms_opt(dt.hours as u32, dt.minutes as u32, dt.seconds as u32)
646                .ok_or(RtcError::InvalidInputData)?;
647
648        Ok(RtccNaiveDateTime::new(date, time))
649    }
650
651    fn set_datetime(&mut self, datetime: &RtccNaiveDateTime) -> Result<(), Self::Error> {
652        let date = datetime.date();
653        let time = datetime.time();
654        let year = date.year();
655
656        if !(1900..=2099).contains(&year) {
657            return Err(RtcError::InvalidInputData);
658        }
659
660        let dt = DateTime {
661            year: (year % 100) as u8,
662            month: date.month() as u8,
663            day: date.day() as u8,
664            weekday: date.weekday().num_days_from_sunday() as u8,
665            hours: time.hour() as u8,
666            minutes: time.minute() as u8,
667            seconds: time.second() as u8,
668        };
669
670        self.set_century_flag(year < 2000)?;
671        self.set_datetime(&dt)
672    }
673}
674
675#[cfg(feature = "rtcc")]
676#[only_sync]
677impl<I2CImpl, I2CBusErr> rtcc::Rtcc for Pcf8563<I2CImpl, I2CBusErr>
678where
679    I2CImpl: RegisterInterface<AddressType = u8, Error = RtcError<I2CBusErr>>,
680    I2CBusErr: core::fmt::Debug,
681{
682    fn seconds(&mut self) -> Result<u8, Self::Error> {
683        Ok(self.get_datetime()?.seconds)
684    }
685
686    fn minutes(&mut self) -> Result<u8, Self::Error> {
687        Ok(self.get_datetime()?.minutes)
688    }
689
690    fn hours(&mut self) -> Result<RtccHours, Self::Error> {
691        let hours = self.get_datetime()?.hours;
692        if hours > 23 {
693            Err(RtcError::InvalidInputData)
694        } else {
695            Ok(RtccHours::H24(hours))
696        }
697    }
698
699    fn time(&mut self) -> Result<RtccNaiveTime, Self::Error> {
700        let dt = self.get_datetime()?;
701        RtccNaiveTime::from_hms_opt(dt.hours as u32, dt.minutes as u32, dt.seconds as u32)
702            .ok_or(RtcError::InvalidInputData)
703    }
704
705    fn weekday(&mut self) -> Result<u8, Self::Error> {
706        let weekday = self.get_datetime()?.weekday;
707        if weekday > 6 {
708            Err(RtcError::InvalidInputData)
709        } else {
710            Ok(weekday + 1)
711        }
712    }
713
714    fn day(&mut self) -> Result<u8, Self::Error> {
715        Ok(self.get_datetime()?.day)
716    }
717
718    fn month(&mut self) -> Result<u8, Self::Error> {
719        Ok(self.get_datetime()?.month)
720    }
721
722    fn year(&mut self) -> Result<u16, Self::Error> {
723        let datetime = <Self as rtcc::DateTimeAccess>::datetime(self)?;
724        Ok(datetime.date().year() as u16)
725    }
726
727    fn date(&mut self) -> Result<RtccNaiveDate, Self::Error> {
728        Ok(<Self as rtcc::DateTimeAccess>::datetime(self)?.date())
729    }
730
731    fn set_seconds(&mut self, seconds: u8) -> Result<(), Self::Error> {
732        let mut dt = self.get_datetime()?;
733        dt.seconds = seconds;
734        self.set_datetime(&dt)
735    }
736
737    fn set_minutes(&mut self, minutes: u8) -> Result<(), Self::Error> {
738        let mut dt = self.get_datetime()?;
739        dt.minutes = minutes;
740        self.set_datetime(&dt)
741    }
742
743    fn set_hours(&mut self, hours: RtccHours) -> Result<(), Self::Error> {
744        let hours_24 = match hours {
745            RtccHours::H24(h) if h < 24 => h,
746            RtccHours::AM(h) if (1..=12).contains(&h) => {
747                if h == 12 {
748                    0
749                } else {
750                    h
751                }
752            }
753            RtccHours::PM(h) if (1..=12).contains(&h) => {
754                if h == 12 {
755                    12
756                } else {
757                    h + 12
758                }
759            }
760            _ => return Err(RtcError::InvalidInputData),
761        };
762
763        let mut dt = self.get_datetime()?;
764        dt.hours = hours_24;
765        self.set_datetime(&dt)
766    }
767
768    fn set_time(&mut self, time: &RtccNaiveTime) -> Result<(), Self::Error> {
769        let time = Time {
770            hours: time.hour() as u8,
771            minutes: time.minute() as u8,
772            seconds: time.second() as u8,
773        };
774        self.set_time(&time)
775    }
776
777    fn set_weekday(&mut self, weekday: u8) -> Result<(), Self::Error> {
778        if !(1..=7).contains(&weekday) {
779            return Err(RtcError::InvalidInputData);
780        }
781
782        let mut dt = self.get_datetime()?;
783        dt.weekday = weekday - 1;
784        self.set_datetime(&dt)
785    }
786
787    fn set_day(&mut self, day: u8) -> Result<(), Self::Error> {
788        let mut dt = self.get_datetime()?;
789        dt.day = day;
790        self.set_datetime(&dt)
791    }
792
793    fn set_month(&mut self, month: u8) -> Result<(), Self::Error> {
794        let mut dt = self.get_datetime()?;
795        dt.month = month;
796        self.set_datetime(&dt)
797    }
798
799    fn set_year(&mut self, year: u16) -> Result<(), Self::Error> {
800        if !(1900..=2099).contains(&year) {
801            return Err(RtcError::InvalidInputData);
802        }
803
804        let mut dt = self.get_datetime()?;
805        dt.year = (year % 100) as u8;
806        self.set_century_flag(year < 2000)?;
807        self.set_datetime(&dt)
808    }
809
810    fn set_date(&mut self, date: &RtccNaiveDate) -> Result<(), Self::Error> {
811        let year = date.year();
812        if !(1900..=2099).contains(&year) {
813            return Err(RtcError::InvalidInputData);
814        }
815
816        let mut dt = self.get_datetime()?;
817        dt.year = (year % 100) as u8;
818        dt.month = date.month() as u8;
819        dt.day = date.day() as u8;
820        dt.weekday = date.weekday().num_days_from_sunday() as u8;
821
822        self.set_century_flag(year < 2000)?;
823        self.set_datetime(&dt)
824    }
825}