1use crate::{
9 interrupt::{InterruptConfigurable, InterruptHandler},
10 pcnt::{AnyPcntUnit, Instance, channel::Channel},
11 system::PeripheralGuard,
12};
13
14#[derive(Debug, Clone, Copy, PartialEq)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub struct InvalidFilterThreshold;
18
19#[derive(Debug, Clone, Copy, PartialEq)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub struct InvalidLowLimit;
23
24#[derive(Debug, Clone, Copy, PartialEq)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27pub struct InvalidHighLimit;
28
29#[derive(Copy, Clone, Debug, Default, PartialEq)]
31#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32pub enum ZeroMode {
33 #[default]
35 PosZero = 0,
36 NegZero = 1,
38 Negative = 2,
40 Positive = 3,
42}
43
44impl From<u8> for ZeroMode {
45 fn from(value: u8) -> Self {
46 match value {
47 0 => Self::PosZero,
48 1 => Self::NegZero,
49 2 => Self::Negative,
50 3 => Self::Positive,
51 _ => unreachable!(),
52 }
53 }
54}
55
56#[derive(Copy, Clone, Debug, Default)]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59pub struct Events {
60 pub low_limit: bool,
62 pub high_limit: bool,
64 pub threshold0: bool,
66 pub threshold1: bool,
68 pub zero: bool,
70}
71
72#[non_exhaustive]
74pub struct Unit<'d> {
75 unit: AnyPcntUnit<'d>,
76 pub counter: Counter<'d>,
78 pub channel0: Channel<'d, 0>,
80 pub channel1: Channel<'d, 1>,
82 _guard: PeripheralGuard,
83}
84
85impl<'d> Unit<'d> {
86 pub fn new(unit: impl Instance + 'd) -> Self {
88 let (info, _) = unit.parts();
89 let guard = PeripheralGuard::new(info.peripheral);
90 let unit = unit.degrade();
91
92 let regs = info.regs();
93 regs.unit(info.unit).conf0().write(|w| unsafe { w.bits(0) });
94 info.lock(|| {
95 regs.ctrl()
97 .modify(|_, w| w.cnt_rst_u(info.unit as u8).set_bit());
98 let bits = regs.ctrl().read().bits();
99 regs.ctrl().write(|w| {
100 unsafe { w.bits(bits) };
101 w.cnt_rst_u(info.unit as u8).clear_bit();
102 w.cnt_pause_u(info.unit as u8).clear_bit();
104 w.clk_en().set_bit()
105 });
106 });
107
108 Self {
109 counter: Counter::new(unsafe { unit.clone_unchecked() }),
110 channel0: Channel::new(unsafe { unit.clone_unchecked() }),
111 channel1: Channel::new(unsafe { unit.clone_unchecked() }),
112 unit,
113 _guard: guard,
114 }
115 }
116
117 fn index(&self) -> u8 {
118 self.unit.info().unit as u8
119 }
120
121 pub fn set_low_limit(&self, value: Option<i16>) -> Result<(), InvalidLowLimit> {
132 let unit = self.unit.register_block().unit(self.unit.info().unit);
133
134 if let Some(value) = value {
135 if !value.is_negative() {
139 return Err(InvalidLowLimit);
140 } else {
141 unit.conf2()
142 .modify(|_, w| unsafe { w.cnt_l_lim().bits(value as u16) });
143 unit.conf0().modify(|_, w| w.thr_l_lim_en().set_bit());
144 }
145 } else {
146 unit.conf0().modify(|_, w| w.thr_l_lim_en().clear_bit());
147 }
148 Ok(())
149 }
150
151 pub fn set_high_limit(&self, value: Option<i16>) -> Result<(), InvalidHighLimit> {
162 let unit = self.unit.register_block().unit(self.unit.info().unit);
163
164 if let Some(value) = value {
165 if !value.is_positive() {
166 return Err(InvalidHighLimit);
167 } else {
168 unit.conf2()
169 .modify(|_, w| unsafe { w.cnt_h_lim().bits(value as u16) });
170 unit.conf0().modify(|_, w| w.thr_h_lim_en().set_bit());
171 }
172 } else {
173 unit.conf0().modify(|_, w| w.thr_h_lim_en().clear_bit());
174 }
175 Ok(())
176 }
177
178 pub fn set_threshold0(&self, value: Option<i16>) {
183 let unit = self.unit.register_block().unit(self.unit.info().unit);
184
185 if let Some(value) = value {
186 unit.conf1()
187 .modify(|_, w| unsafe { w.cnt_thres0().bits(value as u16) });
188 unit.conf0().modify(|_, w| w.thr_thres0_en().set_bit());
189 } else {
190 unit.conf0().modify(|_, w| w.thr_thres0_en().clear_bit());
191 }
192 }
193
194 pub fn set_threshold1(&self, value: Option<i16>) {
199 let unit = self.unit.register_block().unit(self.unit.info().unit);
200
201 if let Some(value) = value {
202 unit.conf1()
203 .modify(|_, w| unsafe { w.cnt_thres1().bits(value as u16) });
204 unit.conf0().modify(|_, w| w.thr_thres1_en().set_bit());
205 } else {
206 unit.conf0().modify(|_, w| w.thr_thres1_en().clear_bit());
207 }
208 }
209
210 pub fn set_filter(&self, threshold: Option<u16>) -> Result<(), InvalidFilterThreshold> {
217 let unit = self.unit.register_block().unit(self.unit.info().unit);
218
219 match threshold {
220 None => {
221 unit.conf0().modify(|_, w| w.filter_en().clear_bit());
222 }
223 Some(threshold) => {
224 if threshold > 1023 {
225 return Err(InvalidFilterThreshold);
226 }
227 unit.conf0().modify(|_, w| unsafe {
228 w.filter_thres().bits(threshold);
229 w.filter_en().set_bit()
230 });
231 }
232 }
233 Ok(())
234 }
235
236 pub fn clear(&self) {
238 let n = self.index();
239 self.unit.lock(|| {
240 let regs = self.unit.register_block();
241 let bits = regs.ctrl().read().bits();
242 regs.ctrl().write(|w| {
243 unsafe { w.bits(bits) };
244 w.cnt_rst_u(n).set_bit()
245 });
246 regs.ctrl().write(|w| {
247 unsafe { w.bits(bits) };
248 w.cnt_rst_u(n).clear_bit()
249 });
250 });
251 }
252
253 pub fn pause(&self) {
255 let n = self.index();
256 self.unit.lock(|| {
257 self.unit
258 .register_block()
259 .ctrl()
260 .modify(|_, w| w.cnt_pause_u(n).set_bit());
261 });
262 }
263
264 pub fn resume(&self) {
266 let n = self.index();
267 self.unit.lock(|| {
268 self.unit
269 .register_block()
270 .ctrl()
271 .modify(|_, w| w.cnt_pause_u(n).clear_bit());
272 });
273 }
274
275 pub fn events(&self) -> Events {
277 let status = self
278 .unit
279 .register_block()
280 .u_status(self.unit.info().unit)
281 .read();
282
283 Events {
284 low_limit: status.l_lim().bit(),
285 high_limit: status.h_lim().bit(),
286 threshold0: status.thres0().bit(),
287 threshold1: status.thres1().bit(),
288 zero: status.zero().bit(),
289 }
290 }
291
292 pub fn zero_mode(&self) -> ZeroMode {
294 self.unit
295 .register_block()
296 .u_status(self.unit.info().unit)
297 .read()
298 .zero_mode()
299 .bits()
300 .into()
301 }
302
303 pub fn listen(&self) {
305 let n = self.index();
306 self.unit.lock(|| {
307 self.unit
308 .register_block()
309 .int_ena()
310 .modify(|_, w| w.cnt_thr_event_u(n).set_bit());
311 });
312 }
313
314 pub fn unlisten(&self) {
316 let n = self.index();
317 self.unit.lock(|| {
318 self.unit
319 .register_block()
320 .int_ena()
321 .modify(|_, w| w.cnt_thr_event_u(n).clear_bit());
322 });
323 }
324
325 pub fn interrupt_is_set(&self) -> bool {
327 self.unit
328 .register_block()
329 .int_raw()
330 .read()
331 .cnt_thr_event_u(self.index())
332 .bit()
333 }
334
335 pub fn reset_interrupt(&self) {
337 self.unit
338 .register_block()
339 .int_clr()
340 .write(|w| w.cnt_thr_event_u(self.index()).set_bit());
341 }
342
343 pub fn value(&self) -> i16 {
345 self.counter.get()
346 }
347
348 #[instability::unstable]
357 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
358 let info = self.unit.info();
359 self.unit.state().store(handler.handler().callback());
360 crate::interrupt::bind_handler(info.interrupt, info.dispatcher);
361 }
362}
363
364impl crate::private::Sealed for Unit<'_> {}
365
366#[instability::unstable]
367impl InterruptConfigurable for Unit<'_> {
368 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
369 self.set_interrupt_handler(handler);
370 }
371}
372
373impl Drop for Unit<'_> {
374 fn drop(&mut self) {
375 self.unlisten();
376 self.pause();
377 let info = self.unit.info();
378 info.regs()
379 .unit(info.unit)
380 .conf0()
381 .write(|w| unsafe { w.bits(0) });
382 self.unit.state().clear();
383 }
384}
385
386unsafe impl Send for Unit<'_> {}
388
389pub struct Counter<'d> {
391 unit: AnyPcntUnit<'d>,
392 _guard: PeripheralGuard,
393}
394
395impl Clone for Counter<'_> {
396 fn clone(&self) -> Self {
397 Self {
398 unit: unsafe { self.unit.clone_unchecked() },
399 _guard: self._guard.clone(),
400 }
401 }
402}
403
404impl<'d> Counter<'d> {
405 fn new(unit: AnyPcntUnit<'d>) -> Self {
406 let guard = PeripheralGuard::new(unit.info().peripheral);
407
408 Self {
409 unit,
410 _guard: guard,
411 }
412 }
413
414 pub fn get(&self) -> i16 {
416 self.unit
417 .register_block()
418 .u_cnt(self.unit.info().unit)
419 .read()
420 .cnt()
421 .bits() as i16
422 }
423}