1use crate::bb;
6use crate::pac::rtc::{dr, tr};
7use crate::pac::{self, PWR, RCC, RTC};
8use crate::rcc::Enable;
9use core::fmt;
10use fugit::RateExtU32;
11use time::{Date, PrimitiveDateTime, Time, Weekday};
12
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15#[derive(Debug, Eq, PartialEq, Copy, Clone)]
16pub enum Error {
17 InvalidInputData,
18}
19
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21#[derive(Debug, Eq, PartialEq, Copy, Clone)]
22pub enum Event {
23 AlarmA,
24 AlarmB,
25 Wakeup,
26 Timestamp,
27}
28
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30#[derive(Debug, Eq, PartialEq, Copy, Clone)]
31pub enum Alarm {
32 AlarmA = 0,
33 AlarmB = 1,
34}
35
36impl From<Alarm> for Event {
37 fn from(a: Alarm) -> Self {
38 match a {
39 Alarm::AlarmA => Event::AlarmA,
40 Alarm::AlarmB => Event::AlarmB,
41 }
42 }
43}
44
45#[derive(Debug, Eq, PartialEq, Copy, Clone)]
46pub enum AlarmDay {
47 Date(Date),
48 Weekday(Weekday),
49 EveryDay,
50}
51
52impl From<Date> for AlarmDay {
53 fn from(date: Date) -> Self {
54 Self::Date(date)
55 }
56}
57
58impl From<Weekday> for AlarmDay {
59 fn from(day: Weekday) -> Self {
60 Self::Weekday(day)
61 }
62}
63
64pub struct Lse;
66pub struct Lsi;
68
69#[cfg_attr(feature = "defmt", derive(defmt::Format))]
70#[derive(Clone, Copy, Debug, PartialEq, Eq)]
71pub enum ClockSource {
72 Lse(LSEClockMode),
73 Lsi,
74}
75
76impl From<LSEClockMode> for ClockSource {
77 fn from(value: LSEClockMode) -> Self {
78 Self::Lse(value)
79 }
80}
81
82impl ClockSource {
83 pub fn frequency(self) -> fugit::Hertz<u32> {
84 match self {
85 Self::Lse(_) => 32_768_u32.Hz(),
86 Self::Lsi => 32.kHz(),
87 }
88 }
89}
90
91pub struct Rtc {
93 pub regs: RTC,
95 clock_source: ClockSource,
96}
97
98#[cfg(feature = "defmt")]
99impl defmt::Format for Rtc {
100 fn format(&self, f: defmt::Formatter) {
101 defmt::write!(f, "Rtc");
102 }
103}
104
105impl fmt::Debug for Rtc {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 f.write_str("Rtc")
108 }
109}
110
111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
113#[derive(Clone, Copy, Debug, PartialEq, Eq)]
114pub enum LSEClockMode {
115 Oscillator,
117 Bypass,
120}
121
122impl Rtc {
123 pub fn new(regs: RTC, rcc: &mut RCC, pwr: &mut PWR) -> Self {
125 Self::with_config(regs, rcc, pwr, LSEClockMode::Oscillator, 255, 127)
126 }
127 pub fn with_config(
132 regs: RTC,
133 rcc: &mut RCC,
134 pwr: &mut PWR,
135 clock_source: impl Into<ClockSource>,
136 prediv_s: u16,
137 prediv_a: u8,
138 ) -> Self {
139 let mut result = Self {
140 regs,
141 clock_source: clock_source.into(),
142 };
143
144 result.unlock(rcc, pwr);
157 match result.clock_source {
158 ClockSource::Lse(mode) => {
159 if rcc.bdcr().read().lserdy().bit_is_clear() {
161 result.enable_lse(rcc, mode);
162 }
163 rcc.bdcr().modify(|_, w| w.rtcsel().lse());
165 }
166 ClockSource::Lsi => {
167 if rcc.csr().read().lsirdy().bit_is_clear() {
169 result.enable_lsi(rcc);
170 }
171 rcc.bdcr().modify(|_, w| w.rtcsel().lsi());
173 }
174 }
175 result.enable(rcc);
176
177 result.modify(true, |regs| {
178 regs.cr().modify(|_, w| w.fmt().clear_bit());
180 regs.prer().modify(|_, w| {
182 w.prediv_s().set(prediv_s);
183 w.prediv_a().set(prediv_a)
184 });
185 });
186
187 result
188 }
189
190 fn enable_lse(&mut self, rcc: &mut RCC, mode: LSEClockMode) {
193 unsafe {
194 self.backup_reset(rcc);
196 bb::set(rcc.bdcr(), 0);
199 match mode {
200 LSEClockMode::Bypass => bb::set(rcc.bdcr(), 2),
202 LSEClockMode::Oscillator => bb::clear(rcc.bdcr(), 2),
204 }
205 while rcc.bdcr().read().lserdy().bit_is_clear() {}
206 }
207 }
208
209 pub fn new_lsi(regs: RTC, rcc: &mut RCC, pwr: &mut PWR) -> Self {
211 Self::with_config(regs, rcc, pwr, ClockSource::Lsi, 249, 127)
212 }
213
214 pub fn lsi_with_config(
219 regs: RTC,
220 rcc: &mut RCC,
221 pwr: &mut PWR,
222 prediv_s: u16,
223 prediv_a: u8,
224 ) -> Self {
225 Self::with_config(regs, rcc, pwr, ClockSource::Lsi, prediv_s, prediv_a)
226 }
227
228 fn enable_lsi(&mut self, rcc: &mut RCC) {
229 self.backup_reset(rcc);
231 rcc.csr().modify(|_, w| w.lsion().on());
233 while rcc.csr().read().lsirdy().is_not_ready() {}
234 }
235
236 fn unlock(&mut self, rcc: &mut RCC, pwr: &mut PWR) {
237 PWR::enable(rcc);
240
241 pwr.cr().modify(|_, w| w.dbp().set_bit());
243 }
244
245 fn backup_reset(&mut self, rcc: &mut RCC) {
246 unsafe {
247 bb::set(rcc.bdcr(), 16);
249 bb::clear(rcc.bdcr(), 16);
251 }
252 }
253
254 fn enable(&mut self, rcc: &mut RCC) {
255 unsafe {
258 bb::set(rcc.bdcr(), 15);
259 }
260 }
261
262 pub fn set_prescalers(&mut self, prediv_s: u16, prediv_a: u8) {
263 self.modify(true, |regs| {
264 regs.prer().modify(|_, w| {
266 w.prediv_s().set(prediv_s);
267 w.prediv_a().set(prediv_a)
268 });
269 });
270 }
271
272 fn modify<F>(&mut self, init_mode: bool, mut closure: F)
276 where
277 F: FnMut(&mut RTC),
278 {
279 self.regs.wpr().write(|w| unsafe { w.bits(0xCA) });
282 self.regs.wpr().write(|w| unsafe { w.bits(0x53) });
283 if init_mode && self.regs.isr().read().initf().bit_is_clear() {
285 self.regs.isr().modify(|_, w| w.init().set_bit());
286 while self.regs.isr().read().initf().bit_is_clear() {}
289 }
290 closure(&mut self.regs);
292 if init_mode {
294 self.regs.isr().modify(|_, w| w.init().clear_bit());
295 }
296 while !self.regs.isr().read().initf().bit_is_clear() {}
298
299 self.regs.wpr().write(|w| unsafe { w.bits(0xFF) });
302 }
303
304 pub fn set_time(&mut self, time: &Time) -> Result<(), Error> {
306 let (ht, hu) = bcd2_encode(time.hour().into())?;
307 let (mnt, mnu) = bcd2_encode(time.minute().into())?;
308 let (st, su) = bcd2_encode(time.second().into())?;
309 self.modify(true, |regs| {
310 regs.tr().write(|w| {
311 w.ht().set(ht);
312 w.hu().set(hu);
313 w.mnt().set(mnt);
314 w.mnu().set(mnu);
315 w.st().set(st);
316 w.su().set(su);
317 w.pm().clear_bit()
318 });
319 });
320
321 Ok(())
322 }
323
324 pub fn set_seconds(&mut self, seconds: u8) -> Result<(), Error> {
326 if seconds > 59 {
327 return Err(Error::InvalidInputData);
328 }
329 let (st, su) = bcd2_encode(seconds.into())?;
330 self.modify(true, |regs| {
331 regs.tr().modify(|_, w| w.st().set(st).su().set(su));
332 });
333
334 Ok(())
335 }
336
337 pub fn set_minutes(&mut self, minutes: u8) -> Result<(), Error> {
339 if minutes > 59 {
340 return Err(Error::InvalidInputData);
341 }
342 let (mnt, mnu) = bcd2_encode(minutes.into())?;
343 self.modify(true, |regs| {
344 regs.tr().modify(|_, w| w.mnt().set(mnt).mnu().set(mnu));
345 });
346
347 Ok(())
348 }
349
350 pub fn set_hours(&mut self, hours: u8) -> Result<(), Error> {
352 if hours > 23 {
353 return Err(Error::InvalidInputData);
354 }
355 let (ht, hu) = bcd2_encode(hours.into())?;
356
357 self.modify(true, |regs| {
358 regs.tr().modify(|_, w| w.ht().set(ht).hu().set(hu));
359 });
360
361 Ok(())
362 }
363
364 pub fn set_weekday(&mut self, weekday: u8) -> Result<(), Error> {
366 if !(1..=7).contains(&weekday) {
367 return Err(Error::InvalidInputData);
368 }
369 self.modify(true, |regs| {
370 regs.dr().modify(|_, w| unsafe { w.wdu().bits(weekday) });
371 });
372
373 Ok(())
374 }
375
376 pub fn set_day(&mut self, day: u8) -> Result<(), Error> {
378 if !(1..=31).contains(&day) {
379 return Err(Error::InvalidInputData);
380 }
381 let (dt, du) = bcd2_encode(day as u32)?;
382 self.modify(true, |regs| {
383 regs.dr().modify(|_, w| w.dt().set(dt).du().set(du));
384 });
385
386 Ok(())
387 }
388
389 pub fn set_month(&mut self, month: u8) -> Result<(), Error> {
391 if !(1..=12).contains(&month) {
392 return Err(Error::InvalidInputData);
393 }
394 let (mt, mu) = bcd2_encode(month as u32)?;
395 self.modify(true, |regs| {
396 regs.dr().modify(|_, w| w.mt().bit(mt > 0).mu().set(mu));
397 });
398
399 Ok(())
400 }
401
402 pub fn set_year(&mut self, year: u16) -> Result<(), Error> {
407 if !(1970..=2069).contains(&year) {
408 return Err(Error::InvalidInputData);
409 }
410 let (yt, yu) = bcd2_encode(year as u32 - 1970)?;
411 self.modify(true, |regs| {
412 regs.dr().modify(|_, w| w.yt().set(yt).yu().set(yu));
413 });
414
415 Ok(())
416 }
417
418 pub fn set_date(&mut self, date: &Date) -> Result<(), Error> {
423 if !(1970..=2069).contains(&date.year()) {
424 return Err(Error::InvalidInputData);
425 }
426
427 let (yt, yu) = bcd2_encode((date.year() - 1970) as u32)?;
428 let (mt, mu) = bcd2_encode(u8::from(date.month()).into())?;
429 let (dt, du) = bcd2_encode(date.day().into())?;
430 let wdu = date.weekday().number_from_monday();
431
432 self.modify(true, |regs| {
433 regs.dr().write(|w| {
434 w.dt().set(dt);
435 w.du().set(du);
436 w.mt().bit(mt > 0);
437 w.mu().set(mu);
438 w.yt().set(yt);
439 w.yu().set(yu);
440 unsafe { w.wdu().bits(wdu) }
441 });
442 });
443
444 Ok(())
445 }
446
447 pub fn set_datetime(&mut self, date: &PrimitiveDateTime) -> Result<(), Error> {
452 if !(1970..=2069).contains(&date.year()) {
453 return Err(Error::InvalidInputData);
454 }
455
456 let (yt, yu) = bcd2_encode((date.year() - 1970) as u32)?;
457 let (mt, mu) = bcd2_encode(u8::from(date.month()).into())?;
458 let (dt, du) = bcd2_encode(date.day().into())?;
459 let wdu = date.weekday().number_from_monday();
460
461 let (ht, hu) = bcd2_encode(date.hour().into())?;
462 let (mnt, mnu) = bcd2_encode(date.minute().into())?;
463 let (st, su) = bcd2_encode(date.second().into())?;
464
465 self.modify(true, |regs| {
466 regs.dr().write(|w| {
467 w.dt().set(dt);
468 w.du().set(du);
469 w.mt().bit(mt > 0);
470 w.mu().set(mu);
471 w.yt().set(yt);
472 w.yu().set(yu);
473 unsafe { w.wdu().bits(wdu) }
474 });
475 regs.tr().write(|w| {
476 w.ht().set(ht);
477 w.hu().set(hu);
478 w.mnt().set(mnt);
479 w.mnu().set(mnu);
480 w.st().set(st);
481 w.su().set(su);
482 w.pm().clear_bit()
483 });
484 });
485
486 Ok(())
487 }
488
489 pub fn get_datetime(&mut self) -> PrimitiveDateTime {
490 while self.regs.isr().read().rsf().bit_is_clear() {}
492
493 let ss = self.regs.ssr().read().ss().bits();
496 let tr = self.regs.tr().read();
497 let dr = self.regs.dr().read();
498 self.regs.isr().modify(|_, w| w.rsf().clear_bit());
501
502 let seconds = decode_seconds(&tr);
503 let minutes = decode_minutes(&tr);
504 let hours = decode_hours(&tr);
505 let day = decode_day(&dr);
506 let month = decode_month(&dr);
507 let year = decode_year(&dr);
508 let prediv_s = self.regs.prer().read().prediv_s().bits();
509 let nano = ss_to_nano(ss, prediv_s);
510
511 PrimitiveDateTime::new(
512 Date::from_calendar_date(year.into(), month.try_into().unwrap(), day).unwrap(),
513 Time::from_hms_nano(hours, minutes, seconds, nano).unwrap(),
514 )
515 }
516
517 pub fn enable_wakeup(&mut self, interval: fugit::MicrosDurationU64) {
523 let clock_source = self.clock_source;
524 self.modify(false, |regs| {
525 regs.cr().modify(|_, w| w.wute().clear_bit());
526 regs.isr().modify(|_, w| w.wutf().clear_bit());
527 while regs.isr().read().wutwf().bit_is_clear() {}
528
529 use crate::pac::rtc::cr::WUCKSEL;
530 if interval < fugit::MicrosDurationU64::secs(32) {
531 let frequency: fugit::Hertz<u64> = (clock_source.frequency() / 2).into();
533 let freq_duration: fugit::MicrosDurationU64 = frequency.into_duration();
534 let ticks_per_interval = interval / freq_duration;
535
536 let mut prescaler = 0;
537 while ticks_per_interval >> prescaler > 1 << 16 {
538 prescaler += 1;
539 }
540
541 let wucksel = match prescaler {
542 0 => WUCKSEL::Div2,
543 1 => WUCKSEL::Div4,
544 2 => WUCKSEL::Div8,
545 3 => WUCKSEL::Div16,
546 _ => unreachable!("Longer durations should use ck_spre"),
547 };
548
549 let interval = u16::try_from((ticks_per_interval >> prescaler) - 1).unwrap();
550
551 regs.cr().modify(|_, w| w.wucksel().variant(wucksel));
552 regs.wutr().write(|w| w.wut().set(interval));
553 } else {
554 let interval = interval.to_secs();
556 if interval > 1 << 16 {
557 regs.cr()
558 .modify(|_, w| w.wucksel().variant(WUCKSEL::ClockSpareWithOffset));
559 let interval = u16::try_from(interval - (1 << 16) - 1)
560 .expect("Interval was too large for wakeup timer");
561 regs.wutr().write(|w| w.wut().set(interval));
562 } else {
563 regs.cr()
564 .modify(|_, w| w.wucksel().variant(WUCKSEL::ClockSpare));
565 let interval = u16::try_from(interval - 1)
566 .expect("Interval was too large for wakeup timer");
567 regs.wutr().write(|w| w.wut().set(interval));
568 }
569 }
570
571 regs.cr().modify(|_, w| w.wute().set_bit());
572 });
573 }
574
575 pub fn disable_wakeup(&mut self) {
577 self.modify(false, |regs| {
578 regs.cr().modify(|_, w| w.wute().clear_bit());
579 regs.isr().modify(|_, w| w.wutf().clear_bit());
580 });
581 }
582
583 pub fn enable_vbat_timestamp(&mut self) {
585 self.modify(false, |regs| {
586 regs.cr().modify(|_, w| w.tse().clear_bit());
587 regs.isr().modify(|_, w| w.tsf().clear_bit());
588 regs.cr().modify(|_, w| w.tse().set_bit());
589 });
590 }
591
592 pub fn disable_timestamp(&mut self) {
594 self.modify(false, |regs| {
595 regs.cr().modify(|_, w| w.tse().clear_bit());
596 regs.isr().modify(|_, w| w.tsf().clear_bit());
597 });
598 }
599
600 pub fn read_timestamp(&self) -> PrimitiveDateTime {
604 while self.regs.isr().read().rsf().bit_is_clear() {}
605
606 let ss = self.regs.tsssr().read().ss().bits();
608
609 let tr = self.regs.tstr().read();
611 let dr = self.regs.tsdr().read();
612 let dry = self.regs.dr().read();
613 let seconds = decode_seconds(&tr);
614 let minutes = decode_minutes(&tr);
615 let hours = decode_hours(&tr);
616 let day = decode_day(&dr);
617 let month = decode_month(&dr);
618 let year = decode_year(&dry);
619 let prediv_s = self.regs.prer().read().prediv_s().bits();
620 let nano = ss_to_nano(ss, prediv_s);
621
622 PrimitiveDateTime::new(
623 Date::from_calendar_date(year.into(), month.try_into().unwrap(), day).unwrap(),
624 Time::from_hms_nano(hours, minutes, seconds, nano).unwrap(),
625 )
626 }
627
628 pub fn set_alarm(
631 &mut self,
632 alarm: Alarm,
633 date: impl Into<AlarmDay>,
634 time: Time,
635 ) -> Result<(), Error> {
636 let date = date.into();
637 let (daymask, wdsel, (dt, du)) = match date {
638 AlarmDay::Date(date) => (false, false, bcd2_encode(date.day().into())?),
639 AlarmDay::Weekday(weekday) => (false, true, (0, weekday.number_days_from_monday())),
640 AlarmDay::EveryDay => (true, false, (0, 0)),
641 };
642 let (ht, hu) = bcd2_encode(time.hour().into())?;
643 let (mnt, mnu) = bcd2_encode(time.minute().into())?;
644 let (st, su) = bcd2_encode(time.second().into())?;
645
646 self.modify(false, |rtc| {
647 unsafe {
648 bb::clear(rtc.cr(), 8 + (alarm as u8));
649 bb::clear(rtc.isr(), 8 + (alarm as u8));
650 }
651 while rtc.isr().read().bits() & (1 << (alarm as u32)) == 0 {}
652 let reg = rtc.alrmr(alarm as usize);
653 reg.modify(|_, w| {
654 w.dt().set(dt);
655 w.du().set(du);
656 w.ht().set(ht);
657 w.hu().set(hu);
658 w.mnt().set(mnt);
659 w.mnu().set(mnu);
660 w.st().set(st);
661 w.su().set(su);
662 w.pm().clear_bit();
663 w.wdsel().bit(wdsel);
664 w.msk4().bit(daymask)
665 });
666 unsafe {
672 bb::set(rtc.cr(), 8 + (alarm as u8));
673 }
674 });
675 Ok(())
676 }
677
678 pub fn listen(&mut self, exti: &mut pac::EXTI, event: Event) {
680 self.modify(false, |regs| match event {
685 Event::AlarmA => {
686 exti.rtsr().modify(|_, w| w.tr17().enabled());
687 exti.imr().modify(|_, w| w.mr17().set_bit());
688 regs.cr().modify(|_, w| w.alraie().set_bit());
689 }
690 Event::AlarmB => {
691 exti.rtsr().modify(|_, w| w.tr17().enabled());
692 exti.imr().modify(|_, w| w.mr17().set_bit());
693 regs.cr().modify(|_, w| w.alrbie().set_bit());
694 }
695 Event::Wakeup => {
696 exti.rtsr().modify(|_, w| w.tr22().enabled());
697 exti.imr().modify(|_, w| w.mr22().set_bit());
698 regs.cr().modify(|_, w| w.wutie().set_bit());
699 }
700 Event::Timestamp => {
701 exti.rtsr().modify(|_, w| w.tr21().enabled());
702 exti.imr().modify(|_, w| w.mr21().set_bit());
703 regs.cr().modify(|_, w| w.tsie().set_bit());
704 }
705 });
706 }
707
708 pub fn unlisten(&mut self, exti: &mut pac::EXTI, event: Event) {
710 self.modify(false, |regs| match event {
712 Event::AlarmA => {
713 regs.cr().modify(|_, w| w.alraie().clear_bit());
714 exti.imr().modify(|_, w| w.mr17().clear_bit());
715 exti.rtsr().modify(|_, w| w.tr17().disabled());
716 }
717 Event::AlarmB => {
718 regs.cr().modify(|_, w| w.alrbie().clear_bit());
719 exti.imr().modify(|_, w| w.mr17().clear_bit());
720 exti.rtsr().modify(|_, w| w.tr17().disabled());
721 }
722 Event::Wakeup => {
723 regs.cr().modify(|_, w| w.wutie().clear_bit());
724 exti.imr().modify(|_, w| w.mr22().clear_bit());
725 exti.rtsr().modify(|_, w| w.tr22().disabled());
726 }
727 Event::Timestamp => {
728 regs.cr().modify(|_, w| w.tsie().clear_bit());
729 exti.imr().modify(|_, w| w.mr21().clear_bit());
730 exti.rtsr().modify(|_, w| w.tr21().disabled());
731 }
732 });
733 }
734
735 pub fn is_pending(&self, event: Event) -> bool {
737 match event {
738 Event::AlarmA => self.regs.isr().read().alraf().bit_is_set(),
739 Event::AlarmB => self.regs.isr().read().alrbf().bit_is_set(),
740 Event::Wakeup => self.regs.isr().read().wutf().bit_is_set(),
741 Event::Timestamp => self.regs.isr().read().tsf().bit_is_set(),
742 }
743 }
744
745 pub fn clear_interrupt(&mut self, event: Event) {
747 match event {
748 Event::AlarmA => {
749 self.regs.isr().modify(|_, w| w.alraf().clear_bit());
750 unsafe {
751 (*pac::EXTI::ptr())
752 .pr()
753 .write(|w| w.pr17().clear_bit_by_one())
754 };
755 }
756 Event::AlarmB => {
757 self.regs.isr().modify(|_, w| w.alrbf().clear_bit());
758 unsafe {
759 (*pac::EXTI::ptr())
760 .pr()
761 .write(|w| w.pr17().clear_bit_by_one())
762 };
763 }
764 Event::Wakeup => {
765 self.regs.isr().modify(|_, w| w.wutf().clear_bit());
766 unsafe {
767 (*pac::EXTI::ptr())
768 .pr()
769 .write(|w| w.pr22().clear_bit_by_one())
770 };
771 }
772 Event::Timestamp => {
773 self.regs.isr().modify(|_, w| w.tsf().clear_bit());
774 unsafe {
775 (*pac::EXTI::ptr())
776 .pr()
777 .write(|w| w.pr21().clear_bit_by_one())
778 };
779 }
780 }
781 }
782}
783
784fn bcd2_encode(word: u32) -> Result<(u8, u8), Error> {
791 let l = match (word / 10).try_into() {
792 Ok(v) => v,
793 Err(_) => {
794 return Err(Error::InvalidInputData);
795 }
796 };
797 let r = match (word % 10).try_into() {
798 Ok(v) => v,
799 Err(_) => {
800 return Err(Error::InvalidInputData);
801 }
802 };
803
804 Ok((l, r))
805}
806
807const fn bcd2_decode(fst: u8, snd: u8) -> u8 {
808 fst * 10 + snd
809}
810
811#[inline(always)]
812fn decode_seconds(tr: &tr::R) -> u8 {
813 bcd2_decode(tr.st().bits(), tr.su().bits())
814}
815
816#[inline(always)]
817fn decode_minutes(tr: &tr::R) -> u8 {
818 bcd2_decode(tr.mnt().bits(), tr.mnu().bits())
819}
820
821#[inline(always)]
822fn decode_hours(tr: &tr::R) -> u8 {
823 bcd2_decode(tr.ht().bits(), tr.hu().bits())
824}
825
826#[inline(always)]
827fn decode_day(dr: &dr::R) -> u8 {
828 bcd2_decode(dr.dt().bits(), dr.du().bits())
829}
830
831#[inline(always)]
832fn decode_month(dr: &dr::R) -> u8 {
833 let mt = u8::from(dr.mt().bit());
834 bcd2_decode(mt, dr.mu().bits())
835}
836
837#[inline(always)]
838fn decode_year(dr: &dr::R) -> u16 {
839 let year = (bcd2_decode(dr.yt().bits(), dr.yu().bits()) as u32) + 1970; year as u16
841}
842
843const fn ss_to_nano(ss: u16, prediv_s: u16) -> u32 {
844 let ss = ss as u32;
845 let prediv_s = prediv_s as u32;
846 assert!(ss <= prediv_s);
847
848 (((prediv_s - ss) * 100_000) / (prediv_s + 1)) * 10_000
849}