1use core::convert::TryInto;
8
9use cfg_if::cfg_if;
10use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
11
12use crate::{
13 error::{Error, Result},
14 pac::{EXTI, PWR, RCC, RTC},
15 util::bounded_loop,
16};
17
18#[derive(Clone, Copy, Debug, PartialEq)]
22#[repr(u8)]
23pub enum RtcClockSource {
24 Lse = 0b01,
26 Lsi = 0b10,
28 Hse = 0b11,
30}
31
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34#[derive(Debug, Clone, Copy, Eq, PartialEq)]
35pub enum RtcError {
36 InvalidInputData,
38}
39
40#[derive(Clone, Copy, Debug)]
43enum WakeupDivision {
44 Sixteen,
45 Eight,
46 Four,
47 Two,
48}
49
50#[derive(Clone, Copy, Debug)]
52enum ClockConfig {
53 One(WakeupDivision),
54 Two,
55 Three,
56}
57
58pub enum Event {
60 WakeupTimer,
61 AlarmA,
62 AlarmB,
63 Timestamp,
64}
65
66pub enum Alarm {
67 AlarmA,
68 AlarmB,
69}
70
71impl From<Alarm> for Event {
72 fn from(a: Alarm) -> Self {
73 match a {
74 Alarm::AlarmA => Event::AlarmA,
75 Alarm::AlarmB => Event::AlarmB,
76 }
77 }
78}
79
80pub struct Rtc {
82 regs: RTC,
84 config: RtcConfig,
85}
86
87#[derive(Copy, Clone, Debug, PartialEq)]
88pub struct RtcConfig {
90 pub clock_source: RtcClockSource,
92 pub async_prescaler: u8,
97 pub sync_prescaler: u16,
102 pub bypass_lse_output: bool,
105}
106
107impl Default for RtcConfig {
108 fn default() -> Self {
111 RtcConfig {
112 clock_source: RtcClockSource::Lsi,
113 async_prescaler: 127,
114 sync_prescaler: 255,
115 bypass_lse_output: false,
116 }
117 }
118}
119
120impl Rtc {
121 pub fn new(regs: RTC, config: RtcConfig) -> Result<Self> {
123 let mut rtc = Self { regs, config };
124
125 let rcc = unsafe { &(*RCC::ptr()) };
134 let pwr = unsafe { &(*PWR::ptr()) };
135
136 cfg_if! {
137 if #[cfg(any(feature = "f3", feature = "f4"))] {
138 rcc.apb1enr().modify(|_, w| w.pwren().bit(true));
139 pwr.cr().read(); pwr.cr().modify(|_, w| w.dbp().bit(true));
141 bounded_loop!(pwr.cr().read().dbp().bit_is_clear(), Error::RegisterUnchanged);
142 } else if #[cfg(any(feature = "l4", feature = "l5", feature = "g4", feature = "l412", feature = "wb", feature = "wl"))] {
143 #[cfg(not(any(feature = "wb", feature = "wl")))]
146 rcc.apb1enr1().modify(|_, w| {
147 w.pwren().bit(true);
148 w.rtcapben().bit(true)
149 });
150 #[cfg(any(feature = "wb", feature = "wl"))]
151 rcc.apb1enr1().modify(|_, w| w.rtcapben().bit(true));
152
153 rcc.apb1smenr1().modify(|_, w| w.rtcapbsmen().bit(true)); pwr.cr1().read(); pwr.cr1().modify( | _, w| w.dbp().bit(true)); bounded_loop!(pwr.cr1().read().dbp().bit_is_clear(), Error::RegisterUnchanged);
159 } else if #[cfg(feature = "c0")] {
160 rcc.apbenr1().modify(|_, w| {
162 w.pwren().bit(true);
163 w.rtcapben().bit(true)
164 });
165
166 rcc.apbsmenr1().modify(|_, w| w.rtcapbsmen().bit(true)); pwr.cr1().read(); } else if #[cfg(any(feature = "g0"))] {
169 rcc.apbenr1().modify(|_, w| {
170 w.pwren().bit(true);
171 w.rtcapben().bit(true)
172 });
173 rcc.apbsmenr1().modify(|_, w| w.rtcapbsmen().bit(true)); pwr.cr1().read();
175 pwr.cr1().modify( | _, w| w.dbp().bit(true));
176 bounded_loop!(pwr.cr1().read().dbp().bit_is_clear(), Error::RegisterUnchanged);
177 while pwr.cr1().read().dbp().bit_is_clear() {}
178 } else if #[cfg(feature = "h5")] {
179 rcc.apb3enr().modify(|_, w| w.rtcapben().bit(true));
180 rcc.apb3lpenr().modify(|_, w| w.rtcapblpen().bit(true)); pwr.dbpcr().read(); pwr.dbpcr().modify( | _, w| w.dbp().bit(true));
183 bounded_loop!(pwr.dbpcr().read().dbp().bit_is_clear(), Error::RegisterUnchanged);
184 } else { rcc.apb4enr().modify(|_, w| w.rtcapben().bit(true));
186 rcc.apb4lpenr().modify(|_, w| w.rtcapblpen().bit(true)); pwr.cr1().read(); pwr.cr1().modify( | _, w| w.dbp().bit(true));
189 bounded_loop!(pwr.cr1().read().dbp().bit_is_clear(), Error::RegisterUnchanged);
190 }
191 }
192
193 match config.clock_source {
195 RtcClockSource::Lsi => {
196 cfg_if! {
197 if #[cfg(feature = "wb")] {
198 rcc.csr().modify(|_, w| w.lsi1on().bit(true));
200 bounded_loop!(rcc.csr().read().lsi1rdy().bit_is_clear(), Error::RegisterUnchanged);
201 } else if #[cfg(feature = "h5")] {
202 rcc.bdcr().modify(|_, w| w.lsion().bit(true));
203 bounded_loop!(rcc.bdcr().read().lsirdy().bit_is_clear(), Error::RegisterUnchanged);
204 } else if #[cfg(feature = "c0")] {
205 rcc.csr2().modify(|_, w| w.lsion().bit(true));
206 bounded_loop!(rcc.csr2().read().lsirdy().bit_is_clear(), Error::RegisterUnchanged);
207 } else {
208 rcc.csr().modify(|_, w| w.lsion().bit(true));
209 bounded_loop!(rcc.csr().read().lsirdy().bit_is_clear(), Error::RegisterUnchanged);
210 }
211 }
212 }
213 #[cfg(not(feature = "c0"))]
214 RtcClockSource::Lse => {
215 rcc.bdcr()
217 .modify(|_, w| w.lsebyp().bit(config.bypass_lse_output));
218 rcc.bdcr().modify(|_, w| w.lseon().bit(true));
219 bounded_loop!(
220 rcc.bdcr().read().lserdy().bit_is_clear(),
221 Error::RegisterUnchanged
222 );
223 }
224 #[cfg(feature = "c0")]
225 RtcClockSource::Lse => {
226 rcc.csr1()
228 .modify(|_, w| w.lsebyp().bit(config.bypass_lse_output));
229 rcc.csr1().modify(|_, w| w.lseon().bit(true));
230
231 bounded_loop!(
232 rcc.csr1().read().lserdy().bit_is_clear(),
233 Error::RegisterUnchanged
234 );
235 }
236 _ => (),
237 }
238
239 #[cfg(not(feature = "c0"))]
240 rcc.bdcr().modify(|_, w| {
241 unsafe { w.rtcsel().bits(rtc.config.clock_source as u8) };
243 w.rtcen().bit(true)
246 });
247
248 #[cfg(feature = "c0")]
249 rcc.csr1().modify(|_, w| {
250 unsafe { w.rtcsel().bits(rtc.config.clock_source as u8) };
251 w.rtcen().bit(true)
252 });
253
254 rtc.edit_regs(false, |regs| {
255 regs.cr().modify(
256 |_, w| {
257 unsafe {
258 w.fmt()
259 .clear_bit() .osel()
261 .bits(0b00)
268 .pol()
269 .clear_bit()
270 }
271 }, );
273
274 regs.prer().modify(|_, w| unsafe {
275 w.prediv_s().bits(config.sync_prescaler);
276 w.prediv_a().bits(config.async_prescaler)
277 });
278 })?;
279
280 Ok(rtc)
281 }
282
283 pub fn set_24h_fmt(&mut self) -> Result<()> {
285 self.edit_regs(true, |regs| {
286 regs.cr().modify(|_, w| w.fmt().clear_bit());
287 })
288 }
289
290 pub fn set_12h_fmt(&mut self) -> Result<()> {
292 self.edit_regs(true, |regs| {
293 regs.cr().modify(|_, w| w.fmt().set_bit());
294 })
295 }
296
297 pub fn is_24h_fmt(&self) -> bool {
299 !self.regs.cr().read().fmt().bit()
300 }
301
302 fn set_wakeup_interval_inner(&mut self, sleep_time: f32) {
326 let lfe_freq = match self.config.clock_source {
336 RtcClockSource::Lse => 32_768.,
337 RtcClockSource::Lsi => 40_000.,
338 RtcClockSource::Hse => 250_000., };
340
341 let clock_cfg;
347 let wutr;
348
349 if sleep_time >= 0.00012207 && sleep_time < 32. {
350 let division;
351 let div;
352 if sleep_time < 4. {
353 division = WakeupDivision::Two; div = 2.;
355 } else if sleep_time < 8. {
356 division = WakeupDivision::Four; div = 4.;
358 } else if sleep_time < 16. {
359 division = WakeupDivision::Eight; div = 8.;
361 } else {
362 division = WakeupDivision::Sixteen; div = 16.;
364 }
365 clock_cfg = ClockConfig::One(division);
366 wutr = sleep_time * lfe_freq / div - 1.
367 } else if sleep_time < 65_536. {
368 clock_cfg = ClockConfig::Two;
370 wutr = sleep_time; } else if sleep_time < 131_072. {
372 clock_cfg = ClockConfig::Three;
374 wutr = sleep_time - 65_537.;
375 } else {
376 panic!("Wakeup period must be between 0122.07µs and 36 hours.")
377 }
378
379 #[cfg(not(feature = "c0"))]
380 self.regs
381 .wutr()
382 .modify(|_, w| unsafe { w.wut().bits(wutr as u16) });
383
384 let word = match clock_cfg {
402 ClockConfig::One(division) => match division {
403 WakeupDivision::Sixteen => 0b000,
404 WakeupDivision::Eight => 0b001,
405 WakeupDivision::Four => 0b010,
406 WakeupDivision::Two => 0b011,
407 },
408 ClockConfig::Two => 0b100, ClockConfig::Three => 0b110, };
412
413 #[cfg(not(feature = "c0"))]
414 self.regs
421 .cr()
422 .modify(|_, w| unsafe { w.wucksel().bits(word) });
423 }
424
425 #[cfg(not(any(feature = "f373", feature = "c0")))]
426 pub fn set_wakeup(&mut self, sleep_time: f32) -> Result<()> {
433 let exti = unsafe { &(*EXTI::ptr()) };
443
444 cfg_if! {
445 if #[cfg(any(feature = "f3", feature = "l4"))] {
446 exti.imr1().modify(|_, w| w.mr20().unmasked());
447 exti.rtsr1().modify(|_, w| w.tr20().bit(true));
448 exti.ftsr1().modify(|_, w| w.tr20().clear_bit());
449 } else if #[cfg(feature = "f4")] {
450 exti.imr().modify(|_, w| w.mr20().unmasked());
451 exti.rtsr().modify(|_, w| w.tr20().bit(true));
452 exti.ftsr().modify(|_, w| w.tr20().clear_bit());
453 } else if #[cfg(feature = "g4")]{
454 exti.imr1().modify(|_, w| w.im20().unmasked());
455 exti.rtsr1().modify(|_, w| w.rt20().bit(true));
456 exti.ftsr1().modify(|_, w| w.ft20().clear_bit());
457 } else if #[cfg(any(feature = "l5", feature = "g0", feature = "wb", feature = "wl", feature = "h5"))] {
458 } else if #[cfg(any(feature = "h747cm4", feature = "h747cm7"))] {
463 exti.c1imr1().modify(|_, w| w.mr20().unmasked());
464 exti.rtsr1().modify(|_, w| w.tr20().bit(true));
465 exti.ftsr1().modify(|_, w| w.tr20().clear_bit());
466 } else { exti.cpuimr1().modify(|_, w| w.mr20().unmasked());
468 exti.rtsr1().modify(|_, w| w.tr20().bit(true));
469 exti.ftsr1().modify(|_, w| w.tr20().clear_bit());
470 }
471 }
472
473 self.regs.wpr().write(|w| unsafe { w.bits(0xCA) });
476 self.regs.wpr().write(|w| unsafe { w.bits(0x53) });
477
478 self.regs.cr().modify(|_, w| w.wute().clear_bit());
480
481 cfg_if! {
484 if #[cfg(rtc_icsr)] {
485 bounded_loop!(self.regs.icsr().read().wutwf().bit_is_clear(), Error::RegisterUnchanged);
486 } else {
487 bounded_loop!(self.regs.isr().read().wutwf().bit_is_clear(), Error::RegisterUnchanged);
488 }
489 }
490
491 self.set_wakeup_interval_inner(sleep_time);
492 self.regs.cr().modify(|_, w| w.wute().bit(true));
495
496 self.regs.cr().modify(|_, w| w.wutie().bit(true));
498
499 cfg_if! {
500 if #[cfg(rtc_icsr)] {
501 self.regs.scr().write(|w| w.cwutf().bit(true));
502 } else {
503 self.regs.isr().modify(|_, w| w.wutf().clear_bit());
504 }
505 }
506
507 self.regs.wpr().write(|w| unsafe { w.bits(0xFF) });
508
509 Ok(())
510 }
511
512 #[cfg(not(feature = "c0"))]
513 pub fn enable_wakeup(&mut self) {
515 unsafe {
516 self.regs.wpr().write(|w| w.bits(0xCA));
517 self.regs.wpr().write(|w| w.bits(0x53));
518 self.regs.cr().modify(|_, w| w.wute().bit(true));
519 self.regs.wpr().write(|w| w.bits(0xFF));
520 }
521 }
522
523 #[cfg(not(feature = "c0"))]
524 pub fn disable_wakeup(&mut self) {
526 unsafe {
527 self.regs.wpr().write(|w| w.bits(0xCA));
528 self.regs.wpr().write(|w| w.bits(0x53));
529 self.regs.cr().modify(|_, w| w.wute().clear_bit());
530 self.regs.wpr().write(|w| w.bits(0xFF));
531 }
532 }
533
534 #[cfg(not(feature = "c0"))]
535 pub fn set_wakeup_interval(&mut self, sleep_time: f32) -> Result<()> {
538 self.regs.wpr().write(|w| unsafe { w.bits(0xCA) });
544 self.regs.wpr().write(|w| unsafe { w.bits(0x53) });
545
546 let started_enabled = self.regs.cr().read().wute().bit_is_set();
547 if started_enabled {
548 self.regs.cr().modify(|_, w| w.wute().clear_bit());
549 }
550
551 cfg_if! {
552 if #[cfg(rtc_icsr)] {
553 bounded_loop!(self.regs.icsr().read().wutwf().bit_is_clear(), Error::RegisterUnchanged);
554 } else {
555 bounded_loop!(self.regs.isr().read().wutwf().bit_is_clear(), Error::RegisterUnchanged);
556 }
557 }
558
559 self.set_wakeup_interval_inner(sleep_time);
560
561 if started_enabled {
562 self.regs.cr().modify(|_, w| w.wute().bit(true));
563 }
564
565 self.regs.wpr().write(|w| unsafe { w.bits(0xFF) });
566
567 Ok(())
568 }
569
570 #[cfg(not(feature = "c0"))]
571 pub fn clear_wakeup_flag(&mut self) -> Result<()> {
574 self.edit_regs(false, |regs| {
575 regs.cr().modify(|_, w| w.wute().clear_bit());
576
577 cfg_if! {
578 if #[cfg(any(feature = "l412", feature = "l5", feature = "g0", feature = "g4", feature = "l412",
579 feature = "wl", feature = "h5", feature = "c0"))] {
580 regs.scr().write(|w| w.cwutf().bit(true));
581 } else {
582 regs.isr().modify(|_, w| w.wutf().clear_bit());
586 }
587 }
588
589 regs.cr().modify(|_, w| w.wute().bit(true));
590 })
591 }
592
593 fn edit_regs<F>(&mut self, init_mode: bool, mut closure: F) -> Result<()>
597 where
598 F: FnMut(&mut RTC),
599 {
600 self.regs.wpr().write(|w| unsafe { w.bits(0xCA) });
603 self.regs.wpr().write(|w| unsafe { w.bits(0x53) });
604
605 cfg_if! {
608 if #[cfg(rtc_icsr)] {
609 if init_mode && self.regs.icsr().read().initf().bit_is_clear() {
612 self.regs.icsr().modify(|_, w| w.init().bit(true));
614 bounded_loop!(self.regs.icsr().read().initf().bit_is_clear(), Error::RegisterUnchanged);
616 }
617
618 closure(&mut self.regs);
620
621 if init_mode {
622 self.regs.icsr().modify(|_, w| w.init().clear_bit()); bounded_loop!(self.regs.icsr().read().initf().bit_is_set(), Error::RegisterUnchanged);
624 }
625 } else {
638 if init_mode && self.regs.isr().read().initf().bit_is_clear() {
639 self.regs.isr().modify(|_, w| w.init().bit(true));
640 bounded_loop!(self.regs.isr().read().initf().bit_is_clear(), Error::RegisterUnchanged);
642 }
643
644 closure(&mut self.regs);
645
646 if init_mode {
647 self.regs.isr().modify(|_, w| w.init().clear_bit()); bounded_loop!(self.regs.isr().read().initf().bit_is_set(), Error::RegisterUnchanged);
649 }
650 }
651 }
652
653 self.regs.wpr().write(|w| unsafe { w.bits(0xFF) });
656
657 Ok(())
658 }
659
660 pub fn set_time(&mut self, time: &NaiveTime) -> Result<()> {
663 self.set_24h_fmt()?;
664 let (ht, hu) = bcd2_encode(time.hour())?;
665 let (mnt, mnu) = bcd2_encode(time.minute())?;
666 let (st, su) = bcd2_encode(time.second())?;
667
668 self.edit_regs(true, |regs| {
669 regs.tr().write(|w| unsafe {
670 w.ht().bits(ht);
671 w.hu().bits(hu);
672 w.mnt().bits(mnt);
673 w.mnu().bits(mnu);
674 w.st().bits(st);
675 w.su().bits(su);
676 w.pm().clear_bit()
677 });
678 })
679 }
680
681 pub fn set_seconds(&mut self, seconds: u8) -> Result<()> {
683 if seconds > 59 {
684 return Err(Error::RtcError(RtcError::InvalidInputData));
685 }
686 let (st, su) = bcd2_encode(seconds as u32)?;
687 self.edit_regs(true, |regs| {
688 regs.tr()
689 .modify(|_, w| unsafe { w.st().bits(st).su().bits(su) });
690 })
691 }
692
693 pub fn set_minutes(&mut self, minutes: u8) -> Result<()> {
695 if minutes > 59 {
696 return Err(Error::RtcError(RtcError::InvalidInputData));
697 }
698 let (mnt, mnu) = bcd2_encode(minutes as u32)?;
699 self.edit_regs(true, |regs| {
700 regs.tr()
701 .modify(|_, w| unsafe { w.mnt().bits(mnt).mnu().bits(mnu) });
702 })
703 }
704
705 pub fn set_hours(&mut self, hours: u8) -> Result<()> {
707 let (ht, hu) = bcd2_encode(hours as u32)?;
708
709 self.edit_regs(true, |regs| {
710 regs.tr()
711 .modify(|_, w| unsafe { w.ht().bits(ht).hu().bits(hu) });
712 })
713 }
714
715 pub fn set_weekday(&mut self, weekday: u8) -> Result<()> {
717 if !(1..=7).contains(&weekday) {
718 return Err(Error::RtcError(RtcError::InvalidInputData));
719 }
720 self.edit_regs(true, |regs| {
721 regs.dr().modify(|_, w| unsafe { w.wdu().bits(weekday) });
722 })
723 }
724
725 pub fn set_day(&mut self, day: u8) -> Result<()> {
727 if !(1..=31).contains(&day) {
728 return Err(Error::RtcError(RtcError::InvalidInputData));
729 }
730 let (dt, du) = bcd2_encode(day as u32)?;
731 self.edit_regs(true, |regs| {
732 regs.dr()
733 .modify(unsafe { |_, w| w.dt().bits(dt).du().bits(du) });
734 })
735 }
736
737 pub fn set_month(&mut self, month: u8) -> Result<()> {
739 if !(1..=12).contains(&month) {
740 return Err(Error::RtcError(RtcError::InvalidInputData));
741 }
742 let (mt, mu) = bcd2_encode(month as u32)?;
743 self.edit_regs(true, |regs| {
744 regs.dr()
745 .modify(|_, w| unsafe { w.mt().bit(mt > 0).mu().bits(mu) });
746 })
747 }
748
749 pub fn set_year(&mut self, year: u16) -> Result<()> {
751 if !(1970..=2038).contains(&year) {
752 return Err(Error::RtcError(RtcError::InvalidInputData));
754 }
755 let (yt, yu) = bcd2_encode(year as u32 - 2_000)?;
756 self.edit_regs(true, |regs| {
758 regs.dr()
759 .modify(|_, w| unsafe { w.yt().bits(yt).yu().bits(yu) });
760 })
761 }
762
763 pub fn set_date(&mut self, date: &NaiveDate) -> Result<()> {
766 if date.year() <= 1970 {
767 return Err(Error::RtcError(RtcError::InvalidInputData));
768 }
769
770 let (yt, yu) = bcd2_encode((date.year() - 2_000) as u32)?;
771 let (mt, mu) = bcd2_encode(date.month())?;
772 let (dt, du) = bcd2_encode(date.day())?;
773
774 let wd = date.weekday().number_from_monday() as u8;
775
776 self.edit_regs(true, |regs| {
777 regs.dr().write(|w| unsafe {
778 w.dt().bits(dt);
779 w.du().bits(du);
780 w.mt().bit(mt > 0);
781 w.mu().bits(mu);
782 w.yt().bits(yt);
783 w.yu().bits(yu);
784 w.wdu().bits(wd)
785 });
786 })
787 }
788
789 pub fn set_datetime(&mut self, date: &NaiveDateTime) -> Result<()> {
791 if date.year() <= 1970 {
792 return Err(Error::RtcError(RtcError::InvalidInputData));
793 }
794
795 self.set_24h_fmt()?;
796
797 let (yt, yu) = bcd2_encode((date.year() - 2_000) as u32)?;
798 let (mt, mu) = bcd2_encode(date.month())?;
799 let (dt, du) = bcd2_encode(date.day())?;
800
801 let (ht, hu) = bcd2_encode(date.hour())?;
802 let (mnt, mnu) = bcd2_encode(date.minute())?;
803 let (st, su) = bcd2_encode(date.second())?;
804
805 let wd = date.weekday().number_from_monday() as u8;
808
809 self.edit_regs(true, |regs| {
810 regs.dr().write(|w| unsafe {
811 w.dt().bits(dt);
812 w.du().bits(du);
813 w.mt().bit(mt > 0);
814 w.mu().bits(mu);
815 w.yt().bits(yt);
816 w.yu().bits(yu);
817 w.wdu().bits(wd)
818 });
819
820 regs.tr().write(|w| unsafe {
821 w.ht().bits(ht);
822 w.hu().bits(hu);
823 w.mnt().bits(mnt);
824 w.mnu().bits(mnu);
825 w.st().bits(st);
826 w.su().bits(su);
827 w.pm().clear_bit()
828 });
829 })?;
830
831 Ok(())
832 }
833
834 pub fn get_seconds(&mut self) -> u8 {
836 let tr = self.regs.tr().read();
837 bcd2_decode(tr.st().bits(), tr.su().bits()) as u8
838 }
839
840 pub fn get_minutes(&mut self) -> u8 {
842 let tr = self.regs.tr().read();
843 bcd2_decode(tr.mnt().bits(), tr.mnu().bits()) as u8
844 }
845
846 pub fn get_hours(&mut self) -> u8 {
848 let tr = self.regs.tr().read();
849 bcd2_decode(tr.ht().bits(), tr.hu().bits()) as u8
850 }
851
852 pub fn get_time(&mut self) -> NaiveTime {
854 let tr = self.regs.tr().read();
855 let _dr = self.regs.dr().read();
856
857 let hours = bcd2_decode(tr.ht().bits(), tr.hu().bits()) as u32;
858 let minutes = bcd2_decode(tr.mnt().bits(), tr.mnu().bits()) as u32;
859 let seconds = bcd2_decode(tr.st().bits(), tr.su().bits()) as u32;
860
861 NaiveTime::from_hms_opt(hours, minutes, seconds).unwrap()
862 }
863
864 pub fn get_weekday(&mut self) -> u8 {
866 let dr = self.regs.dr().read();
867 bcd2_decode(dr.wdu().bits(), 0x00) as u8
868 }
869
870 pub fn get_day(&mut self) -> u8 {
872 let dr = self.regs.dr().read();
873 bcd2_decode(dr.dt().bits(), dr.du().bits()) as u8
874 }
875
876 pub fn get_month(&mut self) -> u8 {
878 let dr = self.regs.dr().read();
879 let mt: u8 = if dr.mt().bit() { 1 } else { 0 };
880 bcd2_decode(mt, dr.mu().bits()) as u8
881 }
882
883 pub fn get_year(&mut self) -> u16 {
885 let dr = self.regs.dr().read();
886 (bcd2_decode(dr.yt().bits(), dr.yu().bits()) + 2000) as u16
887 }
888
889 pub fn get_date(&mut self) -> NaiveDate {
891 let tr = self.regs.tr().read();
892 let dr = self.regs.dr().read();
893
894 let _ = tr;
895
896 let year = (bcd2_decode(dr.yt().bits(), dr.yu().bits()) + 2000) as i32;
897 let month_tens: u8 = if dr.mt().bit() { 1 } else { 0 };
898 let month = bcd2_decode(month_tens, dr.mu().bits()) as u32;
899 let day = bcd2_decode(dr.dt().bits(), dr.du().bits()) as u32;
900
901 NaiveDate::from_ymd_opt(year, month, day).unwrap()
902 }
903
904 pub fn get_datetime(&mut self) -> NaiveDateTime {
906 let tr = self.regs.tr().read();
907 let dr = self.regs.dr().read();
908
909 let year = (bcd2_decode(dr.yt().bits(), dr.yu().bits()) + 2000) as i32;
910 let month_tens: u8 = if dr.mt().bit() { 1 } else { 0 };
911 let month = bcd2_decode(month_tens, dr.mu().bits()) as u32;
912 let day = bcd2_decode(dr.dt().bits(), dr.du().bits()) as u32;
913
914 let hours = bcd2_decode(tr.ht().bits(), tr.hu().bits()) as u32;
915 let minutes = bcd2_decode(tr.mnt().bits(), tr.mnu().bits()) as u32;
916 let seconds = bcd2_decode(tr.st().bits(), tr.su().bits()) as u32;
917
918 NaiveDate::from_ymd_opt(year, month, day)
919 .unwrap()
920 .and_hms_opt(hours, minutes, seconds)
921 .unwrap()
922 }
923}
924
925fn bcd2_encode(word: u32) -> Result<(u8, u8)> {
932 let l = match (word / 10).try_into() {
933 Ok(v) => v,
934 Err(_) => {
935 return Err(Error::RtcError(RtcError::InvalidInputData));
936 }
937 };
938 let r = match (word % 10).try_into() {
939 Ok(v) => v,
940 Err(_) => {
941 return Err(Error::RtcError(RtcError::InvalidInputData));
942 }
943 };
944
945 Ok((l, r))
946}
947
948fn bcd2_decode(fst: u8, snd: u8) -> u32 {
949 (fst * 10 + snd).into()
950}