1use core::marker::PhantomData;
13
14use esp_sync::RawMutex;
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    mutex: RawMutex,
86}
87
88impl<const NUM: usize> Unit<'_, NUM> {
89    pub(super) fn new() -> Self {
91        Self {
92            counter: Counter::new(),
93            channel0: Channel::new(),
94            channel1: Channel::new(),
95            mutex: RawMutex::new(),
96        }
97    }
98
99    pub fn set_low_limit(&self, value: Option<i16>) -> Result<(), InvalidLowLimit> {
110        let pcnt = PCNT::regs();
111        let unit = pcnt.unit(NUM);
112
113        if let Some(value) = value {
114            if !value.is_negative() {
118                return Err(InvalidLowLimit);
119            } else {
120                unit.conf2()
121                    .modify(|_, w| unsafe { w.cnt_l_lim().bits(value as u16) });
122                unit.conf0().modify(|_, w| w.thr_l_lim_en().set_bit());
123            }
124        } else {
125            unit.conf0().modify(|_, w| w.thr_l_lim_en().clear_bit());
126        }
127        Ok(())
128    }
129
130    pub fn set_high_limit(&self, value: Option<i16>) -> Result<(), InvalidHighLimit> {
141        let pcnt = PCNT::regs();
142        let unit = pcnt.unit(NUM);
143
144        if let Some(value) = value {
145            if !value.is_positive() {
146                return Err(InvalidHighLimit);
147            } else {
148                unit.conf2()
149                    .modify(|_, w| unsafe { w.cnt_h_lim().bits(value as u16) });
150                unit.conf0().modify(|_, w| w.thr_h_lim_en().set_bit());
151            }
152        } else {
153            unit.conf0().modify(|_, w| w.thr_h_lim_en().clear_bit());
154        }
155        Ok(())
156    }
157
158    pub fn set_threshold0(&self, value: Option<i16>) {
163        let pcnt = PCNT::regs();
164        let unit = pcnt.unit(NUM);
165
166        if let Some(value) = value {
167            unit.conf1()
168                .modify(|_, w| unsafe { w.cnt_thres0().bits(value as u16) });
169            unit.conf0().modify(|_, w| w.thr_thres0_en().set_bit());
170        } else {
171            unit.conf0().modify(|_, w| w.thr_thres0_en().clear_bit());
172        }
173    }
174
175    pub fn set_threshold1(&self, value: Option<i16>) {
180        let pcnt = PCNT::regs();
181        let unit = pcnt.unit(NUM);
182
183        if let Some(value) = value {
184            unit.conf1()
185                .modify(|_, w| unsafe { w.cnt_thres1().bits(value as u16) });
186            unit.conf0().modify(|_, w| w.thr_thres1_en().set_bit());
187        } else {
188            unit.conf0().modify(|_, w| w.thr_thres1_en().clear_bit());
189        }
190    }
191
192    pub fn set_filter(&self, threshold: Option<u16>) -> Result<(), InvalidFilterThreshold> {
199        let pcnt = PCNT::regs();
200        let unit = pcnt.unit(NUM);
201
202        match threshold {
203            None => {
204                unit.conf0().modify(|_, w| w.filter_en().clear_bit());
205            }
206            Some(threshold) => {
207                if threshold > 1023 {
208                    return Err(InvalidFilterThreshold);
209                }
210                unit.conf0().modify(|_, w| unsafe {
211                    w.filter_thres().bits(threshold).filter_en().set_bit()
212                });
213            }
214        }
215        Ok(())
216    }
217
218    pub fn clear(&self) {
220        let pcnt = PCNT::regs();
221        self.mutex.lock(|| {
222            pcnt.ctrl().modify(|_, w| w.cnt_rst_u(NUM as u8).set_bit());
223            pcnt.ctrl()
225                .modify(|_, w| w.cnt_rst_u(NUM as u8).clear_bit());
226        });
227    }
228
229    pub fn pause(&self) {
231        let pcnt = PCNT::regs();
232        self.mutex.lock(|| {
233            pcnt.ctrl()
234                .modify(|_, w| w.cnt_pause_u(NUM as u8).set_bit());
235        });
236    }
237
238    pub fn resume(&self) {
240        let pcnt = PCNT::regs();
241        self.mutex.lock(|| {
242            pcnt.ctrl()
243                .modify(|_, w| w.cnt_pause_u(NUM as u8).clear_bit());
244        });
245    }
246
247    pub fn events(&self) -> Events {
249        let pcnt = PCNT::regs();
250        let status = pcnt.u_status(NUM).read();
251
252        Events {
253            low_limit: status.l_lim().bit(),
254            high_limit: status.h_lim().bit(),
255            threshold0: status.thres0().bit(),
256            threshold1: status.thres1().bit(),
257            zero: status.zero().bit(),
258        }
259    }
260
261    pub fn zero_mode(&self) -> ZeroMode {
263        let pcnt = PCNT::regs();
264        pcnt.u_status(NUM).read().zero_mode().bits().into()
265    }
266
267    pub fn listen(&self) {
269        let pcnt = PCNT::regs();
270        self.mutex.lock(|| {
271            pcnt.int_ena()
272                .modify(|_, w| w.cnt_thr_event_u(NUM as u8).set_bit());
273        });
274    }
275
276    pub fn unlisten(&self) {
278        let pcnt = PCNT::regs();
279        self.mutex.lock(|| {
280            pcnt.int_ena()
281                .modify(|_, w| w.cnt_thr_event_u(NUM as u8).clear_bit());
282        });
283    }
284
285    pub fn interrupt_is_set(&self) -> bool {
287        let pcnt = PCNT::regs();
288        pcnt.int_raw().read().cnt_thr_event_u(NUM as u8).bit()
289    }
290
291    pub fn reset_interrupt(&self) {
293        let pcnt = PCNT::regs();
294        self.mutex.lock(|| {
295            pcnt.int_clr()
296                .write(|w| w.cnt_thr_event_u(NUM as u8).set_bit());
297        });
298    }
299
300    pub fn value(&self) -> i16 {
302        self.counter.get()
303    }
304}
305
306impl<const NUM: usize> Drop for Unit<'_, NUM> {
307    fn drop(&mut self) {
308        }
310}
311
312unsafe impl<const NUM: usize> Send for Unit<'_, NUM> {}
314
315#[derive(Clone)]
317pub struct Counter<'d, const NUM: usize> {
318    _phantom: PhantomData<&'d ()>,
319
320    _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Pcnt as u8 }>,
321}
322
323impl<const NUM: usize> Counter<'_, NUM> {
324    fn new() -> Self {
325        let guard = GenericPeripheralGuard::new();
326
327        Self {
328            _phantom: PhantomData,
329            _guard: guard,
330        }
331    }
332
333    pub fn get(&self) -> i16 {
335        let pcnt = PCNT::regs();
336        pcnt.u_cnt(NUM).read().cnt().bits() as i16
337    }
338}