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 _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Pcnt as u8 }>,
87}
88
89impl<const NUM: usize> Unit<'_, NUM> {
90 pub(super) fn new() -> Self {
92 let guard = GenericPeripheralGuard::new();
93
94 Self {
95 counter: Counter::new(),
96 channel0: Channel::new(),
97 channel1: Channel::new(),
98 _guard: guard,
99 }
100 }
101
102 pub fn set_low_limit(&self, value: Option<i16>) -> Result<(), InvalidLowLimit> {
113 let pcnt = PCNT::regs();
114 let unit = pcnt.unit(NUM);
115
116 if let Some(value) = value {
117 if !value.is_negative() {
121 return Err(InvalidLowLimit);
122 } else {
123 unit.conf2()
124 .modify(|_, w| unsafe { w.cnt_l_lim().bits(value as u16) });
125 unit.conf0().modify(|_, w| w.thr_l_lim_en().set_bit());
126 }
127 } else {
128 unit.conf0().modify(|_, w| w.thr_l_lim_en().clear_bit());
129 }
130 Ok(())
131 }
132
133 pub fn set_high_limit(&self, value: Option<i16>) -> Result<(), InvalidHighLimit> {
144 let pcnt = PCNT::regs();
145 let unit = pcnt.unit(NUM);
146
147 if let Some(value) = value {
148 if !value.is_positive() {
149 return Err(InvalidHighLimit);
150 } else {
151 unit.conf2()
152 .modify(|_, w| unsafe { w.cnt_h_lim().bits(value as u16) });
153 unit.conf0().modify(|_, w| w.thr_h_lim_en().set_bit());
154 }
155 } else {
156 unit.conf0().modify(|_, w| w.thr_h_lim_en().clear_bit());
157 }
158 Ok(())
159 }
160
161 pub fn set_threshold0(&self, value: Option<i16>) {
166 let pcnt = PCNT::regs();
167 let unit = pcnt.unit(NUM);
168
169 if let Some(value) = value {
170 unit.conf1()
171 .modify(|_, w| unsafe { w.cnt_thres0().bits(value as u16) });
172 unit.conf0().modify(|_, w| w.thr_thres0_en().set_bit());
173 } else {
174 unit.conf0().modify(|_, w| w.thr_thres0_en().clear_bit());
175 }
176 }
177
178 pub fn set_threshold1(&self, value: Option<i16>) {
183 let pcnt = PCNT::regs();
184 let unit = pcnt.unit(NUM);
185
186 if let Some(value) = value {
187 unit.conf1()
188 .modify(|_, w| unsafe { w.cnt_thres1().bits(value as u16) });
189 unit.conf0().modify(|_, w| w.thr_thres1_en().set_bit());
190 } else {
191 unit.conf0().modify(|_, w| w.thr_thres1_en().clear_bit());
192 }
193 }
194
195 pub fn set_filter(&self, threshold: Option<u16>) -> Result<(), InvalidFilterThreshold> {
202 let pcnt = PCNT::regs();
203 let unit = pcnt.unit(NUM);
204
205 match threshold {
206 None => {
207 unit.conf0().modify(|_, w| w.filter_en().clear_bit());
208 }
209 Some(threshold) => {
210 if threshold > 1023 {
211 return Err(InvalidFilterThreshold);
212 }
213 unit.conf0().modify(|_, w| unsafe {
214 w.filter_thres().bits(threshold).filter_en().set_bit()
215 });
216 }
217 }
218 Ok(())
219 }
220
221 pub fn clear(&self) {
223 let pcnt = PCNT::regs();
224 critical_section::with(|_cs| {
225 pcnt.ctrl().modify(|_, w| w.cnt_rst_u(NUM as u8).set_bit());
226 pcnt.ctrl()
228 .modify(|_, w| w.cnt_rst_u(NUM as u8).clear_bit());
229 });
230 }
231
232 pub fn pause(&self) {
234 let pcnt = PCNT::regs();
235 critical_section::with(|_cs| {
236 pcnt.ctrl()
237 .modify(|_, w| w.cnt_pause_u(NUM as u8).set_bit());
238 });
239 }
240
241 pub fn resume(&self) {
243 let pcnt = PCNT::regs();
244 critical_section::with(|_cs| {
245 pcnt.ctrl()
246 .modify(|_, w| w.cnt_pause_u(NUM as u8).clear_bit());
247 });
248 }
249
250 pub fn events(&self) -> Events {
252 let pcnt = PCNT::regs();
253 let status = pcnt.u_status(NUM).read();
254
255 Events {
256 low_limit: status.l_lim().bit(),
257 high_limit: status.h_lim().bit(),
258 threshold0: status.thres0().bit(),
259 threshold1: status.thres1().bit(),
260 zero: status.zero().bit(),
261 }
262 }
263
264 pub fn zero_mode(&self) -> ZeroMode {
266 let pcnt = PCNT::regs();
267 pcnt.u_status(NUM).read().zero_mode().bits().into()
268 }
269
270 pub fn listen(&self) {
272 let pcnt = PCNT::regs();
273 critical_section::with(|_cs| {
274 pcnt.int_ena()
275 .modify(|_, w| w.cnt_thr_event_u(NUM as u8).set_bit());
276 });
277 }
278
279 pub fn unlisten(&self, _cs: CriticalSection<'_>) {
281 let pcnt = PCNT::regs();
282 critical_section::with(|_cs| {
283 pcnt.int_ena()
284 .modify(|_, w| w.cnt_thr_event_u(NUM as u8).clear_bit());
285 });
286 }
287
288 pub fn interrupt_is_set(&self) -> bool {
290 let pcnt = PCNT::regs();
291 pcnt.int_raw().read().cnt_thr_event_u(NUM as u8).bit()
292 }
293
294 pub fn reset_interrupt(&self) {
296 let pcnt = PCNT::regs();
297 critical_section::with(|_cs| {
298 pcnt.int_clr()
299 .write(|w| w.cnt_thr_event_u(NUM as u8).set_bit());
300 });
301 }
302
303 pub fn value(&self) -> i16 {
305 self.counter.get()
306 }
307}
308
309impl<const NUM: usize> Drop for Unit<'_, NUM> {
310 fn drop(&mut self) {
311 }
313}
314
315unsafe impl<const NUM: usize> Send for Unit<'_, NUM> {}
317
318#[derive(Clone)]
320pub struct Counter<'d, const NUM: usize> {
321 _phantom: PhantomData<&'d ()>,
322}
323
324impl<const NUM: usize> Counter<'_, NUM> {
325 fn new() -> Self {
326 Self {
327 _phantom: PhantomData,
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}