1use crate::gpio::*;
3use crate::rcc::{RTCSrc, Rcc};
4use crate::stm32::RTC;
5use crate::time::*;
6
7#[derive(Debug, PartialEq, Eq)]
8pub enum RtcHourFormat {
9 H24,
10 H12,
11}
12
13#[derive(Debug, PartialEq, Eq)]
14pub enum RtcCalibrationFrequency {
15 F1Hz,
16 F512Hz,
17}
18
19pub enum Event {
20 WakeupTimer,
21 AlarmA,
22 AlarmB,
23 Timestamp,
24}
25
26#[derive(Debug, Default, PartialEq, Eq)]
27pub struct Alarm {
28 day: Option<u32>,
29 hours: Option<u32>,
30 minutes: Option<u32>,
31 seconds: Option<u32>,
32 subseconds: u16,
33 subseconds_mask_bits: u8,
34 use_weekday: bool,
35}
36
37impl Alarm {
38 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn set_month_day(mut self, day: u32) -> Self {
43 self.use_weekday = false;
44 self.day = Some(day);
45 self
46 }
47
48 pub fn set_week_day(mut self, day: u32) -> Self {
49 self.use_weekday = true;
50 self.day = Some(day);
51 self
52 }
53
54 pub fn set_hours(mut self, val: u32) -> Self {
55 self.hours = Some(val);
56 self
57 }
58
59 pub fn set_minutes(mut self, val: u32) -> Self {
60 self.minutes = Some(val);
61 self
62 }
63
64 pub fn set_seconds(mut self, val: u32) -> Self {
65 self.seconds = Some(val);
66 self
67 }
68
69 pub fn set_subseconds(mut self, subseconds: u16, mask_bits: u8) -> Self {
70 self.subseconds_mask_bits = mask_bits;
71 self.subseconds = subseconds;
72 self
73 }
74
75 pub fn mask_day(mut self) -> Self {
76 self.day = None;
77 self
78 }
79
80 pub fn mask_hours(mut self) -> Self {
81 self.hours = None;
82 self
83 }
84
85 pub fn mask_minutes(mut self) -> Self {
86 self.minutes = None;
87 self
88 }
89
90 pub fn mask_seconds(mut self) -> Self {
91 self.seconds = None;
92 self
93 }
94}
95
96impl From<Time> for Alarm {
97 fn from(time: Time) -> Self {
98 Self::default()
99 .set_hours(time.hours)
100 .set_minutes(time.minutes)
101 .set_seconds(time.seconds)
102 }
103}
104
105pub struct Rtc {
106 rb: RTC,
107}
108
109impl Rtc {
110 pub fn new(rtc: RTC, src: RTCSrc, rcc: &mut Rcc) -> Self {
111 rcc.enable_rtc(src);
112 Rtc { rb: rtc }
113 }
114
115 pub fn set_hour_format(&mut self, fmt: RtcHourFormat) {
116 self.modify(|rb| {
117 rb.cr.modify(|_, w| w.fmt().bit(fmt == RtcHourFormat::H12));
118 });
119 }
120
121 pub fn set_date(&mut self, date: &Date) {
122 let (yt, yu) = bcd2_encode(date.year - 1970);
123 let (mt, mu) = bcd2_encode(date.month);
124 let (dt, du) = bcd2_encode(date.day);
125
126 self.modify(|rb| {
127 rb.dr.write(|w| unsafe {
128 w.dt()
129 .bits(dt)
130 .du()
131 .bits(du)
132 .mt()
133 .bit(mt > 0)
134 .mu()
135 .bits(mu)
136 .yt()
137 .bits(yt)
138 .yu()
139 .bits(yu)
140 .wdu()
141 .bits(date.day as u8)
142 });
143 });
144 }
145
146 pub fn set_time(&mut self, time: &Time) {
147 let (ht, hu) = bcd2_encode(time.hours);
148 let (mnt, mnu) = bcd2_encode(time.minutes);
149 let (st, su) = bcd2_encode(time.seconds);
150 self.modify(|rb| {
151 rb.tr.write(|w| unsafe {
152 w.ht()
153 .bits(ht)
154 .hu()
155 .bits(hu)
156 .mnt()
157 .bits(mnt)
158 .mnu()
159 .bits(mnu)
160 .st()
161 .bits(st)
162 .su()
163 .bits(su)
164 .pm()
165 .clear_bit()
166 });
167 rb.cr.modify(|_, w| w.fmt().bit(time.daylight_savings));
168 });
169 }
170
171 pub fn get_time(&self) -> Time {
172 let timer = self.rb.tr.read();
173 Time::new(
174 bcd2_decode(timer.ht().bits(), timer.hu().bits()).hours(),
175 bcd2_decode(timer.mnt().bits(), timer.mnu().bits()).minutes(),
176 bcd2_decode(timer.st().bits(), timer.su().bits()).secs(),
177 self.rb.cr.read().fmt().bit(),
178 )
179 }
180
181 pub fn get_date(&self) -> Date {
182 let date = self.rb.dr.read();
183 Date::new(
184 (bcd2_decode(date.yt().bits(), date.yu().bits()) + 1970).year(),
185 bcd2_decode(date.mt().bit() as u8, date.mu().bits()).month(),
186 bcd2_decode(date.dt().bits(), date.du().bits()).day(),
187 )
188 }
189
190 pub fn get_week_day(&self) -> u8 {
191 self.rb.dr.read().wdu().bits()
192 }
193
194 pub fn set_alarm_a(&mut self, alarm: impl Into<Alarm>) {
195 let alarm = alarm.into();
196 let (dt, du) = bcd2_encode(alarm.day.unwrap_or_default() as u32);
197 let (ht, hu) = bcd2_encode(alarm.hours.unwrap_or_default() as u32);
198 let (mt, mu) = bcd2_encode(alarm.minutes.unwrap_or_default() as u32);
199 let (st, su) = bcd2_encode(alarm.seconds.unwrap_or_default() as u32);
200
201 self.modify(|rb| {
202 rb.alrmassr.write(|w| unsafe {
203 w.maskss()
204 .bits(alarm.subseconds_mask_bits)
205 .ss()
206 .bits(alarm.subseconds)
207 });
208 rb.alrmar.write(|w| unsafe {
209 w.wdsel().bit(alarm.use_weekday);
210 w.msk1().bit(alarm.seconds.is_none());
211 w.msk2().bit(alarm.minutes.is_none());
212 w.msk3().bit(alarm.hours.is_none());
213 w.msk4().bit(alarm.day.is_none());
214 w.dt().bits(dt);
215 w.du().bits(du);
216 w.ht().bits(ht);
217 w.hu().bits(hu);
218 w.mnt().bits(mt);
219 w.mnu().bits(mu);
220 w.st().bits(st);
221 w.su().bits(su)
222 });
223
224 rb.cr.modify(|_, w| w.alrae().set_bit());
225 });
226 }
227
228 pub fn set_alarm_b(&mut self, alarm: Alarm) {
229 let (dt, du) = bcd2_encode(alarm.day.unwrap_or_default() as u32);
230 let (ht, hu) = bcd2_encode(alarm.hours.unwrap_or_default() as u32);
231 let (mt, mu) = bcd2_encode(alarm.minutes.unwrap_or_default() as u32);
232 let (st, su) = bcd2_encode(alarm.seconds.unwrap_or_default() as u32);
233
234 self.modify(|rb| {
235 rb.alrmbssr.write(|w| unsafe {
236 w.maskss()
237 .bits(alarm.subseconds_mask_bits)
238 .ss()
239 .bits(alarm.subseconds)
240 });
241 rb.alrmbr.write(|w| unsafe {
242 w.wdsel().bit(alarm.use_weekday);
243 w.msk1().bit(alarm.seconds.is_none());
244 w.msk2().bit(alarm.minutes.is_none());
245 w.msk3().bit(alarm.hours.is_none());
246 w.msk4().bit(alarm.day.is_none());
247 w.dt().bits(dt);
248 w.du().bits(du);
249 w.ht().bits(ht);
250 w.hu().bits(hu);
251 w.mnt().bits(mt);
252 w.mnu().bits(mu);
253 w.st().bits(st);
254 w.su().bits(su)
255 });
256
257 rb.cr.modify(|_, w| w.alrbe().set_bit());
258 });
259 }
260
261 pub fn listen(&mut self, ev: Event) {
262 self.modify(|rb| match ev {
263 Event::WakeupTimer => rb.cr.modify(|_, w| w.wutie().set_bit()),
264 Event::AlarmA => rb.cr.modify(|_, w| w.alraie().set_bit()),
265 Event::AlarmB => rb.cr.modify(|_, w| w.alrbie().set_bit()),
266 Event::Timestamp => rb.cr.modify(|_, w| w.tsie().set_bit()),
267 })
268 }
269
270 pub fn unlisten(&mut self, ev: Event) {
271 self.modify(|rb| match ev {
272 Event::WakeupTimer => rb.cr.modify(|_, w| w.wutie().clear_bit()),
273 Event::AlarmA => rb.cr.modify(|_, w| w.alraie().clear_bit()),
274 Event::AlarmB => rb.cr.modify(|_, w| w.alrbie().clear_bit()),
275 Event::Timestamp => rb.cr.modify(|_, w| w.tsie().clear_bit()),
276 })
277 }
278
279 pub fn is_pending(&self, ev: Event) -> bool {
280 match ev {
281 Event::WakeupTimer => self.rb.sr.read().wutf().bit_is_set(),
282 Event::AlarmA => self.rb.sr.read().alraf().bit_is_set(),
283 Event::AlarmB => self.rb.sr.read().alrbf().bit_is_set(),
284 Event::Timestamp => self.rb.sr.read().tsf().bit_is_set(),
285 }
286 }
287
288 pub fn unpend(&mut self, ev: Event) {
289 self.modify(|rb| match ev {
290 Event::WakeupTimer => rb.scr.modify(|_, w| w.cwutf().set_bit()),
291 Event::AlarmA => rb.scr.modify(|_, w| w.calraf().set_bit()),
292 Event::AlarmB => rb.scr.modify(|_, w| w.calrbf().set_bit()),
293 Event::Timestamp => rb.scr.modify(|_, w| w.ctsf().set_bit()),
294 });
295 }
296
297 pub fn enable_calibration_output<PIN: RtcOutputPin>(
298 &mut self,
299 pin: PIN,
300 freq: RtcCalibrationFrequency,
301 ) {
302 pin.setup();
303 self.modify(|rb| {
304 rb.cr.modify(|_, w| unsafe {
305 w.osel()
306 .bits(0b0)
307 .out2en()
308 .bit(pin.channel())
309 .cosel()
310 .bit(freq == RtcCalibrationFrequency::F1Hz)
311 .tampoe()
312 .clear_bit()
313 .coe()
314 .set_bit()
315 });
316 });
317 }
318
319 fn modify<F>(&mut self, mut closure: F)
320 where
321 F: FnMut(&mut RTC),
322 {
323 self.rb.wpr.write(|w| unsafe { w.bits(0xCA) });
325 self.rb.wpr.write(|w| unsafe { w.bits(0x53) });
326 let isr = self.rb.icsr.read();
328 if isr.initf().bit_is_clear() {
329 self.rb.icsr.write(|w| w.init().set_bit());
330 self.rb.icsr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
331 while self.rb.icsr.read().initf().bit_is_clear() {}
332 }
333 closure(&mut self.rb);
335 self.rb.icsr.write(|w| w.init().clear_bit());
337 self.rb.wpr.write(|w| unsafe { w.bits(0xFF) });
339 }
340}
341
342pub trait RtcExt {
343 fn constrain(self, rcc: &mut Rcc) -> Rtc;
344}
345
346impl RtcExt for RTC {
347 fn constrain(self, rcc: &mut Rcc) -> Rtc {
348 Rtc::new(self, RTCSrc::LSI, rcc)
349 }
350}
351
352pub trait RtcOutputPin {
353 fn setup(&self);
354 fn channel(&self) -> bool;
355 fn release(self) -> Self;
356}
357
358macro_rules! rtc_out_pins {
359 ($($pin:ty: ($af_mode:expr, $ch:expr),)+) => {
360 $(
361 impl RtcOutputPin for $pin {
362 fn setup(&self) {
363 self.set_alt_mode($af_mode);
364 }
365
366 fn channel(&self) -> bool {
367 $ch
368 }
369
370 fn release(self) -> Self {
371 self.into_analog()
372 }
373 }
374 )+
375 }
376}
377
378rtc_out_pins! {
379 PA4<DefaultMode>: (AltFunction::AF3, true),
380 PC13<DefaultMode>: (AltFunction::AF3, false),
381}
382
383fn bcd2_encode(word: u32) -> (u8, u8) {
384 let mut value = word as u8;
385 let mut bcd_high: u8 = 0;
386 while value >= 10 {
387 bcd_high += 1;
388 value -= 10;
389 }
390 let bcd_low = ((bcd_high << 4) | value) as u8;
391 (bcd_high, bcd_low)
392}
393
394fn bcd2_decode(fst: u8, snd: u8) -> u32 {
395 let value = snd | fst << 4;
396 let value = (value & 0x0F) + ((value & 0xF0) >> 4) * 10;
397 value as u32
398}