1Pulse Counter (PCNT)
2====================
3
4{IDF_TARGET_PCNT_UNIT_NUM:default="8", esp32s2="4"}
5{IDF_TARGET_PCNT_MAX_UNIT_NUM:default="7", esp32s2="3"}
6
7Introduction
8------------
9
10The PCNT (Pulse Counter) module is designed to count the number of rising and/or falling edges of an input signal. Each pulse counter unit has a 16-bit signed counter register and two channels that can be configured to either increment or decrement the counter. Each channel has a signal input that accepts signal edges to be detected, as well as a control input that can be used to enable or disable the signal input. The inputs have optional filters that can be used to discard unwanted glitches in the signal.
11
12
13Functionality Overview
14----------------------
15
16Description of functionality of this API has been broken down into four sections:
17
18* :ref:`pcnt-api-configuration` - describes counter's configuration parameters and how to setup the counter.
19* :ref:`pcnt-api-operating-the-counter` - provides information on control functions to pause, measure and clear the counter.
20* :ref:`pcnt-api-filtering-pulses` - describes options to filtering pulses and the counter control signals.
21* :ref:`pcnt-api-using-interrupts` - presents how to trigger interrupts on specific states of the counter.
22
23
24.. _pcnt-api-configuration:
25
26Configuration
27-------------
28
29The PCNT module has {IDF_TARGET_PCNT_UNIT_NUM} independent counting "units" numbered from 0 to {IDF_TARGET_PCNT_MAX_UNIT_NUM}. In the API they are referred to using :cpp:type:`pcnt_unit_t`. Each unit has two independent channels numbered as 0 and 1 and specified with :cpp:type:`pcnt_channel_t`.
30
31The configuration is provided separately per unit's channel using :cpp:type:`pcnt_config_t` and covers:
32
33    * The unit and the channel number this configuration refers to.
34    * GPIO numbers of the pulse input and the pulse gate input.
35    * Two pairs of parameters: :cpp:type:`pcnt_ctrl_mode_t` and :cpp:type:`pcnt_count_mode_t` to define how the counter reacts depending on the the status of control signal and how counting is done positive / negative edge of the pulses.
36    * Two limit values (minimum / maximum) that are used to establish watchpoints and trigger interrupts when the pulse count is meeting particular limit.
37
38Setting up of particular channel is then done by calling a function :cpp:func:`pcnt_unit_config` with above :cpp:type:`pcnt_config_t` as the input parameter.
39
40To disable the pulse or the control input pin in configuration, provide :cpp:type:`PCNT_PIN_NOT_USED` instead of the GPIO number.
41
42
43.. _pcnt-api-operating-the-counter:
44
45Operating the Counter
46---------------------
47
48After doing setup with :cpp:func:`pcnt_unit_config`, the counter immediately starts to operate. The accumulated pulse count can be checked by calling :cpp:func:`pcnt_get_counter_value`.
49
50There are couple of functions that allow to control the counter's operation: :cpp:func:`pcnt_counter_pause`,  :cpp:func:`pcnt_counter_resume` and :cpp:func:`pcnt_counter_clear`
51
52It is also possible to dynamically change the previously set up counter modes with :cpp:func:`pcnt_unit_config` by calling :cpp:func:`pcnt_set_mode`.
53
54If desired, the pulse input pin and the control input pin may be changed "on the fly" using :cpp:func:`pcnt_set_pin`. To disable particular input provide as a function parameter :cpp:type:`PCNT_PIN_NOT_USED` instead of the GPIO number.
55
56.. note::
57
58    For the counter not to miss any pulses, the pulse duration should be longer than one APB_CLK cycle (12.5 ns). The pulses are sampled on the edges of the APB_CLK clock and may be missed, if fall between the edges. This applies to counter operation with or without a :ref:`filer <pcnt-api-filtering-pulses>`.
59
60
61.. _pcnt-api-filtering-pulses:
62
63Filtering Pulses
64----------------
65
66The PCNT unit features filters on each of the pulse and control inputs, adding the option to ignore short glitches in the signals.
67
68The length of ignored pulses is provided in APB_CLK clock cycles by calling :cpp:func:`pcnt_set_filter_value`. The current filter setting may be checked with :cpp:func:`pcnt_get_filter_value`. The APB_CLK clock is running at 80 MHz.
69
70The filter is put into operation / suspended by calling :cpp:func:`pcnt_filter_enable` / :cpp:func:`pcnt_filter_disable`.
71
72
73.. _pcnt-api-using-interrupts:
74
75Using Interrupts
76----------------
77
78There are five counter state watch events, defined in :cpp:type:`pcnt_evt_type_t`, that are able to trigger an interrupt. The event happens on the pulse counter reaching specific values:
79
80    * Minimum or maximum count values: :cpp:member:`counter_l_lim` or :cpp:member:`counter_h_lim` provided in :cpp:type:`pcnt_config_t` as discussed in :ref:`pcnt-api-configuration`
81    * Threshold 0 or Threshold 1 values set using function :cpp:func:`pcnt_set_event_value`.
82    * Pulse count = 0
83
84To register, enable or disable an interrupt to service the above events, call :cpp:func:`pcnt_isr_register`, :cpp:func:`pcnt_intr_enable`. and :cpp:func:`pcnt_intr_disable`. To enable or disable events on reaching threshold values, you will also need to call functions :cpp:func:`pcnt_event_enable` and :cpp:func:`pcnt_event_disable`.
85
86In order to check what are the threshold values currently set, use function :cpp:func:`pcnt_get_event_value`.
87
88
89Application Example
90-------------------
91
92* Pulse counter with control signal and event interrupt example: :example:`peripherals/pcnt/pulse_count_event`.
93* Parse the signal generated from rotary encoder: :example:`peripherals/pcnt/rotary_encoder`.
94
95
96API Reference
97-------------
98
99.. include-build-file:: inc/pcnt.inc
100.. include-build-file:: inc/pcnt_types.inc
101
102