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