stm32_rust_template/bsp/
ds1307.rs1use crate::driver::i2c::{I2c, Result};
2
3const DS1307_I2C_ADDRESS: u32 = 0x68;
5
6const DS1307_ADDR_SEC: u8 = 0x00;
8const DS1307_ADDR_MIN: u8 = 0x01;
9const DS1307_ADDR_HRS: u8 = 0x02;
10const DS1307_ADDR_DAY: u8 = 0x03;
11const DS1307_ADDR_DATE: u8 = 0x04;
12const DS1307_ADDR_MONTH: u8 = 0x05;
13const DS1307_ADDR_YEAR: u8 = 0x06;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum TimeFormat {
18 TwelveHoursAM = 0,
20 TwelveHoursPM = 1,
22 TwentyFourHours = 2,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum DayOfWeek {
29 Sunday = 1,
30 Monday = 2,
31 Tuesday = 3,
32 Wednesday = 4,
33 Thursday = 5,
34 Friday = 6,
35 Saturday = 7,
36}
37
38#[derive(Debug, Clone, Copy)]
40pub struct RtcDate {
41 pub date: u8,
42 pub month: u8,
43 pub year: u8,
44 pub day: DayOfWeek,
45}
46
47#[derive(Debug, Clone, Copy)]
49pub struct RtcTime {
50 pub seconds: u8,
51 pub minutes: u8,
52 pub hours: u8,
53 pub time_format: TimeFormat,
54}
55
56pub struct DS1307<I2C> {
58 i2c: I2C,
59}
60
61impl<I2C> DS1307<I2C>
62where
63 I2C: I2c<'static>,
64{
65 pub fn new(i2c: I2C) -> Self {
67 Self { i2c }
68 }
69
70 pub fn init(&mut self) -> Result<()> {
73 self.write_register(DS1307_ADDR_SEC, 0x00)?;
75
76 let clock_state = self.read_register(DS1307_ADDR_SEC)?;
78
79 if (clock_state >> 7) & 0x1 != 0 {
81 return Err(-1); }
83
84 Ok(())
85 }
86
87 pub fn set_current_time(&mut self, rtc_time: &RtcTime) -> Result<()> {
89 let mut seconds = Self::binary_to_bcd(rtc_time.seconds);
91 seconds &= !(1 << 7); self.write_register(DS1307_ADDR_SEC, seconds)?;
93
94 let minutes = Self::binary_to_bcd(rtc_time.minutes);
96 self.write_register(DS1307_ADDR_MIN, minutes)?;
97
98 let mut hours = Self::binary_to_bcd(rtc_time.hours);
100 match rtc_time.time_format {
101 TimeFormat::TwentyFourHours => {
102 hours &= !(1 << 6); }
104 TimeFormat::TwelveHoursAM => {
105 hours |= 1 << 6; hours &= !(1 << 5); }
108 TimeFormat::TwelveHoursPM => {
109 hours |= 1 << 6; hours |= 1 << 5; }
112 }
113 self.write_register(DS1307_ADDR_HRS, hours)?;
114
115 Ok(())
116 }
117
118 pub fn set_current_date(&mut self, rtc_date: &RtcDate) -> Result<()> {
120 self.write_register(DS1307_ADDR_DATE, Self::binary_to_bcd(rtc_date.date))?;
121 self.write_register(DS1307_ADDR_MONTH, Self::binary_to_bcd(rtc_date.month))?;
122 self.write_register(DS1307_ADDR_YEAR, Self::binary_to_bcd(rtc_date.year))?;
123 self.write_register(DS1307_ADDR_DAY, Self::binary_to_bcd(rtc_date.day as u8))?;
124 Ok(())
125 }
126
127 pub fn get_current_time(&mut self) -> Result<RtcTime> {
129 let mut seconds = self.read_register(DS1307_ADDR_SEC)?;
131 seconds &= !(1 << 7); let minutes = self.read_register(DS1307_ADDR_MIN)?;
134 let mut hours = self.read_register(DS1307_ADDR_HRS)?;
135
136 let time_format = if (hours & (1 << 6)) != 0 {
138 let is_pm = (hours & (1 << 5)) != 0;
140 hours &= !(0x3 << 5); if is_pm {
142 TimeFormat::TwelveHoursPM
143 } else {
144 TimeFormat::TwelveHoursAM
145 }
146 } else {
147 TimeFormat::TwentyFourHours
149 };
150
151 Ok(RtcTime {
152 seconds: Self::bcd_to_binary(seconds),
153 minutes: Self::bcd_to_binary(minutes),
154 hours: Self::bcd_to_binary(hours),
155 time_format,
156 })
157 }
158
159 pub fn get_current_date(&mut self) -> Result<RtcDate> {
161 let day_raw = self.read_register(DS1307_ADDR_DAY)?;
162 let date = self.read_register(DS1307_ADDR_DATE)?;
163 let month = self.read_register(DS1307_ADDR_MONTH)?;
164 let year = self.read_register(DS1307_ADDR_YEAR)?;
165
166 let day = match Self::bcd_to_binary(day_raw) {
167 1 => DayOfWeek::Sunday,
168 2 => DayOfWeek::Monday,
169 3 => DayOfWeek::Tuesday,
170 4 => DayOfWeek::Wednesday,
171 5 => DayOfWeek::Thursday,
172 6 => DayOfWeek::Friday,
173 7 => DayOfWeek::Saturday,
174 _ => DayOfWeek::Sunday, };
176
177 Ok(RtcDate {
178 day,
179 date: Self::bcd_to_binary(date),
180 month: Self::bcd_to_binary(month),
181 year: Self::bcd_to_binary(year),
182 })
183 }
184
185 fn write_register(&mut self, reg_addr: u8, value: u8) -> Result<()> {
187 let tx_data = [reg_addr, value];
188 self.i2c
189 .master_transmit(DS1307_I2C_ADDRESS, &tx_data, false)
190 }
191
192 fn read_register(&mut self, reg_addr: u8) -> Result<u8> {
194 self.i2c
196 .master_transmit(DS1307_I2C_ADDRESS, &[reg_addr], true)?;
197
198 let mut data = [0u8; 1];
200 self.i2c
201 .master_receive(DS1307_I2C_ADDRESS, &mut data, false)?;
202
203 Ok(data[0])
204 }
205
206 fn binary_to_bcd(value: u8) -> u8 {
208 if value >= 10 {
209 let tens = value / 10;
210 let ones = value % 10;
211 (tens << 4) | ones
212 } else {
213 value
214 }
215 }
216
217 fn bcd_to_binary(value: u8) -> u8 {
219 let tens = (value >> 4) * 10;
220 let ones = value & 0x0F;
221 tens + ones
222 }
223}
224
225impl<I2C> DS1307<I2C> {
226 pub fn release(self) -> I2C {
228 self.i2c
229 }
230}
231
232impl RtcDate {
234 pub fn new(date: u8, month: u8, year: u8, day: DayOfWeek) -> Self {
236 Self {
237 date,
238 month,
239 year,
240 day,
241 }
242 }
243}
244
245impl RtcTime {
246 pub fn new(seconds: u8, minutes: u8, hours: u8, time_format: TimeFormat) -> Self {
248 Self {
249 seconds,
250 minutes,
251 hours,
252 time_format,
253 }
254 }
255}