1#![no_std]
4#![allow(non_snake_case)]
5
6extern crate embedded_hal as hal;
7use hal::blocking::spi;
8use hal::digital::v2::OutputPin;
9
10mod registers;
11pub mod datetime;
12
13pub use datetime::DateTime;
14
15extern crate bitfield;
17
18
19pub struct Mcp795xx<SPI, CS> {
21 spi: SPI,
22 cs: CS,
23}
24
25
26impl<SPI, CS, E1, E2> Mcp795xx<SPI, CS>
27 where SPI: spi::Transfer<u8, Error = E1> + spi::Write<u8, Error = E1>,
28 CS: OutputPin<Error = E2>,
29 E1: core::fmt::Debug,
30 E2: core::fmt::Debug
31{
32 pub fn new(spi: SPI, cs: CS) -> Self {
33 Self {
34 spi: spi,
35 cs: cs
36 }
37 }
38
39 pub fn enable_oscillator(&mut self) {
40 let mut buff = [0 as u8; 3];
41
42 buff[0] = Instructions::READ as u8;
43 buff[1] = Addresses::RTCSEC as u8;
44
45 self.cs.set_low().unwrap();
46 self.spi.transfer(&mut buff).unwrap();
47 self.cs.set_high().unwrap();
48
49 let osc_enabled = registers::RTCSEC(buff[2]).ST();
50
51 if !osc_enabled {
52 buff[0] = Instructions::WRITE as u8;
53 buff[1] = Addresses::RTCSEC as u8;
54 let mut seconds = registers::RTCSEC(0);
55 seconds.set_st(true);
56 buff[2] = seconds.0;
57 self.cs.set_low().unwrap();
58 self.spi.transfer(&mut buff).unwrap();
59 self.cs.set_high().unwrap();
60 }
61 }
62
63 pub fn enable_vbat(&mut self) {
64 let mut buff = [0 as u8; 3];
65
66 buff[0] = Instructions::READ as u8;
67 buff[1] = Addresses::RTCWKDAY as u8;
68
69 self.cs.set_low().unwrap();
70 self.spi.transfer(&mut buff).unwrap();
71 self.cs.set_high().unwrap();
72
73 let vbat_enabled = registers::RTCWKDAY(buff[2]).VBATEN();
74
75 if !vbat_enabled {
76 buff[0] = Instructions::WRITE as u8;
77 buff[1] = Addresses::RTCWKDAY as u8;
78 let mut reg = registers::RTCWKDAY(0);
79 reg.set_VBATEN(true);
80 buff[2] = reg.0;
81 self.cs.set_low().unwrap();
82 self.spi.transfer(&mut buff).unwrap();
83 self.cs.set_high().unwrap();
84 }
85 }
86 pub fn get_time(&mut self) -> DateTime {
87 let mut buff = [0 as u8; 10];
88
89 buff[0] = Instructions::READ as u8;
91
92 buff[1] = Addresses::RTCSEC as u8;
94
95 self.cs.set_low().unwrap();
96 self.spi.transfer(&mut buff).unwrap();
97 self.cs.set_high().unwrap();
98
99 DateTime {
100 seconds : registers::RTCSEC(buff[2]).seconds(),
101 minutes : registers::RTCMIN(buff[3]).minutes(),
102 hours : registers::RTCHOUR(buff[4]).hours(),
103 weekday : registers::RTCWKDAY(buff[5]).WKDAY(),
104 date : registers::RTCDATE(buff[6]).date(),
105 month : registers::RTCMTH(buff[7]).month(),
106 year : registers::RTCYEAR(buff[8]).year()
107 }
108 }
109
110 pub fn set_time(&mut self, datetime: DateTime) {
111
112 let mut seconds = registers::RTCSEC(0);
113 seconds.set_seconds(datetime.seconds);
114 seconds.set_st(true);
115
116 let mut minutes = registers::RTCMIN(0);
117 minutes.set_minutes(datetime.minutes);
118
119 let mut hours = registers::RTCHOUR(0);
120 hours.set_hours_military(datetime.hours);
121
122 let mut weekday = registers::RTCWKDAY(0);
123 weekday.set_PWRFAIL(false);
124 weekday.set_VBATEN(true);
125 weekday.set_WKDAY(datetime.weekday);
126
127 let mut date = registers::RTCDATE(0);
128 date.set_date(datetime.date);
129
130 let mut month = registers::RTCMTH(0);
131 month.set_month(datetime.month);
132
133 let mut year = registers::RTCYEAR(0);
134 year.set_year(datetime.year);
135
136 let buff = [
137 (Instructions::WRITE as u8),
139 Addresses::RTCHSEC as u8,
141 0, seconds.0,
143 minutes.0,
144 hours.0,
145 weekday.0,
146 date.0,
147 month.0,
148 year.0,
149 ];
150
151 self.cs.set_low().unwrap();
152 self.spi.write(&buff).unwrap();
153 self.cs.set_high().unwrap();
154 }
155}
156
157#[allow(unused)]
158enum Instructions {
159 EEREAD = 0b0000_0011,
161 EEWRITE = 0b0000_0010,
163 EEWRDI = 0b0000_0100,
165 EEWREN = 0b0000_0110,
167 SRREAD = 0b0000_0101,
169 SRWRITE = 0b0000_0001,
171 READ = 0b0001_0011,
173 WRITE = 0b0001_0010,
175 UNLOCK = 0b0001_0100,
177 IDWRITE = 0b0011_0010,
179 IDREAD = 0b0011_0011,
181 CLRRAM = 0b0101_0100,
183}
184
185#[allow(unused)]
186enum Addresses {
187 RTCHSEC = 0x00,
188 RTCSEC= 0x01,
189 RTCMIN = 0x02,
190 RTCHOUR= 0x03,
191 RTCWKDAY= 0x04,
192 RTCDATE= 0x05,
193 RTCMTH= 0x06,
194 RTCYEAR= 0x07,
195 CONTROL= 0x08,
196 ALM0SEC= 0x0C,
197 ALM0MIN= 0x0D,
198 ALM0HOUR= 0x0E,
199 ALM0WKDAY= 0x0F,
200 ALM0DATE= 0x10,
201 ALM0MTH= 0x11,
202 ALM1HSEC= 0x12,
203 ALM1SEC= 0x13,
204 ALM1MIN= 0x14,
205 ALM1HOUR= 0x15,
206 ALM1WKDAY= 0x16,
207 ALM1DATE= 0x17,
208 PWRDNMIN= 0x18,
209 PWRDNHOUR= 0x19,
210 PWRDNDATE= 0x1A,
211 PWRDNMTH= 0x1B,
212 PWRUPMIN= 0x1C,
213 PWRUPHOUR= 0x1D,
214 PWRUPDATE= 0x1E,
215 PWRUPMTH= 0x1F,
216}
217
218
219#[cfg(test)]
220#[macro_use]
221extern crate std;
222mod tests {
223 }