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}