Timers
******

This section is aimed to provide users an overview on available timers, timer usage,
and availability across various power states.

.. _timer-overview:
.. table:: Timer Overview

    +-----------------------+--------------------------------------------------------+-------------------+
    | **Timer**             | **Availability in Power Mode**                         | **Resolution**    |
    +=======================+========================================================+===================+
    | General Purpose Timer | Available in Active mode and Idle mode.                | (1/48)us          |
    +-----------------------+--------------------------------------------------------+-------------------+
    | Watchdog Timer        | Available in Active mode, Idle mode, and Standby mode. | (1/32)us          |
    +-----------------------+--------------------------------------------------------+-------------------+
    | System Timer          | Available in Active mode and Idle mode.                | 1us or 250ns      |
    +-----------------------+--------------------------------------------------------+-------------------+
    | Real-Time Clock       | Available in Active mode, Idle mode, and Standby mode. | 8us or 524ms      |
    +-----------------------+--------------------------------------------------------+-------------------+
    | Clock DPL             | Available in Active mode, Idle mode, and Standby mode. | 1us               |
    +-----------------------+--------------------------------------------------------+-------------------+
    | FreeRTOS Timer        | Available in Active mode and Idle mode.                | 10ms              |
    +-----------------------+--------------------------------------------------------+-------------------+

Hardware Timers
===============
There are 4 types of HW timer available for the application to use.

General Purpose Timer (LGPT)
----------------------------
The General Purpose Timer (LGPT) runs off of the High Frequency Clock, which is only available in
Active or Idle mode. LGPT is often used for high accuracy measurement, timer comparison,
DMA triggering, PWM, etc. For more information, please refer to the |DEVICE| datasheet.

Watchdog Timer
--------------
The Watchdog Timer is used as a recovery mechanism to regain control.
Upon timer expiration, the |DEVICE| will be reset. Because the |DEVICE| behaves
differently than previous generations, a workaround is needed to reduce the
power consumption of the Watchdog Timer. The :ref:`watchdog-example-code`
explains this workaround.

Real-Time Clock (RTC)
---------------------
The RTC is a 2-channel timer (compare channel and capture channel) and runs on
the Low Frequency Clock. The compare channel is used by system software to program
the |DEVICE|'s future wake up time before going into Standby mode.

System Timer (SYSTIM)
---------------------
SYSTIM has 5 channels; 4 channels are reserved by system software and radio
operation. There is only one available for the user. SYSTIM is synchronized to RTC
in hardware.

To get current device timestamp, users should use
ClockP_getSystemTicks() from :ref:`timer-clockp`.

.. attention::
   For more Hardware Timer information, please refer to the |DEVICE| datasheet.
   In general, it is recommended to use :ref:`timer-clockp` if users want to
   realize the functionality provided by SYSTIM.

Software Timers
===============

.. _timer-clockp:

ClockP Module
-------------
The ClockP module is developed by Texas Instruments and uses one SYSTIM channel
with 1 us resolution and is synchronized with the RTC.

ClockP can be used to do the following:

#. Get current timestamp
#. Get CPU clock frequency
#. Periodic timer to trigger periodic task
#. One shot timer to trigger task
#. Refresh the watchdog when standby is enabled.

.. note::
   To see the available APIs, please navigate to |TI_DRIVERS_API|

Using the ClockP module, a user can make multiple instances of "clocks" in their
application, where a "clock" refers to a distinct instance of ClockP. The "clocks"
constructed can either be one-shot or periodic, and can each have different
timeouts (and periods, for the periodic clocks.) Given that the ClockP module allows
for creation of clocks that can run in standby, it is also possible to create a
clock instances that can help achieve a variety of objectives which involve waking
the device up from standby to do something.

Examples of applications where a ClockP based clock can be used:

#. Non-blocking way of scheduling a function call for a given delta of time in the future (A one-shot ClockP based clock can be used for this.)
#. Trigger a task to start execution upon waking up from standby. This can be achieved together with the use of semaphores to synchronize activities in the system.

The ClockP module keeps track of all the clock instances that have been created
in the application. It then dynamically checks for the timeout that is closest
in the near future, and programs that to be the next timeout duration for the
System Timer. The System Timer then generates an interrupt upon the expiration of
the timeout, which eventually calls the user defined callback for the clock that
timed-out.


Upon timeout, the ClockP module calls a user-defined callback function. In the case
of multiple ClockP instances, the user has two choices when it comes to defining
a callback function. It is possible to define individual callback functions
to each of the clocks. Alternatively, it is also possible to define the same callback
function for each of the clocks, but assign a unique argument to that clock instance.
In the case of the timeout, and having a shared callback function for all the ClockP
based clocks in the system, the callback function will be called, and the user can
add handling in the callback function to determine which clock timed-out by processing
the argument that the callback function was called with.

For more information on how the ClockP module can be used in an embedded application,
please refer to the following training that showcases how a ClockP clock can be used
together with the Data Stream Example: `ClockP with the Basic_Ble example <https://dev.ti.com/tirex/explore/content/simplelink_academy_for_cc23xx_7_40_00_00/_build_simplelink_academy_for_cc23xx_7_40_00_00/source/cc2340rx_04_connections.html#task-3-create-a-oneshot-or-periodic-clock-using-clockp-module>`_

Following is a simple code snippet that shows how to initialize a One-shot clock
instance. (A similar procedure can be followed for creating a periodic clock):

.. code-block:: c
   :caption: Following is the variable, and callback definition required before initializing dockerany ClockP clock:
   :linenos:

      // Include the ClockP header file that contains the variable and function definitions
      #include <ti/drivers/dpl/ClockP.h>

      /* The following three variables can be either global or local. Note that the
      * clockParams and the myClockHandle variables must not be shared between clock
      * instances. It is quintessential that each clock instance have it's own clock
      * handle, and clock parameters.
      */

      // Struct that contains ClockP_parameters
      ClockP_Params clockParams;

      // ClockP handle that will be assigned to this specific ClockP clock.
      ClockP_Handle myClockHandle;

      // Argument used for this clock instance
      uintptr_t argForClockP;

      // Function prototype for the user-defined callback function:
      uintptr_t somePointer_1;
      uintptr_t somePointer_2;
      void myClockTimeoutHandler (uintptr_t arg)
      {
         /*
         * User defined code here:
         */
         if(arg == somePointer_1)
         {
            // Do something
         }
         else if ( arg == somePointer_2)
         {
            // Do something different
         }
         else
         {
            // Do something else. In this example code, the "else" block will run.
         }
      }

Add the following inside the function body where you want to start the clock from:

.. code-block:: c
   :linenos:

      argForClockP = 0xAA;

      ClockP_Params_init(&clockParams);

      // Period for the clock, 0 indicates one-shot clock
      clockParams.period    = 0;
      clockParams.startFlag = false;

      /* .arg is the argument used for this clock instance. It will be passed onto
      * the user-defined callback function. The argument must be of type uintptr_t.
      */
      clockParams.arg    = argForClockP;
      myClockHandle      = ClockP_create(myClockTimeoutHandler, 0, &clockParams);
      if (NULL == myClockHandle)
      {
         return 0;
      }

      // Set the clock timeout to be equal to 1s
      ClockP_setTimeout(myClockHandle, 1000000);

      // Start the clock
      ClockP_start(myClockHandle);

FreeRTOS Timer
--------------
FreeRTOS has its own timer module. For more information, please refer to: |FreeRTOS SOFTWARE TIMERS|
