1use core::marker::PhantomData;
13
14use critical_section::CriticalSection;
15
16use crate::{pcnt::channel::Channel, peripherals::PCNT, system::GenericPeripheralGuard};
17
18#[derive(Debug, Clone, Copy, PartialEq)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub struct InvalidFilterThreshold;
22
23#[derive(Debug, Clone, Copy, PartialEq)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub struct InvalidLowLimit;
27
28#[derive(Debug, Clone, Copy, PartialEq)]
30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31pub struct InvalidHighLimit;
32
33#[derive(Copy, Clone, Debug, Default, PartialEq)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36pub enum ZeroMode {
37 #[default]
39 PosZero = 0,
40 NegZero = 1,
42 Negative = 2,
44 Positive = 3,
46}
47
48impl From<u8> for ZeroMode {
49 fn from(value: u8) -> Self {
50 match value {
51 0 => Self::PosZero,
52 1 => Self::NegZero,
53 2 => Self::Negative,
54 3 => Self::Positive,
55 _ => unreachable!(), }
57 }
58}
59
60#[derive(Copy, Clone, Debug, Default)]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63pub struct Events {
64 pub low_limit: bool,
66 pub high_limit: bool,
68 pub threshold0: bool,
70 pub threshold1: bool,
72 pub zero: bool,
74}
75
76#[non_exhaustive]
78pub struct Unit<'d, const NUM: usize> {
79 pub counter: Counter<'d, NUM>,
81 pub channel0: Channel<'d, NUM, 0>,
83 pub channel1: Channel<'d, NUM, 1>,
85}
86
87impl<const NUM: usize> Unit<'_, NUM> {
88 pub(super) fn new() -> Self {
90 Self {
91 counter: Counter::new(),
92 channel0: Channel::new(),
93 channel1: Channel::new(),
94 }
95 }
96
97 pub fn set_low_limit(&self, value: Option<i16>) -> Result<(), InvalidLowLimit> {
108 let pcnt = PCNT::regs();
109 let unit = pcnt.unit(NUM);
110
111 if let Some(value) = value {
112 if !value.is_negative() {
116 return Err(InvalidLowLimit);
117 } else {
118 unit.conf2()
119 .modify(|_, w| unsafe { w.cnt_l_lim().bits(value as u16) });
120 unit.conf0().modify(|_, w| w.thr_l_lim_en().set_bit());
121 }
122 } else {
123 unit.conf0().modify(|_, w| w.thr_l_lim_en().clear_bit());
124 }
125 Ok(())
126 }
127
128 pub fn set_high_limit(&self, value: Option<i16>) -> Result<(), InvalidHighLimit> {
139 let pcnt = PCNT::regs();
140 let unit = pcnt.unit(NUM);
141
142 if let Some(value) = value {
143 if !value.is_positive() {
144 return Err(InvalidHighLimit);
145 } else {
146 unit.conf2()
147 .modify(|_, w| unsafe { w.cnt_h_lim().bits(value as u16) });
148 unit.conf0().modify(|_, w| w.thr_h_lim_en().set_bit());
149 }
150 } else {
151 unit.conf0().modify(|_, w| w.thr_h_lim_en().clear_bit());
152 }
153 Ok(())
154 }
155
156 pub fn set_threshold0(&self, value: Option<i16>) {
161 let pcnt = PCNT::regs();
162 let unit = pcnt.unit(NUM);
163
164 if let Some(value) = value {
165 unit.conf1()
166 .modify(|_, w| unsafe { w.cnt_thres0().bits(value as u16) });
167 unit.conf0().modify(|_, w| w.thr_thres0_en().set_bit());
168 } else {
169 unit.conf0().modify(|_, w| w.thr_thres0_en().clear_bit());
170 }
171 }
172
173 pub fn set_threshold1(&self, value: Option<i16>) {
178 let pcnt = PCNT::regs();
179 let unit = pcnt.unit(NUM);
180
181 if let Some(value) = value {
182 unit.conf1()
183 .modify(|_, w| unsafe { w.cnt_thres1().bits(value as u16) });
184 unit.conf0().modify(|_, w| w.thr_thres1_en().set_bit());
185 } else {
186 unit.conf0().modify(|_, w| w.thr_thres1_en().clear_bit());
187 }
188 }
189
190 pub fn set_filter(&self, threshold: Option<u16>) -> Result<(), InvalidFilterThreshold> {
197 let pcnt = PCNT::regs();
198 let unit = pcnt.unit(NUM);
199
200 match threshold {
201 None => {
202 unit.conf0().modify(|_, w| w.filter_en().clear_bit());
203 }
204 Some(threshold) => {
205 if threshold > 1023 {
206 return Err(InvalidFilterThreshold);
207 }
208 unit.conf0().modify(|_, w| unsafe {
209 w.filter_thres().bits(threshold).filter_en().set_bit()
210 });
211 }
212 }
213 Ok(())
214 }
215
216 pub fn clear(&self) {
218 let pcnt = PCNT::regs();
219 critical_section::with(|_cs| {
220 pcnt.ctrl().modify(|_, w| w.cnt_rst_u(NUM as u8).set_bit());
221 pcnt.ctrl()
223 .modify(|_, w| w.cnt_rst_u(NUM as u8).clear_bit());
224 });
225 }
226
227 pub fn pause(&self) {
229 let pcnt = PCNT::regs();
230 critical_section::with(|_cs| {
231 pcnt.ctrl()
232 .modify(|_, w| w.cnt_pause_u(NUM as u8).set_bit());
233 });
234 }
235
236 pub fn resume(&self) {
238 let pcnt = PCNT::regs();
239 critical_section::with(|_cs| {
240 pcnt.ctrl()
241 .modify(|_, w| w.cnt_pause_u(NUM as u8).clear_bit());
242 });
243 }
244
245 pub fn events(&self) -> Events {
247 let pcnt = PCNT::regs();
248 let status = pcnt.u_status(NUM).read();
249
250 Events {
251 low_limit: status.l_lim().bit(),
252 high_limit: status.h_lim().bit(),
253 threshold0: status.thres0().bit(),
254 threshold1: status.thres1().bit(),
255 zero: status.zero().bit(),
256 }
257 }
258
259 pub fn zero_mode(&self) -> ZeroMode {
261 let pcnt = PCNT::regs();
262 pcnt.u_status(NUM).read().zero_mode().bits().into()
263 }
264
265 pub fn listen(&self) {
267 let pcnt = PCNT::regs();
268 critical_section::with(|_cs| {
269 pcnt.int_ena()
270 .modify(|_, w| w.cnt_thr_event_u(NUM as u8).set_bit());
271 });
272 }
273
274 pub fn unlisten(&self, _cs: CriticalSection<'_>) {
276 let pcnt = PCNT::regs();
277 critical_section::with(|_cs| {
278 pcnt.int_ena()
279 .modify(|_, w| w.cnt_thr_event_u(NUM as u8).clear_bit());
280 });
281 }
282
283 pub fn interrupt_is_set(&self) -> bool {
285 let pcnt = PCNT::regs();
286 pcnt.int_raw().read().cnt_thr_event_u(NUM as u8).bit()
287 }
288
289 pub fn reset_interrupt(&self) {
291 let pcnt = PCNT::regs();
292 critical_section::with(|_cs| {
293 pcnt.int_clr()
294 .write(|w| w.cnt_thr_event_u(NUM as u8).set_bit());
295 });
296 }
297
298 pub fn value(&self) -> i16 {
300 self.counter.get()
301 }
302}
303
304impl<const NUM: usize> Drop for Unit<'_, NUM> {
305 fn drop(&mut self) {
306 }
308}
309
310unsafe impl<const NUM: usize> Send for Unit<'_, NUM> {}
312
313#[derive(Clone)]
315pub struct Counter<'d, const NUM: usize> {
316 _phantom: PhantomData<&'d ()>,
317
318 _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Pcnt as u8 }>,
319}
320
321impl<const NUM: usize> Counter<'_, NUM> {
322 fn new() -> Self {
323 let guard = GenericPeripheralGuard::new();
324
325 Self {
326 _phantom: PhantomData,
327 _guard: guard,
328 }
329 }
330
331 pub fn get(&self) -> i16 {
333 let pcnt = PCNT::regs();
334 pcnt.u_cnt(NUM).read().cnt().bits() as i16
335 }
336}