1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use chrono::prelude::*;
use i2cdev::core::*;
use i2cdev::linux::LinuxI2CDevice;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
fn bcd_decode(x: u8) -> u32 {
((((x & 0xF0) >> 4) * 10) + (x & 0x0F)) as u32
}
fn bcd_encode(x: u32) -> u8 {
if x >= 100 {
panic!("Tried to BCD encode value {} >= 100", x);
}
let lower = x % 10;
let upper = x / 10;
(lower | (upper << 4)) as u8
}
pub struct Pcf8523 {
dev: LinuxI2CDevice,
}
impl Pcf8523 {
pub fn new(i2cpath: &str) -> Pcf8523 {
let i2caddr = 0x68;
let mut dev = LinuxI2CDevice::new(i2cpath, i2caddr).unwrap();
println!("{}", dev.smbus_read_byte_data(0x04).unwrap());
Pcf8523{
dev: dev,
}
}
pub fn get_time(&mut self) -> chrono::DateTime<Utc> {
let fields = self.dev.smbus_read_i2c_block_data(0x03, 7).unwrap();
let sec = bcd_decode(fields[0]);
let min = bcd_decode(fields[1]);
let hour = bcd_decode(fields[2]);
let day = bcd_decode(fields[3]);
let mon = bcd_decode(fields[5]);
let yr = bcd_decode(fields[6]);
Utc.ymd(2000 + yr as i32, mon, day).and_hms(hour, min, sec)
}
pub fn set_time(&mut self, time: chrono::DateTime<Utc>) {
let sec = bcd_encode(time.second());
let min = bcd_encode(time.minute());
let hour = bcd_encode(time.hour());
let day = bcd_encode(time.day());
let days_since_monday = time.weekday().number_from_monday();
let dow = bcd_encode(if days_since_monday == 7 { 0 } else { days_since_monday });
let mon = bcd_encode(time.month());
let yr = bcd_encode(time.year() as u32 - 2000);
let data = [sec, min, hour, day, dow, mon, yr];
self.dev.smbus_write_i2c_block_data(0x03, &data).unwrap();
}
}