1#![cfg_attr(not(test), no_std)]
2
3
4pub use chrono::{Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Weekday};
5pub use rtcc::{ DateTimeAccess };
6
7use embedded_hal::blocking::i2c::{Write, Read, WriteRead};
8
9const RV3028_ADDRESS: u8 = 0xA4 >> 1;
11
12const REG_SECONDS: u8 = 0x00;
14const REG_WEEKDAY: u8 = 0x03;
23
24const REG_DATE: u8 = 0x04;
28
29const REG_MINUTES_ALARM: u8 = 0x07;
39
40const REG_HOURS_ALARM: u8 = 0x08;
48
49const REG_WEEKDAY_DATE_ALARM: u8 = 0x09;
57
58const REG_TIMER_VALUE0: u8 = 0x0A;
64
65const REG_TIMER_STATUS0: u8 = 0x0C; const REG_STATUS: u8 = 0x0E;
78
79const REG_CONTROL1:u8 = 0x0F;
84
85const REG_CONTROL2:u8 = 0x10;
91
92const REG_CLOCK_INTERRUPT_MASK:u8 = 0x12;
98
99const REG_EVENT_CONTROL: u8 = 0x13;
101
102const REG_COUNT_EVENTS_TS: u8 = 0x14; const REG_UNIX_TIME_0: u8 = 0x1B;
114#[repr(u8)]
120enum RegControl1Bits {
121 TimerRepeatBit = 1 << 7,
123 WadaBit = 1 << 5,
125 UselBit = 1 << 4,
127 TimerEnableBit = 1 << 2,
130 TimerClockFreqBits = 0b11,
132}
133
134#[derive(Clone, Copy, Debug, PartialEq)]
136enum TimerClockFreq {
137 Hertz4096 = 0b00, Hertz64 = 0b01, Hertz1 = 0b10, HertzSixtieth = 0b11, }
142
143#[repr(u8)]
145enum RegStatusBits {
146 ClockIntFlagBit = 1 << 6,
149 BackupSwitchFlag = 1 << 5,
151 TimeUpdateFlag = 1 << 4,
153 PeriodicTimerFlag = 1 << 3,
155 AlarmFlagBit = 1 << 2,
157 EventFlagBit = 1 << 1,
159 PowerOnResetFlagBit = 1 << 0,
161}
162
163const EEPROM_MIRROR_ADDRESS: u8 = 0x37;#[repr(u8)]
171enum RegEventControlBits {
172 EventHighLowBit = 1 << 6,
174 EventFilteringTimeBits = 0b11 << 4,
176 TimeStampResetBit = 1 << 2,
178 TimeStampOverwriteBit = 1 << 1,
180 TimeStampSourceBit = 1 << 0,
182}
183
184pub const TS_EVENT_SOURCE_EVI: u8 = 0; pub const TS_EVENT_SOURCE_BSF: u8 = 1; #[repr(u8)]
189enum RegClockIntMaskBits {
190 ClockoutOnExtEvtBit = 1 << 3,
192 ClockoutOnAlarmBit = 1 << 2,
194 ClockoutOnPctBit = 1 << 1,
196 ClockoutOnUpdateBit = 1 << 0,
198}
199
200#[repr(u8)]
202enum RegControl2Bits {
203 TimeStampEnableBit = 1 << 7,
205 ClockoutIntEnableBit = 1 << 6,
207 TimeUpdateIntEnableBit = 1 << 5,
209 TimerIntEnableBit = 1 << 4,
211 AlarmIntEnableBit = 1 << 3,
213 EventIntEnableBit = 1 << 2,
215}
216
217#[repr(u8)]
219enum RegEepromMirrorBits {
220 ClockoutOutputEnableBit = 1 << 7,
222 BackupSwitchIntEnableBit = 1 << 6,
224 TrickleChargeEnableBit = 1 << 5,
226 BackupSwitchoverDsm = 0b01 << 2,
229 TrickleChargeResistanceBits = 0b11, }
231
232#[derive(Clone, Copy)]
233pub enum TrickleChargeCurrentLimiter {
234 Ohms3k = 0b00,
235 Ohms5k = 0b01,
236 Ohms9k = 0b10,
237 Ohms15k = 0b11,
238}
239
240const ALARM_NO_WATCH_FLAG: u8 = 1 << 7;
242
243
244pub struct RV3028<I2C> {
248 i2c: I2C,
249 mux_addr: u8,
250 mux_chan: u8,
251}
252
253impl<I2C, E> RV3028<I2C>
254 where
255 I2C: Write<Error = E> + Read<Error = E> + WriteRead<Error = E>,
256{
257
258 pub fn new(i2c: I2C) -> Self {
261 RV3028 {
262 i2c,
263 mux_addr: 0u8,
264 mux_chan: 0u8
265 }
266 }
267
268 pub fn new_with_mux(i2c: I2C, mux_addr: u8, mux_chan: u8) -> Self {
273 RV3028 {
274 i2c,
275 mux_addr,
276 mux_chan
277 }
278 }
279
280 fn bin_to_bcd(value: u8) -> u8 {
282 ((value / 10) << 4) | (value % 10)
283 }
284
285 fn bcd_to_bin(value: u8) -> u8 {
287 ((value & 0xF0) >> 4) * 10 + (value & 0x0F)
288 }
289
290 fn select_mux_channel(&mut self) -> Result<(), E> {
292 if self.mux_addr != 0u8 {
293 self.i2c.write(self.mux_addr, &[self.mux_chan])
294 }
295 else {
296 Ok(())
297 }
298 }
299
300 fn write_register_raw(&mut self, reg: u8, data: u8) -> Result<(), E> {
306 self.i2c.write(RV3028_ADDRESS, &[reg, data])
307 }
308
309 fn read_register_raw(&mut self, reg: u8) -> Result<u8, E> {
315 let mut buf = [0];
316 self.i2c.write_read(RV3028_ADDRESS, &[reg], &mut buf)?;
317 Ok(buf[0])
318 }
319
320
321 pub fn check_and_clear_power_on_reset(&mut self) -> Result<bool, E> {
329 let flag_set = 0 != self.check_and_clear_bits(
330 REG_STATUS, RegStatusBits::PowerOnResetFlagBit as u8)?;
331 Ok(flag_set)
332 }
333
334 pub fn check_and_clear_ext_event(&mut self)-> Result<bool, E> {
337 let flag_set = 0 != self.check_and_clear_bits(
338 REG_STATUS, RegStatusBits::EventFlagBit as u8)?;
339 Ok(flag_set)
340 }
341
342 fn set_reg_bits_raw(&mut self, reg: u8, bits: u8) -> Result<(), E> {
390 let mut reg_val = self.read_register_raw(reg)?;
391 reg_val |= bits; self.write_register_raw(reg, reg_val)
393 }
394
395 fn clear_reg_bits_raw(&mut self, reg: u8, bits: u8) -> Result<(), E> {
405 let mut reg_val = self.read_register_raw(reg)?;
406 reg_val &= !(bits); self.write_register_raw(reg, reg_val)
408 }
409
410 pub fn toggle_trickle_charge(&mut self, enable: bool,
416 limit_resistance: TrickleChargeCurrentLimiter) -> Result<bool, E> {
417 self.select_mux_channel()?;
418
419 self.clear_reg_bits_raw(
421 EEPROM_MIRROR_ADDRESS, RegEepromMirrorBits::TrickleChargeEnableBit as u8)?;
422 self.clear_reg_bits_raw(
424 EEPROM_MIRROR_ADDRESS, RegEepromMirrorBits::TrickleChargeResistanceBits as u8 )?;
425
426 if enable {
427 self.set_reg_bits_raw(EEPROM_MIRROR_ADDRESS, limit_resistance as u8)?; self.set_reg_bits_raw(
429 EEPROM_MIRROR_ADDRESS, RegEepromMirrorBits::TrickleChargeEnableBit as u8)?;
430 }
431
432 let conf_val =
434 0 != self.read_register_raw(EEPROM_MIRROR_ADDRESS)?
435 & RegEepromMirrorBits::TrickleChargeEnableBit as u8;
436 Ok(conf_val)
437 }
438
439 pub fn toggle_backup_switchover(&mut self, enable: bool) -> Result<bool, E> {
444 self.select_mux_channel()?;
445 self.set_or_clear_reg_bits_raw(
446 EEPROM_MIRROR_ADDRESS, RegEepromMirrorBits::BackupSwitchoverDsm as u8, enable)?;
447 let conf_val =
448 0 != self.read_register_raw(
449 EEPROM_MIRROR_ADDRESS)? & RegEepromMirrorBits::BackupSwitchoverDsm as u8;
450 Ok(conf_val)
451 }
452
453 pub fn clear_all_int_clockout_bits(&mut self) -> Result<(), E> {
455 self.select_mux_channel()?;
456 self.clear_reg_bits_raw(REG_CLOCK_INTERRUPT_MASK,
457 RegClockIntMaskBits::ClockoutOnExtEvtBit as u8 |
458 RegClockIntMaskBits::ClockoutOnAlarmBit as u8 |
459 RegClockIntMaskBits::ClockoutOnPctBit as u8 |
460 RegClockIntMaskBits::ClockoutOnUpdateBit as u8)
461 }
462
463
464 pub fn get_eeprom_mirror_value(&mut self) -> Result<u8, E> {
466 self.select_mux_channel()?;
467 let reg_val = self.read_register_raw(EEPROM_MIRROR_ADDRESS)?;
468 Ok(reg_val)
469 }
470
471 fn set_time_raw(&mut self, time: &NaiveTime) -> Result<(), E> {
474 let write_buf = [
475 REG_SECONDS, Self::bin_to_bcd(time.second() as u8 ),
477 Self::bin_to_bcd(time.minute() as u8 ),
478 Self::bin_to_bcd(time.hour() as u8 )
479 ];
480 self.i2c.write(RV3028_ADDRESS, &write_buf)
481 }
482
483
484 fn set_date_raw(&mut self, date: &NaiveDate) -> Result<(), E> {
488 let year = if date.year() > 2000 { (date.year() - 2000) as u8} else {0};
489 let month = (date.month() % 13) as u8;
490 let day = (date.day() % 32) as u8;
491 let weekday = (date.weekday() as u8) % 7;
492
493 let write_buf = [
494 REG_WEEKDAY, Self::bin_to_bcd(weekday ),
496 Self::bin_to_bcd(day ),
497 Self::bin_to_bcd(month ),
498 Self::bin_to_bcd(year )
499 ];
500 self.i2c.write(RV3028_ADDRESS, &write_buf)
501 }
502
503 pub fn get_ymd(&mut self) -> Result<(i32, u8, u8), E> {
505 let mut read_buf = [0u8;3];
506 self.read_multi_registers(REG_DATE, &mut read_buf)?;
507 let day = Self::bcd_to_bin(read_buf[0]);
508 let month = Self::bcd_to_bin(read_buf[1]);
509 let year:i32 = Self::bcd_to_bin(read_buf[2]) as i32 + 2000;
510
511 Ok((year, month, day))
512 }
513
514 pub fn get_hms(&mut self) -> Result<(u8, u8, u8), E> {
516 let mut read_buf = [0u8;3];
517 self.read_multi_registers(REG_SECONDS, &mut read_buf)?;
518 let seconds = Self::bcd_to_bin(read_buf[0]);
519 let minutes = Self::bcd_to_bin(read_buf[1]);
520 let hours = Self::bcd_to_bin(read_buf[2]);
521 Ok( (hours, minutes, seconds) )
522 }
523
524 fn read_multi_registers(&mut self, reg: u8, read_buf: &mut [u8] ) -> Result<(), E> {
526 self.select_mux_channel()?;
527 self.read_multi_registers_raw(reg, read_buf)
528 }
529
530 fn read_multi_registers_raw(&mut self, reg: u8, read_buf: &mut [u8] ) -> Result<(), E> {
532 self.i2c.write_read(RV3028_ADDRESS, &[reg], read_buf)
533 }
534
535 pub fn set_unix_time(&mut self, unix_time: u32) -> Result<(), E> {
545 self.select_mux_channel()?;
546 self.set_unix_time_raw(unix_time)
547 }
548
549 fn set_unix_time_raw(&mut self, unix_time: u32) -> Result<(), E> {
551 let bytes = unix_time.to_le_bytes(); self.i2c.write(RV3028_ADDRESS, &[REG_UNIX_TIME_0, bytes[0], bytes[1], bytes[2], bytes[3]])
553 }
554
555 pub fn get_unix_time(&mut self) -> Result<u32, E> {
564 let mut read_buf = [0u8; 4];
565 self.read_multi_registers(REG_UNIX_TIME_0, &mut read_buf)?;
566 let val = u32::from_le_bytes(read_buf);
567 Ok(val)
568 }
569
570 pub fn get_unix_time_blocking(&mut self) -> Result<u32, E> {
574 loop {
575 let val1 = self.get_unix_time()?;
576 let val2 = self.get_unix_time()?;
577
578 if val1 == val2 {
579 return Ok(val2)
580 }
581 }
582 }
583
584 pub fn toggle_event_high_low(&mut self, high: bool) -> Result<(), E> {
586 self.set_or_clear_reg_bits(REG_EVENT_CONTROL, RegEventControlBits::EventHighLowBit as u8, high)
587 }
588
589 pub fn toggle_alarm_int_enable(&mut self, enable: bool) -> Result<(), E> {
591 self.set_or_clear_reg_bits(REG_CONTROL2, RegControl2Bits::AlarmIntEnableBit as u8, enable)
592 }
593
594 pub fn toggle_countdown_int_enable(&mut self, enable: bool) -> Result<(), E> {
597 self.set_or_clear_reg_bits(REG_CONTROL2, RegControl2Bits::TimerIntEnableBit as u8, enable)
598 }
599
600 pub fn toggle_ext_event_int_enable(&mut self, enable: bool) -> Result<(), E> {
606 self.set_or_clear_reg_bits(REG_CONTROL2, RegControl2Bits::EventIntEnableBit as u8, enable)
607 }
608
609 pub fn toggle_time_up_int_enable(&mut self, enable: bool) -> Result<(), E> {
612 self.set_or_clear_reg_bits(REG_CONTROL2, RegControl2Bits::TimeUpdateIntEnableBit as u8, enable)
613 }
614
615 pub fn clear_all_int_out_bits(&mut self) -> Result<(), E> {
617 self.select_mux_channel()?;
618 self.clear_reg_bits_raw(REG_CONTROL2,
620 RegControl2Bits::TimeUpdateIntEnableBit as u8 |
621 RegControl2Bits::TimerIntEnableBit as u8 |
622 RegControl2Bits::AlarmIntEnableBit as u8 |
623 RegControl2Bits::EventIntEnableBit as u8 )?;
624 self.clear_reg_bits_raw(
626 EEPROM_MIRROR_ADDRESS, RegEepromMirrorBits::BackupSwitchIntEnableBit as u8)?;
627
628 Ok(())
630 }
631
632
633 pub fn clear_all_status_flags(&mut self) -> Result<(), E> {
636 self.select_mux_channel()?;
637 self.clear_reg_bits_raw(REG_STATUS,
638 RegStatusBits::ClockIntFlagBit as u8 |
639 RegStatusBits::BackupSwitchFlag as u8 |
640 RegStatusBits::TimeUpdateFlag as u8 |
641 RegStatusBits::PeriodicTimerFlag as u8 |
642 RegStatusBits::AlarmFlagBit as u8 |
643 RegStatusBits::EventFlagBit as u8 |
644 RegStatusBits::PowerOnResetFlagBit as u8
645 )
646
647 }
648
649 pub fn configure_periodic_time_update(&mut self, minutes: bool, int_enable: bool) -> Result<(), E> {
651 self.select_mux_channel()?;
652
653 self.clear_reg_bits_raw(
663 REG_CONTROL2, RegControl2Bits::TimeUpdateIntEnableBit as u8)?;
664 self.clear_reg_bits_raw(REG_STATUS, RegStatusBits::TimeUpdateFlag as u8)?;
666 self.set_or_clear_reg_bits_raw(
668 REG_CONTROL1, RegControl1Bits::UselBit as u8, minutes)?;
669 self.set_or_clear_reg_bits_raw(
671 REG_CONTROL2, RegControl2Bits::TimeUpdateIntEnableBit as u8, int_enable)?;
672
673 Ok(())
674 }
675
676
677 pub fn check_and_clear_alarm(&mut self) -> Result<bool, E> {
680 let alarm_flag_set = 0 != self.check_and_clear_bits(
682 REG_STATUS, RegStatusBits::AlarmFlagBit as u8)?;
683 Ok(alarm_flag_set)
684 }
685
686 pub fn set_alarm(&mut self, datetime: &NaiveDateTime,
694 weekday: Option<Weekday>, match_day: bool, match_hour: bool, match_minute: bool) -> Result<(), E> {
695
696 self.select_mux_channel()?;
697 self.clear_reg_bits_raw(REG_STATUS, RegStatusBits::AlarmFlagBit as u8)?;
699
700 self.set_or_clear_reg_bits_raw(
710 REG_CONTROL1, RegControl1Bits::WadaBit as u8, !weekday.is_some())?;
711
712 let bcd_minute = Self::bin_to_bcd(datetime.time().minute() as u8);
713 self.write_register_raw(REG_MINUTES_ALARM,
714 if match_minute { bcd_minute }
715 else { ALARM_NO_WATCH_FLAG | bcd_minute })?;
716
717 let bcd_hour = Self::bin_to_bcd(datetime.time().hour() as u8);
718 self.write_register_raw(REG_HOURS_ALARM,
719 if match_hour { bcd_hour }
720 else { ALARM_NO_WATCH_FLAG | bcd_hour })?;
721
722 if let Some(inner_weekday) = weekday {
723 let bcd_weekday = Self::bin_to_bcd(inner_weekday as u8);
724 self.write_register_raw(REG_WEEKDAY_DATE_ALARM,
725 if match_day { bcd_weekday }
726 else { ALARM_NO_WATCH_FLAG | bcd_weekday }
727 )?;
728 }
729 else {
730 let bcd_day = Self::bin_to_bcd(datetime.date().day() as u8);
731 self.write_register_raw(REG_WEEKDAY_DATE_ALARM,
732 if match_day { bcd_day }
733 else { ALARM_NO_WATCH_FLAG | bcd_day })?;
734 }
735
736 self.clear_reg_bits_raw(REG_STATUS, RegStatusBits::AlarmFlagBit as u8)?;
738
739 Ok(())
740 }
741
742 pub fn get_alarm_datetime_wday_matches(&mut self)
746 -> Result<(NaiveDateTime, Option<Weekday>, bool, bool, bool), E> {
747
748 self.select_mux_channel()?;
749
750 let raw_day = self.read_register_raw(REG_WEEKDAY_DATE_ALARM)?;
751 let match_day = 0 == (raw_day & ALARM_NO_WATCH_FLAG);
752 let day = Self::bcd_to_bin(0x7F & raw_day);
753
754 let raw_hour = self.read_register_raw(REG_HOURS_ALARM)?;
755 let match_hour = 0 == (raw_hour & ALARM_NO_WATCH_FLAG);
756 let hour = Self::bcd_to_bin(0x7F & raw_hour);
757
758 let raw_minutes = self.read_register_raw(REG_MINUTES_ALARM)?;
759 let match_minutes = 0 == (raw_minutes & ALARM_NO_WATCH_FLAG);
760 let minutes = Self::bcd_to_bin(0x7F & raw_minutes);
761
762 let mut weekday = None;
763
764 let wada_state = self.read_register_raw(REG_CONTROL1)? & RegControl1Bits::WadaBit as u8;
765
766 let dt =
767 if 0 == wada_state {
768 weekday = Some(Weekday::try_from(day).unwrap());
770 NaiveDateTime::UNIX_EPOCH.with_hour(hour as u32).unwrap()
771 .with_minute(minutes as u32).unwrap()
772 }
773 else {
774 NaiveDateTime::UNIX_EPOCH.with_day(day as u32).unwrap()
776 .with_hour(hour as u32).unwrap()
777 .with_minute(minutes as u32).unwrap()
778 };
779
780 Ok((dt, weekday, match_day, match_hour, match_minutes))
781 }
782
783
784
785 fn set_or_clear_reg_bits(&mut self, reg: u8, bits: u8, set: bool) -> Result<(), E> {
787 self.select_mux_channel()?;
788 self.set_or_clear_reg_bits_raw(reg, bits, set)
789 }
790
791 fn set_or_clear_reg_bits_raw(&mut self, reg: u8, bits: u8, set: bool) -> Result<(), E> {
792 if set {
793 self.set_reg_bits_raw(reg, bits)
794 }
795 else {
796 self.clear_reg_bits_raw(reg, bits)
797 }
798 }
799
800
801 pub fn toggle_plain_clockout(&mut self, enable: bool) -> Result<(), E> {
803 self.select_mux_channel()?;
804 self.set_or_clear_reg_bits_raw(
806 EEPROM_MIRROR_ADDRESS, RegEepromMirrorBits::ClockoutOutputEnableBit as u8, enable)
807 }
808
809 pub fn toggle_int_clockout(&mut self, enable: bool) -> Result<(), E> {
811 self.select_mux_channel()?;
812 self.set_or_clear_reg_bits_raw(
813 REG_CONTROL2, RegControl2Bits::ClockoutIntEnableBit as u8, enable)
814 }
815
816 fn config_pct_raw(&mut self, value: u16, freq: TimerClockFreq, repeat: bool ) -> Result<(), E> {
818 let value_high: u8 = ((value >> 8) as u8) & 0x0F;
819 let value_low: u8 = (value & 0xFF) as u8;
820
821 self.clear_reg_bits_raw(REG_CONTROL1, RegControl1Bits::TimerEnableBit as u8)?;
823 self.set_or_clear_reg_bits_raw(REG_CONTROL1, RegControl1Bits::TimerRepeatBit as u8, repeat)?;
824
825 self.clear_reg_bits_raw(REG_CONTROL1, RegControl1Bits::TimerClockFreqBits as u8)?;
826 self.set_reg_bits_raw(REG_CONTROL1, freq as u8)?; let write_buf = [ REG_TIMER_VALUE0, value_low, value_high];
830 self.i2c.write(RV3028_ADDRESS, &write_buf)?;
831
832 self.clear_reg_bits_raw(REG_STATUS, RegStatusBits::PeriodicTimerFlag as u8)?;
833 Ok(())
834 }
835
836 const MAX_PCT_TICKS: u16 = 0x0FFF; const PCT_MILLIS_PERIOD:i64 = 15; const PCT_MICROS_PERIOD:i64 = 244; const MAX_PCT_COUNT:i64 = Self::MAX_PCT_TICKS as i64;
841 const MAX_PCT_MILLIS:i64 = Self::MAX_PCT_COUNT * Self::PCT_MILLIS_PERIOD;
842 const MAX_PCT_MICROS:i64 = Self::MAX_PCT_COUNT * Self::PCT_MICROS_PERIOD;
843 const PCT_MILLIS_SECOND_BARRIER: i64 = Self::PCT_MILLIS_PERIOD*(1000/Self::PCT_MILLIS_PERIOD);
844
845 fn pct_ticks_and_rate_for_duration(duration: &Duration) -> (u16, TimerClockFreq, Duration)
849 {
850 let whole_minutes = duration.num_minutes();
851 let whole_seconds = duration.num_seconds();
852 let whole_milliseconds = duration.num_milliseconds();
853 let frac_milliseconds = whole_milliseconds % 1_000;
854 let infrac_milliseconds = whole_milliseconds % Self::PCT_MILLIS_PERIOD;
855 let whole_microseconds = duration.num_microseconds().unwrap();
856
857 return if whole_minutes >= Self::MAX_PCT_COUNT {
858 (Self::MAX_PCT_TICKS, TimerClockFreq::HertzSixtieth, Duration::minutes(Self::MAX_PCT_COUNT))
859 } else if whole_seconds > Self::MAX_PCT_COUNT {
860 let ticks = whole_minutes;
862 (ticks as u16, TimerClockFreq::HertzSixtieth, Duration::minutes(ticks))
863 } else if (whole_milliseconds > Self::MAX_PCT_MILLIS) ||
864 ((0 == frac_milliseconds) && (whole_milliseconds > Self::PCT_MILLIS_SECOND_BARRIER)) {
865 let ticks = whole_seconds;
867 (ticks as u16, TimerClockFreq::Hertz1, Duration::seconds(ticks))
868 } else if (whole_microseconds > Self::MAX_PCT_MICROS) ||
869 ((0 == infrac_milliseconds) && (whole_milliseconds >= Self::PCT_MILLIS_PERIOD)) {
870 let ticks = whole_milliseconds / Self::PCT_MILLIS_PERIOD;
872 (ticks as u16, TimerClockFreq::Hertz64,
873 Duration::milliseconds(ticks * Self::PCT_MILLIS_PERIOD))
874 } else {
875 let ticks = whole_microseconds / Self::PCT_MICROS_PERIOD;
877 (ticks as u16, TimerClockFreq::Hertz4096,
878 Duration::microseconds(ticks * Self::PCT_MICROS_PERIOD))
879 }
880
881 }
882
883 pub fn config_countdown_timer(&mut self, duration: &Duration,
892 repeat: bool, start: bool
893 ) -> Result<Duration, E> {
894 let (ticks, freq, estimated) =
895 Self::pct_ticks_and_rate_for_duration(duration);
896
897 self.select_mux_channel()?;
898 self.config_pct_raw(ticks, freq, repeat)?;
899 if start {
900 self.set_reg_bits_raw(REG_CONTROL1, RegControl1Bits::TimerEnableBit as u8)?;
901 }
902
903 Ok(estimated)
904 }
905
906 pub fn toggle_countdown_timer(&mut self, enable: bool) -> Result<(), E> {
909 self.set_or_clear_reg_bits(
910 REG_CONTROL1, RegControl1Bits::TimerEnableBit as u8, enable)
911 }
912
913 pub fn check_and_clear_countdown(&mut self) -> Result<bool, E> {
915 let flag_set = 0 != self.check_and_clear_bits(
916 REG_STATUS, RegStatusBits::PeriodicTimerFlag as u8)?;
917 Ok(flag_set)
918 }
919
920 pub fn get_countdown_value(&mut self) -> Result<u16, E> {
924 let mut read_buf = [0u8;2];
925 self.read_multi_registers(REG_TIMER_STATUS0, &mut read_buf)?;
926 let value = ((read_buf[1] as u16) << 8) | (read_buf[0] as u16);
927 Ok(value)
928 }
929
930 fn check_and_clear_bits(&mut self, reg: u8, bits: u8) -> Result<u8, E> {
932 self.select_mux_channel()?;
933 let reg_val = self.read_register_raw(reg)?;
934 let bits_val = reg_val & bits;
935 if 0 != bits_val {
936 self.clear_reg_bits_raw(reg, bits)?;
937 }
938 Ok(bits_val)
939 }
940
941
942 pub fn config_ext_event_detection(
947 &mut self, rising: bool, int_enable: bool, filtering: u8, clockout_enable: bool) -> Result<(), E>
948 {
949 self.select_mux_channel()?;
950
951 self.clear_reg_bits_raw(REG_CONTROL2,
962 RegControl2Bits::EventIntEnableBit as u8)?;
963 self.clear_reg_bits_raw(
965 REG_STATUS, RegStatusBits::EventFlagBit as u8)?;
966
967 self.set_or_clear_reg_bits_raw(
970 REG_EVENT_CONTROL, RegEventControlBits::EventHighLowBit as u8, rising)?;
971
972 self.clear_reg_bits_raw(REG_EVENT_CONTROL,RegEventControlBits::EventFilteringTimeBits as u8)?;
974 if 0 != filtering {
975 self.set_reg_bits_raw(REG_EVENT_CONTROL, filtering << 4)?;
977 }
978
979 self.set_or_clear_reg_bits_raw(
982 REG_CLOCK_INTERRUPT_MASK, RegClockIntMaskBits::ClockoutOnExtEvtBit as u8, clockout_enable)?;
983
984 self.set_or_clear_reg_bits_raw(
986 REG_CONTROL2, RegControl2Bits::EventIntEnableBit as u8, int_enable)?;
987
988 Ok(())
989 }
990
991}
992
993
994pub trait EventTimeStampLogger {
995 type Error;
997
998 fn toggle_timestamp_logging(&mut self, enable: bool) -> Result<(), Self::Error>;
1001
1002 fn reset_timestamp_log(&mut self) -> Result<(), Self::Error>;
1004
1005 fn config_timestamp_logging(
1010 &mut self, evt_source: u8, overwrite: bool, start: bool)
1011 -> Result<(), Self::Error>;
1012
1013 fn get_event_count_and_datetime(&mut self) -> Result<(u32, Option<NaiveDateTime>), Self::Error>;
1016
1017 fn toggle_time_stamp_overwrite(&mut self, enable: bool) -> Result<(), Self::Error>;
1021
1022 fn set_event_timestamp_source(&mut self, source: u8) -> Result<(), Self::Error>;
1024}
1025
1026impl<I2C, E> DateTimeAccess for RV3028<I2C>
1027 where
1028 I2C: Write<Error = E> + Read<Error = E> + WriteRead<Error = E>,
1029{
1030 type Error = E;
1031
1032 fn datetime(&mut self) -> Result<NaiveDateTime, Self::Error> {
1037 let unix_timestamp = self.get_unix_time()?;
1038 Ok(NaiveDateTime::from_timestamp_opt(unix_timestamp.into(), 0).unwrap())
1039 }
1040
1041 fn set_datetime(&mut self, datetime: &NaiveDateTime) -> Result<(), Self::Error> {
1049 let unix_timestamp: u32 = datetime.timestamp().try_into().unwrap();
1050 self.select_mux_channel()?;
1051 self.set_unix_time_raw(unix_timestamp)?;
1055 self.set_date_raw(&datetime.date())?;
1056 self.set_time_raw(&datetime.time())?;
1059 Ok(())
1060 }
1061
1062}
1063impl<I2C, E> EventTimeStampLogger for RV3028<I2C>
1064 where
1065 I2C: Write<Error = E> + Read<Error = E> + WriteRead<Error = E>
1066{
1067 type Error = E;
1068
1069
1070 fn toggle_timestamp_logging(&mut self, enable: bool) -> Result<(), Self::Error> {
1071 self.select_mux_channel()?;
1072 self.set_or_clear_reg_bits_raw(REG_CONTROL2, RegControl2Bits::TimeStampEnableBit as u8, enable)
1073 }
1074
1075 fn reset_timestamp_log(&mut self) -> Result<(), Self::Error> {
1076 self.select_mux_channel()?;
1077 self.set_reg_bits_raw(
1078 REG_EVENT_CONTROL, RegEventControlBits::TimeStampResetBit as u8)
1079
1080 }
1081
1082 fn config_timestamp_logging(
1083 &mut self, evt_source: u8, overwrite: bool, start:bool) -> Result<(), E>
1084 {
1085 self.select_mux_channel()?;
1086
1087 self.clear_reg_bits_raw(REG_CONTROL2,
1090 RegControl2Bits::TimeStampEnableBit as u8)?;
1091
1092 self.clear_reg_bits_raw(
1094 REG_STATUS, RegStatusBits::EventFlagBit as u8 | RegStatusBits::BackupSwitchFlag as u8)?;
1095
1096 let enable_bsf = evt_source == TS_EVENT_SOURCE_BSF;
1101 self.set_or_clear_reg_bits_raw(
1102 REG_EVENT_CONTROL, RegEventControlBits::TimeStampSourceBit as u8, enable_bsf)?;
1103
1104 self.set_or_clear_reg_bits_raw(
1106 REG_EVENT_CONTROL, RegEventControlBits::TimeStampOverwriteBit as u8, overwrite)?;
1107
1108 self.set_reg_bits_raw(
1110 REG_EVENT_CONTROL, RegEventControlBits::TimeStampResetBit as u8)?;
1111
1112 self.set_or_clear_reg_bits_raw(
1115 REG_CONTROL2, RegControl2Bits::TimeStampEnableBit as u8, start)?;
1116
1117 Ok(())
1125 }
1126
1127 fn get_event_count_and_datetime(&mut self) -> Result<(u32, Option<NaiveDateTime>), Self::Error> {
1128 let mut read_buf:[u8;7] = [0u8;7];
1130 self.read_multi_registers(REG_COUNT_EVENTS_TS, &mut read_buf)?;
1131
1132 let count = read_buf[0]; let odt = {
1136 if count > 0 {
1137 let seconds = Self::bcd_to_bin(read_buf[1]);
1138 let minutes = Self::bcd_to_bin(read_buf[2]);
1139 let hours = Self::bcd_to_bin(read_buf[3]);
1140 let date = Self::bcd_to_bin(read_buf[4]);
1141 let month = Self::bcd_to_bin(read_buf[5]);
1142 let year:i32 = Self::bcd_to_bin(read_buf[6]) as i32 + 2000;
1143 Some(NaiveDate::from_ymd_opt(year as i32, month as u32, date as u32)
1144 .expect("YMD")
1145 .and_hms_opt(hours as u32, minutes as u32, seconds as u32)
1146 .expect("HMS"))
1147 }
1148 else {
1149 None
1150 }
1151 };
1152
1153 Ok((count as u32, odt))
1154 }
1155
1156 fn toggle_time_stamp_overwrite(&mut self, enable: bool) -> Result<(), Self::Error> {
1157 self.set_or_clear_reg_bits(
1158 REG_EVENT_CONTROL, RegEventControlBits::TimeStampOverwriteBit as u8, enable)
1159 }
1160
1161 fn set_event_timestamp_source(&mut self, source: u8) -> Result<(), Self::Error> {
1162 let enable = TS_EVENT_SOURCE_BSF == source;
1163 self.set_or_clear_reg_bits(
1164 REG_EVENT_CONTROL, RegEventControlBits::TimeStampSourceBit as u8, enable)
1165 }
1166
1167}
1168
1169#[cfg(test)]
1170mod tests {
1171 use super::*;
1172 use embedded_hal_mock::i2c::{Mock as I2cMock, Transaction as I2cTrans};
1173 use std::vec;
1174
1175
1176 type TestClass = RV3028<I2cMock>;
1177
1178
1179 #[test]
1180 fn test_set_unix_time() {
1181 let unix_time: u32 = 1_614_456_789; let bytes = unix_time.to_le_bytes(); let expectations = [
1184 I2cTrans::write(
1185 RV3028_ADDRESS,
1186 vec![
1187 REG_UNIX_TIME_0,
1188 bytes[0],
1189 bytes[1],
1190 bytes[2],
1191 bytes[3],
1192 ],
1193 ),
1194 ];
1195 let mock = I2cMock::new(&expectations);
1196 let mut rv3028 = RV3028::new(mock);
1197 rv3028.set_unix_time(unix_time).unwrap();
1198 }
1199
1200 #[test]
1201 fn test_get_unix_time() {
1202 let unix_time: u32 = 1_614_456_789; let bytes = unix_time.to_le_bytes(); let expectations = [
1205 I2cTrans::write_read(
1206 RV3028_ADDRESS,
1207 vec![REG_UNIX_TIME_0],
1208 bytes.to_vec(),
1209 ),
1210 I2cTrans::write_read(
1211 RV3028_ADDRESS,
1212 vec![REG_UNIX_TIME_0],
1213 bytes.to_vec(),
1214 ),
1215 ];
1216 let mock = I2cMock::new(&expectations);
1217 let mut rv3028 = RV3028::new(mock);
1218 assert_eq!(rv3028.get_unix_time().unwrap(), unix_time);
1219 }
1220
1221 fn verify_whole_time_estimate(duration: &Duration, known_freq: TimerClockFreq, known_ticks: u16) {
1224 let (ticks, freq, estimated) =
1225 TestClass::pct_ticks_and_rate_for_duration(&duration);
1226 assert_eq!(freq, known_freq);
1227 assert_eq!(ticks, known_ticks);
1228 assert_eq!(*duration, estimated);
1229 }
1230
1231 fn verify_ticks_and_freq(duration: &Duration, known_freq: TimerClockFreq, known_ticks: u16) {
1234 let (ticks, freq, _estimated) =
1235 TestClass::pct_ticks_and_rate_for_duration(&duration);
1236 assert_eq!(freq, known_freq);
1237 assert_eq!(ticks, known_ticks);
1238 }
1240
1241 #[test]
1242 fn test_countdown_timer_conversion_minutes() {
1243 let minutes_clock_freq = TimerClockFreq::HertzSixtieth;
1245
1246 verify_ticks_and_freq(
1248 &Duration::minutes(TestClass::MAX_PCT_COUNT + 32),
1249 minutes_clock_freq, TestClass::MAX_PCT_TICKS);
1250
1251 verify_whole_time_estimate(
1252 &Duration::minutes(TestClass::MAX_PCT_COUNT),
1253 minutes_clock_freq, TestClass::MAX_PCT_TICKS);
1254
1255 const MAX_SECONDS_IN_MINUTES: i64 = (TestClass::MAX_PCT_COUNT/ 60) + 1;
1257 verify_whole_time_estimate(
1258 &Duration::minutes(MAX_SECONDS_IN_MINUTES),
1259 minutes_clock_freq, MAX_SECONDS_IN_MINUTES as u16);
1260
1261 verify_whole_time_estimate(
1262 &Duration::minutes(2047),
1263 minutes_clock_freq, 2047);
1264
1265 }
1266
1267 #[test]
1268 fn test_countdown_timer_conversion_seconds() {
1269 let seconds_clock_freq = TimerClockFreq::Hertz1;
1271
1272 verify_whole_time_estimate(
1274 &Duration::seconds(TestClass::MAX_PCT_COUNT),
1275 seconds_clock_freq, TestClass::MAX_PCT_TICKS);
1276
1277 verify_whole_time_estimate(
1278 &Duration::seconds(2047),
1279 seconds_clock_freq, 2047);
1280
1281 verify_whole_time_estimate(
1282 &Duration::seconds(61),
1283 seconds_clock_freq, 61);
1284
1285 verify_whole_time_estimate(
1287 &Duration::seconds(60),
1288 seconds_clock_freq, 60);
1289
1290 verify_whole_time_estimate(
1291 &Duration::minutes(1),
1292 seconds_clock_freq, 60);
1293
1294 verify_whole_time_estimate(
1295 &Duration::minutes(45),
1296 seconds_clock_freq, 45*60);
1297
1298 verify_whole_time_estimate(
1300 &Duration::seconds(1),
1301 seconds_clock_freq, 1);
1302
1303 }
1304
1305 #[test]
1306 fn test_countdown_timer_conversion_micros() {
1307 let micros_clock_freq = TimerClockFreq::Hertz4096;
1309
1310 verify_whole_time_estimate(
1311 &Duration::microseconds(TestClass::MAX_PCT_MICROS),
1312 micros_clock_freq, TestClass::MAX_PCT_TICKS);
1313
1314 verify_ticks_and_freq(
1315 &Duration::microseconds(2048),
1316 micros_clock_freq, (2048 / TestClass::PCT_MICROS_PERIOD) as u16);
1317
1318 verify_ticks_and_freq(
1319 &Duration::microseconds(655),
1320 micros_clock_freq, (655 / TestClass::PCT_MICROS_PERIOD) as u16);
1321
1322 verify_ticks_and_freq(
1323 &Duration::microseconds(1024),
1324 micros_clock_freq, (1024 / TestClass::PCT_MICROS_PERIOD) as u16);
1325
1326 verify_whole_time_estimate(
1329 &Duration::microseconds(999*TestClass::PCT_MICROS_PERIOD),
1330 micros_clock_freq, 999);
1331
1332 verify_whole_time_estimate(
1333 &Duration::microseconds(100*TestClass::PCT_MICROS_PERIOD),
1334 micros_clock_freq, 100);
1335
1336 verify_whole_time_estimate(
1337 &Duration::microseconds(17*TestClass::PCT_MICROS_PERIOD),
1338 micros_clock_freq, 17);
1339
1340 verify_whole_time_estimate(
1342 &Duration::microseconds(TestClass::PCT_MICROS_PERIOD),
1343 micros_clock_freq, 1);
1344
1345 }
1346
1347 #[test]
1348 fn test_countdown_timer_conversion_millis() {
1349 let millis_clock_freq = TimerClockFreq::Hertz64;
1351
1352 verify_ticks_and_freq(
1354 &Duration::microseconds(TestClass::MAX_PCT_MICROS + 1),
1355 millis_clock_freq,
1356 ((TestClass::MAX_PCT_MICROS + 1) / (TestClass::PCT_MILLIS_PERIOD * 1_000)) as u16
1357 );
1358
1359 verify_whole_time_estimate(
1361 &Duration::milliseconds(TestClass::MAX_PCT_MILLIS),
1362 millis_clock_freq, TestClass::MAX_PCT_TICKS);
1363
1364 verify_ticks_and_freq(
1366 &Duration::milliseconds(2047),
1367 millis_clock_freq, (2047 / TestClass::PCT_MILLIS_PERIOD) as u16);
1368
1369 verify_whole_time_estimate(
1371 &Duration::milliseconds(1000*TestClass::PCT_MILLIS_PERIOD),
1372 TimerClockFreq::Hertz1, TestClass::PCT_MILLIS_PERIOD as u16 );
1373
1374 verify_whole_time_estimate(
1377 &Duration::milliseconds(999*TestClass::PCT_MILLIS_PERIOD),
1378 millis_clock_freq, 999);
1379
1380 verify_whole_time_estimate(
1381 &Duration::milliseconds(100*TestClass::PCT_MILLIS_PERIOD),
1382 millis_clock_freq, 100);
1383
1384 verify_whole_time_estimate(
1386 &Duration::milliseconds(TestClass::PCT_MILLIS_PERIOD),
1387 millis_clock_freq, 1);
1388
1389 }
1390
1391
1392
1393}
1394