.. currentmodule:: machine
.. _machine.Counter:

class Counter -- pulse counter
==============================

Counter implements pulse counting by monitoring an input signal and counting
rising or falling edges.

Minimal ESP32 example usage::

    from machine import Pin, Counter

    counter = Counter(0, Pin(0, Pin.IN))  # create Counter for pin 0 and begin counting
    value = counter.value()               # retrieve current pulse count

Availability: **ESP32, MIMXRT**

Constructors
------------

.. class:: Counter(id, ...)

   Returns the singleton Counter object for the the given *id*. Values of *id*
   depend on a particular port and its hardware. Values 0, 1, etc. are commonly
   used to select hardware block #0, #1, etc.

   Additional arguments are passed to the :meth:`init` method described below,
   and will cause the Counter instance to be re-initialised and reset.

   On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`.

Methods
-------

.. method:: Counter.init(src, *, ...)

   Initialise and reset the Counter with the given parameters:

   - *src* specifies the input pin as a :ref:`machine.Pin <machine.Pin>` object.
     May be omitted on ports that have a predefined pin for a given hardware
     block.

   Additional keyword-only parameters that may be supported by a port are:

   - *edge* specifies the edge to count. Either ``Counter.RISING`` (the default)
     or ``Counter.FALLING``. *(Supported on ESP32)*

   - *direction* specifies the direction to count. Either ``Counter.UP`` (the
     default) or ``Counter.DOWN``. *(Supported on ESP32 and MIMXRT)*
     A :ref:`machine.Pin <machine.Pin>` object as parameter argument specifies a
     pin which controls the counting direction. Low: Count up, High: Count down.
     *(Supported on MIMXRT)*

   - *filter_ns* specifies a minimum period of time in nanoseconds that the
     source signal needs to be stable for a pulse to be counted. Implementations
     should use the longest filter supported by the hardware that is less than
     or equal to this value. The default is 0 (no filter). *(Supported on ESP32 and MIMXRT)*

   - *max* Specify the upper counting range. The position counter will count up
     from a *min* start value up to *max*, then roll over to the init value and
     increase the cycles counter by one. When counting down, the cycles counter
     decreases at the transition from *min* to *max*. The range is reset by defining
     both *max* and *min* to 0. The default value is the hardware's counter range.
     *(Supported by MIMXRT and the ESP32 PCNT module)*

   - *min* Specify the lower counting range. The default value is 0.
     *(Supported by MIMXRT and the ESP32 PCNT module)*

   - *index* A Pin specifier telling to which pin the index pulse is connected.
     At a rising slope of the index pulse the pulse counter is reset to the min value and
     the cycles counter is increased or decreased by one, depending on the counting direction.
     A *value* of *None* disables the index
     input. *(Supported on MIMXRT)*

   - *reset* A Pin specifier telling to which pin the reset pulse is connected.
     At a rising slope of the reset pulse the counter is set to the init
     value, but the cycles counter is not changed. A *value* of *None* disables the reset input.
     *(Supported on MIMXRT)*

   - *match* Set the counter value at which the interrupt IRQ_MATCH shall trigger.
     The value is not checked for being in the bounds of the counter range. This option
     if equivalent to the *threshold* options of the ESP32 PCNT module.
     A *value* of *None* resets the match value and disables the IRQ_MATCH interrupt.
     *(Supported on MIMXRT)*

   - *match_pin* A Pin specifier telling to which pin the match output is connected.
     This output will have a high level as long as the counter matches the
     match value. The signal is generated by the encoder logic and requires no
     further software support. The pulse width is defined by the input signal frequency
     and can be very short, like 20ns, or stay, if the counter stops at the match value.
     A *value* of *None* disables the match output. *(Supported on MIMXRT)*

.. method:: Counter.deinit()

   Stops the Counter, disabling any interrupts and releasing hardware resources.
   A Soft Reset should deinitialize all Counter objects.

.. method:: Counter.value([value])

   Get, and optionally set, the counter value as a signed integer.
   Implementations must aim to do the get and set atomically (i.e. without
   leading to skipped counts).

   This counter value could exceed the range of a :term:`small integer`, which
   means that calling :meth:`Counter.value` could cause a heap allocation, but
   implementations should aim to ensure that internal state only uses small
   integers and therefore will not allocate until the user calls
   :meth:`Counter.value`.

   For example, on ESP32, the internal state counts overflows of the hardware
   counter (every 32000 counts), which means that it will not exceed the small
   integer range until ``2**30 * 32000`` counts (slightly over 1 year at 1MHz).

   In general, it is recommended that you should use ``Counter.value(0)`` to reset
   the counter (i.e. to measure the counts since the last call), and this will
   avoid this problem.

.. method:: Counter.cycles([value])

   Get or set the current cycles counter of the counter as signed 16 bit integer.
   The value represents the overflow or underflow events of the count range.
   With no arguments the actual cycles counter value is returned.
   With a single *value* argument the cycles counter is set to that value. The
   base counter is not changed. The method returns the previous value.
   *(Supported on MIMXRT)*

.. method:: Counter.irq(handler=None, trigger=0, hard=False)

   Specifies, that the *handler* is called when the respective *event* happens.

   *event* may be:
    - Counter.IRQ_RESET Triggered with a transition at the *reset* input.
    - Counter.IRQ_INDEX Triggered with a transition at the *index* input.
    - Counter.IRQ_MATCH Triggered when the positions counter matches the match value. For fast signals,
      the actual position counter value when retrieved in the callback may be different from the trigger value.
    - Counter.IRQ_ROLL_OVER Triggered when the position counter rolls over from the highest
      to the lowest value.
    - Counter.IRQ_ROLL_UNDER Triggered when the position counter rolls under from the lowest
      to the highest value.

   The callback function *handler* receives a single argument, which is the Counter object. All
   events share the same callback. The event which triggers the callback can be identified
   with the irq.flags() method. The argument *hard* specifies, whether the callback is called
   as a hard interrupt or as regular scheduled function. Hard interrupts have always a short latency,
   but are limited in that they must not allocate memory. Regular scheduled functions are not limited
   in what can be used, but depending on the load of the device execution may be delayed.
   Under low load, the difference in latency is minor.

   The default arguments values are handler=None, trigger=0, hard=False. The callback will be
   disabled, when called with handler=None.

   The position match event is triggered as long as the position and match value are identical.
   Therefore the position match callback is run in a one-shot fashion, and has to be enabled
   again when the position has changed. It will be enabled by re-defining the trigger with either
   :meth:`Counter.irq()` or :meth:`irq().trigger()`. For ESP32, Counter interrupts are handled
   by the :ref:`PCNT<esp32.PCNT>`. *(Supported on MIMXRT)*

Constants
---------

.. data:: Counter.RISING
          Counter.FALLING

   Select the pulse edge. *(Supported on ESP32)*

.. data:: Counter.UP
          Counter.DOWN

   Select the counting direction.

.. data:: Counter.IRQ_RESET
          Counter.IRQ_INDEX
          Counter.IRQ_MATCH
          Counter.IRQ_ROLL_OVER
          Counter.IRQ_ROLL_UNDER

   Select the IRQ trigger event.  *(Supported on MIMXRT)*
