1use crate::bb;
6use crate::pac::rtc::{dr, tr};
7use crate::pac::{self, rcc::RegisterBlock, 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, pwr: &mut PWR) -> Self {
125 Self::with_config(regs, pwr, LSEClockMode::Oscillator, 255, 127)
126 }
127 pub fn with_config(
132 regs: RTC,
133 pwr: &mut PWR,
134 clock_source: impl Into<ClockSource>,
135 prediv_s: u16,
136 prediv_a: u8,
137 ) -> Self {
138 let mut result = Self {
139 regs,
140 clock_source: clock_source.into(),
141 };
142
143 unsafe {
155 let rcc = &(*RCC::ptr());
156 result.unlock(rcc, pwr);
158 match result.clock_source {
159 ClockSource::Lse(mode) => {
160 if rcc.bdcr().read().lserdy().bit_is_clear() {
162 result.enable_lse(rcc, mode);
163 }
164 rcc.bdcr().modify(|_, w| w.rtcsel().lse());
166 }
167 ClockSource::Lsi => {
168 if rcc.csr().read().lsirdy().bit_is_clear() {
170 result.enable_lsi(rcc);
171 }
172 rcc.bdcr().modify(|_, w| w.rtcsel().lsi());
174 }
175 }
176 result.enable(rcc);
177 }
178
179 result.modify(true, |regs| {
180 regs.cr().modify(|_, w| w.fmt().clear_bit());
182 regs.prer().modify(|_, w| {
184 w.prediv_s().set(prediv_s);
185 w.prediv_a().set(prediv_a)
186 })
187 });
188
189 result
190 }
191
192 fn enable_lse(&mut self, rcc: &RegisterBlock, mode: LSEClockMode) {
195 unsafe {
196 self.backup_reset(rcc);
198 bb::set(rcc.bdcr(), 0);
201 match mode {
202 LSEClockMode::Bypass => bb::set(rcc.bdcr(), 2),
204 LSEClockMode::Oscillator => bb::clear(rcc.bdcr(), 2),
206 }
207 while rcc.bdcr().read().lserdy().bit_is_clear() {}
208 }
209 }
210
211 pub fn new_lsi(regs: RTC, pwr: &mut PWR) -> Self {
213 Self::with_config(regs, pwr, ClockSource::Lsi, 249, 127)
214 }
215
216 pub fn lsi_with_config(regs: RTC, pwr: &mut PWR, prediv_s: u16, prediv_a: u8) -> Self {
221 Self::with_config(regs, pwr, ClockSource::Lsi, prediv_s, prediv_a)
222 }
223
224 fn enable_lsi(&mut self, rcc: &RegisterBlock) {
225 self.backup_reset(rcc);
227 rcc.csr().modify(|_, w| w.lsion().on());
229 while rcc.csr().read().lsirdy().is_not_ready() {}
230 }
231
232 fn unlock(&mut self, rcc: &RegisterBlock, pwr: &mut PWR) {
233 PWR::enable(rcc);
236
237 pwr.cr().modify(|_, w| w.dbp().set_bit());
239 }
240
241 fn backup_reset(&mut self, rcc: &RegisterBlock) {
242 unsafe {
243 bb::set(rcc.bdcr(), 16);
245 bb::clear(rcc.bdcr(), 16);
247 }
248 }
249
250 fn enable(&mut self, rcc: &RegisterBlock) {
251 unsafe {
254 bb::set(rcc.bdcr(), 15);
255 }
256 }
257
258 pub fn set_prescalers(&mut self, prediv_s: u16, prediv_a: u8) {
259 self.modify(true, |regs| {
260 regs.prer().modify(|_, w| {
262 w.prediv_s().set(prediv_s);
263 w.prediv_a().set(prediv_a)
264 })
265 });
266 }
267
268 fn modify<F>(&mut self, init_mode: bool, mut closure: F)
272 where
273 F: FnMut(&mut RTC),
274 {
275 self.regs.wpr().write(|w| unsafe { w.bits(0xCA) });
278 self.regs.wpr().write(|w| unsafe { w.bits(0x53) });
279 if init_mode && self.regs.isr().read().initf().bit_is_clear() {
281 self.regs.isr().modify(|_, w| w.init().set_bit());
282 while self.regs.isr().read().initf().bit_is_clear() {}
285 }
286 closure(&mut self.regs);
288 if init_mode {
290 self.regs.isr().modify(|_, w| w.init().clear_bit());
291 }
292 while !self.regs.isr().read().initf().bit_is_clear() {}
294
295 self.regs.wpr().write(|w| unsafe { w.bits(0xFF) });
298 }
299
300 pub fn set_time(&mut self, time: &Time) -> Result<(), Error> {
302 let (ht, hu) = bcd2_encode(time.hour().into())?;
303 let (mnt, mnu) = bcd2_encode(time.minute().into())?;
304 let (st, su) = bcd2_encode(time.second().into())?;
305 self.modify(true, |regs| {
306 regs.tr().write(|w| {
307 w.ht().set(ht);
308 w.hu().set(hu);
309 w.mnt().set(mnt);
310 w.mnu().set(mnu);
311 w.st().set(st);
312 w.su().set(su);
313 w.pm().clear_bit()
314 })
315 });
316
317 Ok(())
318 }
319
320 pub fn set_seconds(&mut self, seconds: u8) -> Result<(), Error> {
322 if seconds > 59 {
323 return Err(Error::InvalidInputData);
324 }
325 let (st, su) = bcd2_encode(seconds.into())?;
326 self.modify(true, |regs| {
327 regs.tr().modify(|_, w| w.st().set(st).su().set(su))
328 });
329
330 Ok(())
331 }
332
333 pub fn set_minutes(&mut self, minutes: u8) -> Result<(), Error> {
335 if minutes > 59 {
336 return Err(Error::InvalidInputData);
337 }
338 let (mnt, mnu) = bcd2_encode(minutes.into())?;
339 self.modify(true, |regs| {
340 regs.tr().modify(|_, w| w.mnt().set(mnt).mnu().set(mnu))
341 });
342
343 Ok(())
344 }
345
346 pub fn set_hours(&mut self, hours: u8) -> Result<(), Error> {
348 if hours > 23 {
349 return Err(Error::InvalidInputData);
350 }
351 let (ht, hu) = bcd2_encode(hours.into())?;
352
353 self.modify(true, |regs| {
354 regs.tr().modify(|_, w| w.ht().set(ht).hu().set(hu))
355 });
356
357 Ok(())
358 }
359
360 pub fn set_weekday(&mut self, weekday: u8) -> Result<(), Error> {
362 if !(1..=7).contains(&weekday) {
363 return Err(Error::InvalidInputData);
364 }
365 self.modify(true, |regs| {
366 regs.dr().modify(|_, w| unsafe { w.wdu().bits(weekday) })
367 });
368
369 Ok(())
370 }
371
372 pub fn set_day(&mut self, day: u8) -> Result<(), Error> {
374 if !(1..=31).contains(&day) {
375 return Err(Error::InvalidInputData);
376 }
377 let (dt, du) = bcd2_encode(day as u32)?;
378 self.modify(true, |regs| {
379 regs.dr().modify(|_, w| w.dt().set(dt).du().set(du))
380 });
381
382 Ok(())
383 }
384
385 pub fn set_month(&mut self, month: u8) -> Result<(), Error> {
387 if !(1..=12).contains(&month) {
388 return Err(Error::InvalidInputData);
389 }
390 let (mt, mu) = bcd2_encode(month as u32)?;
391 self.modify(true, |regs| {
392 regs.dr().modify(|_, w| w.mt().bit(mt > 0).mu().set(mu))
393 });
394
395 Ok(())
396 }
397
398 pub fn set_year(&mut self, year: u16) -> Result<(), Error> {
403 if !(1970..=2069).contains(&year) {
404 return Err(Error::InvalidInputData);
405 }
406 let (yt, yu) = bcd2_encode(year as u32 - 1970)?;
407 self.modify(true, |regs| {
408 regs.dr().modify(|_, w| w.yt().set(yt).yu().set(yu))
409 });
410
411 Ok(())
412 }
413
414 pub fn set_date(&mut self, date: &Date) -> Result<(), Error> {
419 if !(1970..=2069).contains(&date.year()) {
420 return Err(Error::InvalidInputData);
421 }
422
423 let (yt, yu) = bcd2_encode((date.year() - 1970) as u32)?;
424 let (mt, mu) = bcd2_encode(u8::from(date.month()).into())?;
425 let (dt, du) = bcd2_encode(date.day().into())?;
426 let wdu = date.weekday().number_from_monday();
427
428 self.modify(true, |regs| {
429 regs.dr().write(|w| {
430 w.dt().set(dt);
431 w.du().set(du);
432 w.mt().bit(mt > 0);
433 w.mu().set(mu);
434 w.yt().set(yt);
435 w.yu().set(yu);
436 unsafe { w.wdu().bits(wdu) }
437 })
438 });
439
440 Ok(())
441 }
442
443 pub fn set_datetime(&mut self, date: &PrimitiveDateTime) -> Result<(), Error> {
448 if !(1970..=2069).contains(&date.year()) {
449 return Err(Error::InvalidInputData);
450 }
451
452 let (yt, yu) = bcd2_encode((date.year() - 1970) as u32)?;
453 let (mt, mu) = bcd2_encode(u8::from(date.month()).into())?;
454 let (dt, du) = bcd2_encode(date.day().into())?;
455 let wdu = date.weekday().number_from_monday();
456
457 let (ht, hu) = bcd2_encode(date.hour().into())?;
458 let (mnt, mnu) = bcd2_encode(date.minute().into())?;
459 let (st, su) = bcd2_encode(date.second().into())?;
460
461 self.modify(true, |regs| {
462 regs.dr().write(|w| {
463 w.dt().set(dt);
464 w.du().set(du);
465 w.mt().bit(mt > 0);
466 w.mu().set(mu);
467 w.yt().set(yt);
468 w.yu().set(yu);
469 unsafe { w.wdu().bits(wdu) }
470 });
471 regs.tr().write(|w| {
472 w.ht().set(ht);
473 w.hu().set(hu);
474 w.mnt().set(mnt);
475 w.mnu().set(mnu);
476 w.st().set(st);
477 w.su().set(su);
478 w.pm().clear_bit()
479 })
480 });
481
482 Ok(())
483 }
484
485 pub fn get_datetime(&mut self) -> PrimitiveDateTime {
486 while self.regs.isr().read().rsf().bit_is_clear() {}
488
489 let ss = self.regs.ssr().read().ss().bits();
492 let tr = self.regs.tr().read();
493 let dr = self.regs.dr().read();
494 self.regs.isr().modify(|_, w| w.rsf().clear_bit());
497
498 let seconds = decode_seconds(&tr);
499 let minutes = decode_minutes(&tr);
500 let hours = decode_hours(&tr);
501 let day = decode_day(&dr);
502 let month = decode_month(&dr);
503 let year = decode_year(&dr);
504 let prediv_s = self.regs.prer().read().prediv_s().bits();
505 let nano = ss_to_nano(ss, prediv_s);
506
507 PrimitiveDateTime::new(
508 Date::from_calendar_date(year.into(), month.try_into().unwrap(), day).unwrap(),
509 Time::from_hms_nano(hours, minutes, seconds, nano).unwrap(),
510 )
511 }
512
513 pub fn enable_wakeup(&mut self, interval: fugit::MicrosDurationU64) {
519 let clock_source = self.clock_source;
520 self.modify(false, |regs| {
521 regs.cr().modify(|_, w| w.wute().clear_bit());
522 regs.isr().modify(|_, w| w.wutf().clear_bit());
523 while regs.isr().read().wutwf().bit_is_clear() {}
524
525 use crate::pac::rtc::cr::WUCKSEL;
526 if interval < fugit::MicrosDurationU64::secs(32) {
527 let frequency: fugit::Hertz<u64> = (clock_source.frequency() / 2).into();
529 let freq_duration: fugit::MicrosDurationU64 = frequency.into_duration();
530 let ticks_per_interval = interval / freq_duration;
531
532 let mut prescaler = 0;
533 while ticks_per_interval >> prescaler > 1 << 16 {
534 prescaler += 1;
535 }
536
537 let wucksel = match prescaler {
538 0 => WUCKSEL::Div2,
539 1 => WUCKSEL::Div4,
540 2 => WUCKSEL::Div8,
541 3 => WUCKSEL::Div16,
542 _ => unreachable!("Longer durations should use ck_spre"),
543 };
544
545 let interval = u16::try_from((ticks_per_interval >> prescaler) - 1).unwrap();
546
547 regs.cr().modify(|_, w| w.wucksel().variant(wucksel));
548 regs.wutr().write(|w| w.wut().set(interval));
549 } else {
550 let interval = interval.to_secs();
552 if interval > 1 << 16 {
553 regs.cr()
554 .modify(|_, w| w.wucksel().variant(WUCKSEL::ClockSpareWithOffset));
555 let interval = u16::try_from(interval - (1 << 16) - 1)
556 .expect("Interval was too large for wakeup timer");
557 regs.wutr().write(|w| w.wut().set(interval));
558 } else {
559 regs.cr()
560 .modify(|_, w| w.wucksel().variant(WUCKSEL::ClockSpare));
561 let interval = u16::try_from(interval - 1)
562 .expect("Interval was too large for wakeup timer");
563 regs.wutr().write(|w| w.wut().set(interval));
564 }
565 }
566
567 regs.cr().modify(|_, w| w.wute().set_bit());
568 });
569 }
570
571 pub fn disable_wakeup(&mut self) {
573 self.modify(false, |regs| {
574 regs.cr().modify(|_, w| w.wute().clear_bit());
575 regs.isr().modify(|_, w| w.wutf().clear_bit());
576 });
577 }
578
579 pub fn enable_vbat_timestamp(&mut self) {
581 self.modify(false, |regs| {
582 regs.cr().modify(|_, w| w.tse().clear_bit());
583 regs.isr().modify(|_, w| w.tsf().clear_bit());
584 regs.cr().modify(|_, w| w.tse().set_bit());
585 });
586 }
587
588 pub fn disable_timestamp(&mut self) {
590 self.modify(false, |regs| {
591 regs.cr().modify(|_, w| w.tse().clear_bit());
592 regs.isr().modify(|_, w| w.tsf().clear_bit());
593 });
594 }
595
596 pub fn read_timestamp(&self) -> PrimitiveDateTime {
600 while self.regs.isr().read().rsf().bit_is_clear() {}
601
602 let ss = self.regs.tsssr().read().ss().bits();
604
605 let tr = self.regs.tstr().read();
607 let dr = self.regs.tsdr().read();
608 let dry = self.regs.dr().read();
609 let seconds = decode_seconds(&tr);
610 let minutes = decode_minutes(&tr);
611 let hours = decode_hours(&tr);
612 let day = decode_day(&dr);
613 let month = decode_month(&dr);
614 let year = decode_year(&dry);
615 let prediv_s = self.regs.prer().read().prediv_s().bits();
616 let nano = ss_to_nano(ss, prediv_s);
617
618 PrimitiveDateTime::new(
619 Date::from_calendar_date(year.into(), month.try_into().unwrap(), day).unwrap(),
620 Time::from_hms_nano(hours, minutes, seconds, nano).unwrap(),
621 )
622 }
623
624 pub fn set_alarm(
627 &mut self,
628 alarm: Alarm,
629 date: impl Into<AlarmDay>,
630 time: Time,
631 ) -> Result<(), Error> {
632 let date = date.into();
633 let (daymask, wdsel, (dt, du)) = match date {
634 AlarmDay::Date(date) => (false, false, bcd2_encode(date.day().into())?),
635 AlarmDay::Weekday(weekday) => (false, true, (0, weekday.number_days_from_monday())),
636 AlarmDay::EveryDay => (true, false, (0, 0)),
637 };
638 let (ht, hu) = bcd2_encode(time.hour().into())?;
639 let (mnt, mnu) = bcd2_encode(time.minute().into())?;
640 let (st, su) = bcd2_encode(time.second().into())?;
641
642 self.modify(false, |rtc| {
643 unsafe {
644 bb::clear(rtc.cr(), 8 + (alarm as u8));
645 bb::clear(rtc.isr(), 8 + (alarm as u8));
646 }
647 while rtc.isr().read().bits() & (1 << (alarm as u32)) == 0 {}
648 let reg = rtc.alrmr(alarm as usize);
649 reg.modify(|_, w| {
650 w.dt().set(dt);
651 w.du().set(du);
652 w.ht().set(ht);
653 w.hu().set(hu);
654 w.mnt().set(mnt);
655 w.mnu().set(mnu);
656 w.st().set(st);
657 w.su().set(su);
658 w.pm().clear_bit();
659 w.wdsel().bit(wdsel);
660 w.msk4().bit(daymask)
661 });
662 unsafe {
668 bb::set(rtc.cr(), 8 + (alarm as u8));
669 }
670 });
671 Ok(())
672 }
673
674 pub fn listen(&mut self, exti: &mut pac::EXTI, event: Event) {
676 self.modify(false, |regs| match event {
681 Event::AlarmA => {
682 exti.rtsr().modify(|_, w| w.tr17().enabled());
683 exti.imr().modify(|_, w| w.mr17().set_bit());
684 regs.cr().modify(|_, w| w.alraie().set_bit());
685 }
686 Event::AlarmB => {
687 exti.rtsr().modify(|_, w| w.tr17().enabled());
688 exti.imr().modify(|_, w| w.mr17().set_bit());
689 regs.cr().modify(|_, w| w.alrbie().set_bit());
690 }
691 Event::Wakeup => {
692 exti.rtsr().modify(|_, w| w.tr22().enabled());
693 exti.imr().modify(|_, w| w.mr22().set_bit());
694 regs.cr().modify(|_, w| w.wutie().set_bit());
695 }
696 Event::Timestamp => {
697 exti.rtsr().modify(|_, w| w.tr21().enabled());
698 exti.imr().modify(|_, w| w.mr21().set_bit());
699 regs.cr().modify(|_, w| w.tsie().set_bit());
700 }
701 });
702 }
703
704 pub fn unlisten(&mut self, exti: &mut pac::EXTI, event: Event) {
706 self.modify(false, |regs| match event {
708 Event::AlarmA => {
709 regs.cr().modify(|_, w| w.alraie().clear_bit());
710 exti.imr().modify(|_, w| w.mr17().clear_bit());
711 exti.rtsr().modify(|_, w| w.tr17().disabled());
712 }
713 Event::AlarmB => {
714 regs.cr().modify(|_, w| w.alrbie().clear_bit());
715 exti.imr().modify(|_, w| w.mr17().clear_bit());
716 exti.rtsr().modify(|_, w| w.tr17().disabled());
717 }
718 Event::Wakeup => {
719 regs.cr().modify(|_, w| w.wutie().clear_bit());
720 exti.imr().modify(|_, w| w.mr22().clear_bit());
721 exti.rtsr().modify(|_, w| w.tr22().disabled());
722 }
723 Event::Timestamp => {
724 regs.cr().modify(|_, w| w.tsie().clear_bit());
725 exti.imr().modify(|_, w| w.mr21().clear_bit());
726 exti.rtsr().modify(|_, w| w.tr21().disabled());
727 }
728 });
729 }
730
731 pub fn is_pending(&self, event: Event) -> bool {
733 match event {
734 Event::AlarmA => self.regs.isr().read().alraf().bit_is_set(),
735 Event::AlarmB => self.regs.isr().read().alrbf().bit_is_set(),
736 Event::Wakeup => self.regs.isr().read().wutf().bit_is_set(),
737 Event::Timestamp => self.regs.isr().read().tsf().bit_is_set(),
738 }
739 }
740
741 pub fn clear_interrupt(&mut self, event: Event) {
743 match event {
744 Event::AlarmA => {
745 self.regs.isr().modify(|_, w| w.alraf().clear_bit());
746 unsafe {
747 (*pac::EXTI::ptr())
748 .pr()
749 .write(|w| w.pr17().clear_bit_by_one())
750 };
751 }
752 Event::AlarmB => {
753 self.regs.isr().modify(|_, w| w.alrbf().clear_bit());
754 unsafe {
755 (*pac::EXTI::ptr())
756 .pr()
757 .write(|w| w.pr17().clear_bit_by_one())
758 };
759 }
760 Event::Wakeup => {
761 self.regs.isr().modify(|_, w| w.wutf().clear_bit());
762 unsafe {
763 (*pac::EXTI::ptr())
764 .pr()
765 .write(|w| w.pr22().clear_bit_by_one())
766 };
767 }
768 Event::Timestamp => {
769 self.regs.isr().modify(|_, w| w.tsf().clear_bit());
770 unsafe {
771 (*pac::EXTI::ptr())
772 .pr()
773 .write(|w| w.pr21().clear_bit_by_one())
774 };
775 }
776 }
777 }
778}
779
780fn bcd2_encode(word: u32) -> Result<(u8, u8), Error> {
787 let l = match (word / 10).try_into() {
788 Ok(v) => v,
789 Err(_) => {
790 return Err(Error::InvalidInputData);
791 }
792 };
793 let r = match (word % 10).try_into() {
794 Ok(v) => v,
795 Err(_) => {
796 return Err(Error::InvalidInputData);
797 }
798 };
799
800 Ok((l, r))
801}
802
803const fn bcd2_decode(fst: u8, snd: u8) -> u8 {
804 fst * 10 + snd
805}
806
807#[inline(always)]
808fn decode_seconds(tr: &tr::R) -> u8 {
809 bcd2_decode(tr.st().bits(), tr.su().bits())
810}
811
812#[inline(always)]
813fn decode_minutes(tr: &tr::R) -> u8 {
814 bcd2_decode(tr.mnt().bits(), tr.mnu().bits())
815}
816
817#[inline(always)]
818fn decode_hours(tr: &tr::R) -> u8 {
819 bcd2_decode(tr.ht().bits(), tr.hu().bits())
820}
821
822#[inline(always)]
823fn decode_day(dr: &dr::R) -> u8 {
824 bcd2_decode(dr.dt().bits(), dr.du().bits())
825}
826
827#[inline(always)]
828fn decode_month(dr: &dr::R) -> u8 {
829 let mt = u8::from(dr.mt().bit());
830 bcd2_decode(mt, dr.mu().bits())
831}
832
833#[inline(always)]
834fn decode_year(dr: &dr::R) -> u16 {
835 let year = (bcd2_decode(dr.yt().bits(), dr.yu().bits()) as u32) + 1970; year as u16
837}
838
839const fn ss_to_nano(ss: u16, prediv_s: u16) -> u32 {
840 let ss = ss as u32;
841 let prediv_s = prediv_s as u32;
842 assert!(ss <= prediv_s);
843
844 (((prediv_s - ss) * 100_000) / (prediv_s + 1)) * 10_000
845}