1use core::ops::Deref;
4
5use crate::target::{rtc0, Interrupt, NVIC, RTC0, RTC1};
6
7#[cfg(not(feature = "52810"))]
8use crate::target::RTC2;
9
10pub struct Stopped;
14pub struct Started;
16
17pub struct Rtc<T, M> {
19 periph: T,
20 _mode: M,
21}
22
23pub trait RtcExt: Deref<Target = rtc0::RegisterBlock> + Sized {
25 const INTERRUPT: Interrupt;
27
28 fn constrain(self) -> Rtc<Self, Stopped>;
29}
30
31macro_rules! impl_rtc_ext {
32 ($($rtc:ident,)*) => {
33 $(
34 impl RtcExt for $rtc {
35 const INTERRUPT: Interrupt = Interrupt::$rtc;
36
37 fn constrain(self) -> Rtc<$rtc, Stopped> {
38 Rtc {
39 periph: self,
40 _mode: Stopped,
41 }
42 }
43 }
44 )+
45 }
46}
47
48impl_rtc_ext!(RTC0, RTC1,);
49
50#[cfg(not(feature = "52810"))]
51impl_rtc_ext!(RTC2,);
52
53pub enum RtcInterrupt {
55 Tick,
56 Overflow,
57 Compare0,
58 Compare1,
59 Compare2,
60 Compare3,
61}
62
63pub enum RtcCompareReg {
65 Compare0,
66 Compare1,
67 Compare2,
68 Compare3,
69}
70
71impl<T, M> Rtc<T, M>
72where
73 T: RtcExt,
74{
75 pub fn enable_counter(self) -> Rtc<T, Started> {
77 unsafe {
78 self.periph.tasks_start.write(|w| w.bits(1));
79 }
80 Rtc {
81 periph: self.periph,
82 _mode: Started,
83 }
84 }
85
86 pub fn disable_counter(self) -> Rtc<T, Stopped> {
88 unsafe {
89 self.periph.tasks_stop.write(|w| w.bits(1));
90 }
91 Rtc {
92 periph: self.periph,
93 _mode: Stopped,
94 }
95 }
96
97 pub fn enable_interrupt(&mut self, int: RtcInterrupt, nvic: &mut NVIC) {
99 match int {
100 RtcInterrupt::Tick => self.periph.intenset.write(|w| w.tick().set()),
101 RtcInterrupt::Overflow => self.periph.intenset.write(|w| w.ovrflw().set()),
102 RtcInterrupt::Compare0 => self.periph.intenset.write(|w| w.compare0().set()),
103 RtcInterrupt::Compare1 => self.periph.intenset.write(|w| w.compare1().set()),
104 RtcInterrupt::Compare2 => self.periph.intenset.write(|w| w.compare2().set()),
105 RtcInterrupt::Compare3 => self.periph.intenset.write(|w| w.compare3().set()),
106 }
107 nvic.enable(T::INTERRUPT);
108 }
109
110 pub fn disable_interrupt(&mut self, int: RtcInterrupt, nvic: &mut NVIC) {
112 match int {
113 RtcInterrupt::Tick => self.periph.intenclr.write(|w| w.tick().clear()),
114 RtcInterrupt::Overflow => self.periph.intenclr.write(|w| w.ovrflw().clear()),
115 RtcInterrupt::Compare0 => self.periph.intenclr.write(|w| w.compare0().clear()),
116 RtcInterrupt::Compare1 => self.periph.intenclr.write(|w| w.compare1().clear()),
117 RtcInterrupt::Compare2 => self.periph.intenclr.write(|w| w.compare2().clear()),
118 RtcInterrupt::Compare3 => self.periph.intenclr.write(|w| w.compare3().clear()),
119 }
120 nvic.disable(T::INTERRUPT);
121 }
122
123 pub fn enable_event(&mut self, evt: RtcInterrupt) {
125 match evt {
126 RtcInterrupt::Tick => self.periph.evtenset.write(|w| w.tick().set()),
127 RtcInterrupt::Overflow => self.periph.evtenset.write(|w| w.ovrflw().set()),
128 RtcInterrupt::Compare0 => self.periph.evtenset.write(|w| w.compare0().set()),
129 RtcInterrupt::Compare1 => self.periph.evtenset.write(|w| w.compare1().set()),
130 RtcInterrupt::Compare2 => self.periph.evtenset.write(|w| w.compare2().set()),
131 RtcInterrupt::Compare3 => self.periph.evtenset.write(|w| w.compare3().set()),
132 }
133 }
134
135 pub fn disable_event(&mut self, evt: RtcInterrupt) {
137 match evt {
138 RtcInterrupt::Tick => self.periph.evtenclr.write(|w| w.tick().clear()),
139 RtcInterrupt::Overflow => self.periph.evtenclr.write(|w| w.ovrflw().clear()),
140 RtcInterrupt::Compare0 => self.periph.evtenclr.write(|w| w.compare0().clear()),
141 RtcInterrupt::Compare1 => self.periph.evtenclr.write(|w| w.compare1().clear()),
142 RtcInterrupt::Compare2 => self.periph.evtenclr.write(|w| w.compare2().clear()),
143 RtcInterrupt::Compare3 => self.periph.evtenclr.write(|w| w.compare3().clear()),
144 }
145 }
146
147 pub fn get_event_triggered(&mut self, evt: RtcInterrupt, clear_on_read: bool) -> bool {
150 let mut orig = 0;
151 let set_val = if clear_on_read { 0 } else { 1 };
152 match evt {
153 RtcInterrupt::Tick => self.periph.events_tick.modify(|r, w| {
154 orig = r.bits();
155 unsafe { w.bits(set_val) }
156 }),
157 RtcInterrupt::Overflow => self.periph.events_ovrflw.modify(|r, w| {
158 orig = r.bits();
159 unsafe { w.bits(set_val) }
160 }),
161 RtcInterrupt::Compare0 => self.periph.events_compare[0].modify(|r, w| {
162 orig = r.bits();
163 unsafe { w.bits(set_val) }
164 }),
165 RtcInterrupt::Compare1 => self.periph.events_compare[1].modify(|r, w| {
166 orig = r.bits();
167 unsafe { w.bits(set_val) }
168 }),
169 RtcInterrupt::Compare2 => self.periph.events_compare[2].modify(|r, w| {
170 orig = r.bits();
171 unsafe { w.bits(set_val) }
172 }),
173 RtcInterrupt::Compare3 => self.periph.events_compare[3].modify(|r, w| {
174 orig = r.bits();
175 unsafe { w.bits(set_val) }
176 }),
177 };
178
179 orig == 1
180 }
181
182 pub fn set_compare(&mut self, reg: RtcCompareReg, val: u32) -> Result<(), Error> {
185 if val >= (1 << 24) {
186 return Err(Error::CompareOutOfRange);
187 }
188
189 let reg = match reg {
190 RtcCompareReg::Compare0 => 0,
191 RtcCompareReg::Compare1 => 1,
192 RtcCompareReg::Compare2 => 2,
193 RtcCompareReg::Compare3 => 3,
194 };
195
196 unsafe {
197 self.periph.cc[reg].write(|w| w.bits(val));
198 }
199
200 Ok(())
201 }
202
203 pub fn get_counter(&self) -> u32 {
205 self.periph.counter.read().bits()
206 }
207
208 pub fn release(self) -> T {
211 self.periph
212 }
213}
214
215#[derive(Debug, PartialEq, Eq)]
217pub enum Error {
218 PrescalerOutOfRange,
219 CompareOutOfRange,
220}
221
222impl<T> Rtc<T, Stopped>
223where
224 T: RtcExt,
225{
226 pub fn set_prescaler(&mut self, prescaler: u32) -> Result<(), Error> {
229 if prescaler >= (1 << 12) {
230 return Err(Error::PrescalerOutOfRange);
231 }
232
233 unsafe { self.periph.prescaler.write(|w| w.bits(prescaler)) };
234
235 Ok(())
236 }
237}