1 /***************************************************************************//**
2 * \file cyhal_timer.h
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon Timer/Counter.
6 * This interface abstracts out the chip specific details. If any chip specific
7 * functionality is necessary, or performance is critical the low level functions
8 * can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 *     http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 
30 /**
31 * \addtogroup group_hal_timer Timer (Timer/Counter)
32 * \ingroup group_hal
33 * \{
34 * High level interface for interacting with the Timer/Counter hardware resource.
35 *
36 * The timer block is commonly used to measure the time of occurrence of an event,
37 * to measure the time difference between two events or perform an action after
38 * a specified period of time. The driver also allows the user to invoke a callback function
39 * when a particular event occurs.
40 *
41 * Some use case scenarios of timer -
42 *
43 * * Creating a periodic interrupt for executing periodic tasks
44 * * Measuring time between two events
45 * * Triggering other system resources after a certain number of events
46 * * Capturing time stamps when events occur
47 *
48 * \section subsection_timer_features Features
49 * * Runtime configurable parameters like period and compare value - \ref cyhal_timer_cfg_t
50 * * Configurable counting direction - \ref cyhal_timer_direction_t
51 * * Interrupt on various events - \ref cyhal_timer_event_t
52 * * Continuous or One Shot run modes
53 *
54 * \section subsection_timer_quickstart Quick Start
55 *
56 * \ref cyhal_timer_init can be used for timer initialization by providing the timer object - \ref cyhal_timer_t,
57 * and shared clock source - <b> clk </b> (optional). The timer parameters needs to be populated in \ref cyhal_timer_cfg_t structure.
58 * The timer then needs to be configured by using the \ref cyhal_timer_configure function.
59 *
60 * \note A default frequency is set when an existing clock divider - <b> clk </b> is not provided to \ref cyhal_timer_init which is
61 * defined by the macro - \ref CYHAL_TIMER_DEFAULT_FREQ.
62 *
63 * \warning Currently there is no support for pin connections to Timer using this driver. So, the <b> pin </b> should be
64 * assigned as \ref NC while using the \ref cyhal_timer_init to initialize the timer.
65 *
66 *
67 * See \ref subsection_timer_snippet_1.
68 *
69 * \section subsection_timer_sample_snippets Code Snippets
70 *
71 * \subsection subsection_timer_snippet_1 Snippet 1: Measuring time of an operation
72 * The following snippet initializes a Timer and measures the time between two events.
73 * The <b>clk</b> need not be provided, in which case a clock resource is assigned.
74 * \snippet hal_timer.c snippet_cyhal_timer_event_measure
75 *
76 * \subsection subsection_timer_snippet_2 Snippet 2: Handling an event in a callback function
77 * The following snippet initializes a Timer and triggers an event after every one second.
78 * The <b>clk</b> need not be provided (NULL), in which case a clock resource is assigned.
79 * \snippet hal_timer.c snippet_cyhal_timer_event_interrupt
80 *
81 */
82 
83 #pragma once
84 
85 #include <stdint.h>
86 #include <stdbool.h>
87 #include "cy_result.h"
88 #include "cyhal_hw_types.h"
89 #if defined(COMPONENT_CAT5)
90 #include "cyhal_t2timer.h"
91 #endif
92 
93 #if defined(__cplusplus)
94 extern "C" {
95 #endif
96 
97 /** \addtogroup group_hal_results_timer Timer HAL Results
98  *  Timer specific return codes
99  *  \ingroup group_hal_results
100  *  \{ *//**
101  */
102 
103 /** Bad argument. eg: null pointer */
104 #define CYHAL_TIMER_RSLT_ERR_BAD_ARGUMENT               \
105     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 0))
106 /** Failed to initialize Timer clock */
107 #define CYHAL_TIMER_RSLT_ERR_CLOCK_INIT                 \
108     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 1))
109 /** Failed to initialize Timer */
110 #define CYHAL_TIMER_RSLT_ERR_INIT                       \
111     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 2))
112 /** Cannot change the timer frequency when a shared clock divider is in use */
113 #define CYHAL_TIMER_RSLT_ERR_SHARED_CLOCK               \
114     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 3))
115 /** Feature unsupported with this Timer */
116 #define CYHAL_TIMER_RSLT_ERR_UNSUPPORTED                \
117     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 4))
118 
119 /**
120  * \}
121  */
122 
123 /*******************************************************************************
124 *       Enumerations
125 *******************************************************************************/
126 
127 /** Timer directions */
128 typedef enum
129 {
130     CYHAL_TIMER_DIR_UP, //!< Counts up
131     CYHAL_TIMER_DIR_DOWN, //!< Counts down
132     CYHAL_TIMER_DIR_UP_DOWN, //!< Counts up and down, terminal count occurs on both overflow and underflow.
133 } cyhal_timer_direction_t;
134 
135 /** Timer/counter interrupt triggers */
136 typedef enum {
137     CYHAL_TIMER_IRQ_NONE            =  0, /**< No interrupt handled **/
138     CYHAL_TIMER_IRQ_TERMINAL_COUNT  =  1 << 0, /**< Interrupt when terminal count is reached **/
139     CYHAL_TIMER_IRQ_CAPTURE_COMPARE =  1 << 1, /**< Interrupt when Compare/Capture value is reached **/
140     CYHAL_TIMER_IRQ_ALL             = (1 << 2) - 1, /**< Interrupt on terminal count and Compare/Capture values **/
141 } cyhal_timer_event_t;
142 
143 /** Timer/counter input signal */
144 typedef enum
145 {
146     CYHAL_TIMER_INPUT_START,    //!< Start signal
147     CYHAL_TIMER_INPUT_STOP,     //!< Stop signal
148     CYHAL_TIMER_INPUT_RELOAD,   //!< Reload signal
149     CYHAL_TIMER_INPUT_COUNT,    //!< Count signal
150     CYHAL_TIMER_INPUT_CAPTURE,  //!< Capture signal
151 } cyhal_timer_input_t;
152 
153 /** Timer/counter output signal */
154 typedef enum
155 {
156     CYHAL_TIMER_OUTPUT_OVERFLOW,       //!< Overflow signal
157     CYHAL_TIMER_OUTPUT_UNDERFLOW,      //!< Underflow signal
158     CYHAL_TIMER_OUTPUT_COMPARE_MATCH,  //!< Compare Match signal
159     CYHAL_TIMER_OUTPUT_TERMINAL_COUNT, //!< Terminal count signal (logical OR of overflow and underflow signal)
160 } cyhal_timer_output_t;
161 
162 /*******************************************************************************
163 *       Data Structures
164 *******************************************************************************/
165 
166 /** @brief Describes the current configuration of a timer/counter */
167 typedef struct
168 {
169     /**
170       * Whether the timer is set to continuously run.
171       * If true, the timer will run forever.
172       * Otherwise, the timer will run once and stop (one shot).
173       */
174     bool is_continuous; //!< Whether the timer/counter operates continuous (true) or one shot (false)
175     cyhal_timer_direction_t direction; //!< Direction the timer/counter is running
176     bool is_compare; //!< Is it in compare (true) or capture (false) mode
177     uint32_t period; //!< Timer/counter period
178     uint32_t compare_value; //!< Timer/counter comparison value
179     uint32_t value; //!< Default value of the timer/counter. \ref cyhal_timer_reset() will also change counter to this value when called.
180 } cyhal_timer_cfg_t;
181 
182 /*******************************************************************************
183 *       Typedefs
184 *******************************************************************************/
185 
186 /** Handler for timer events */
187 typedef void(*cyhal_timer_event_callback_t)(void *callback_arg, cyhal_timer_event_t event);
188 
189 /*******************************************************************************
190 *       Defines
191 *******************************************************************************/
192 
193 /** Default timer frequency, used when an existing clock divider is not provided to \ref cyhal_timer_init() */
194 #define CYHAL_TIMER_DEFAULT_FREQ (1000000u)
195 
196 /*******************************************************************************
197 *       Functions
198 *******************************************************************************/
199 
200 /** Initialize the timer/counter peripheral and configure the pin. <br>
201  * See \ref subsection_timer_snippet_1.
202  *
203  * @param[out] obj  Pointer to a timer/counter object. The caller must allocate the memory
204  *  for this object but the init function will initialize its contents.
205  * @param[in]  pin optional - The timer/counter compare/capture pin to initialize
206  * @param[in]  clk optional - The shared clock to use, if not provided a new clock will be allocated
207  *                  and the timer frequency will be set to \ref CYHAL_TIMER_DEFAULT_FREQ
208  * @return The status of the init request
209  */
210 cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clock_t *clk);
211 
212 /** Initialize the Timer peripheral using a configurator generated configuration struct
213   *
214  * @param[out] obj              Pointer to a Timer object. The caller must allocate the memory
215  *                              for this object but the init function will initialize its contents.
216  * @param[in] cfg               Configuration structure generated by a configurator.
217  * @return The status of the init request
218  */
219  cy_rslt_t cyhal_timer_init_cfg(cyhal_timer_t *obj, const cyhal_timer_configurator_t *cfg);
220 
221 /** Deinitialize the timer/counter object
222  *
223  * @param[in,out] obj The timer/counter object
224  */
225 void cyhal_timer_free(cyhal_timer_t *obj);
226 
227 /** Updates the configuration and counter value of the timer/counter object. <br>
228  * This function may temporary stop the timer if it is currently running.
229  * See \ref subsection_timer_snippet_1.
230  * @param[in] obj  The timer/counter object
231  * @param[in] cfg  The configuration of the timer/counter
232  * @return The status of the configure request
233  */
234 cy_rslt_t cyhal_timer_configure(cyhal_timer_t *obj, const cyhal_timer_cfg_t *cfg);
235 
236 /** Configures the timer frequency.
237  * \note This is only valid to call if a null clock divider was provided to \ref cyhal_timer_init.
238  * If a custom clock was provided its frequency should be adjusted directly.
239  *
240  * See \ref subsection_timer_snippet_1.
241  * @param[in] obj  The timer/counter object
242  * @param[in] hz   The frequency rate in Hz
243  * @return The status of the set_frequency request
244  */
245 cy_rslt_t cyhal_timer_set_frequency(cyhal_timer_t *obj, uint32_t hz);
246 
247 /** Starts the timer/counter with the pre-set configuration from \ref cyhal_timer_configure.
248  * This does not reset the counter. The count value will start from the value that was
249  * set by the last operation to modify it. See \ref cyhal_timer_configure, and \ref
250  * cyhal_timer_reset for how the value can be changed. If none of these functions have
251  * been called, it will start from 0.<br>
252  * See \ref subsection_timer_snippet_1.
253  *
254  * @param[in] obj     The timer/counter object
255  * @return The status of the start request
256  */
257 cy_rslt_t cyhal_timer_start(cyhal_timer_t *obj);
258 
259 /** Stops the timer/counter. Does not reset counter value. <br>
260  *
261  * @param[in] obj     The timer/counter object
262  * @return The status of the stop request
263  */
264 cy_rslt_t cyhal_timer_stop(cyhal_timer_t *obj);
265 
266 /** Reset the timer/counter value to the default value set from \ref cyhal_timer_configure.
267  * If \ref cyhal_timer_configure was never called, this will reset timer/counter value to 0.
268  * This function may temporary stop the timer. <br>
269  *
270  * @param[in] obj     The timer/counter object
271  * @return The status of the reset request
272  */
273 cy_rslt_t cyhal_timer_reset(cyhal_timer_t *obj);
274 
275 /** Reads the current value from the timer/counter <br>
276  * See \ref subsection_timer_snippet_1.
277  *
278  * @param[in] obj     The timer/counter object
279  * @return The current value of the timer/counter
280  */
281 uint32_t cyhal_timer_read(const cyhal_timer_t *obj);
282 
283 /** Register a timer/counter callback handler<br>
284  *
285  * This function will be called when one of the events enabled by \ref cyhal_timer_enable_event occurs.
286  *
287  * See \ref subsection_timer_snippet_2.
288  *
289  * @param[in] obj          The timer/counter object
290  * @param[in] callback     The callback handler which will be invoked when the event occurs
291  * @param[in] callback_arg Generic argument that will be provided to the callback when called
292  */
293 void cyhal_timer_register_callback(cyhal_timer_t *obj, cyhal_timer_event_callback_t callback, void *callback_arg);
294 
295 /** Configure timer/counter event enablement <br>
296  *
297  * When an enabled event occurs, the function specified by \ref cyhal_timer_register_callback will be called.
298  *
299  * See \ref subsection_timer_snippet_2.
300  *
301  * @param[in] obj           The timer/counter object
302  * @param[in] event         The timer/counter event type
303  * @param[in] intr_priority  The priority for NVIC interrupt events
304  * @param[in] enable        True to turn on interrupts, False to turn off
305  */
306 void cyhal_timer_enable_event(cyhal_timer_t *obj, cyhal_timer_event_t event, uint8_t intr_priority, bool enable);
307 
308 /** Connects a source signal and configures and enables a timer event to be
309  * triggered from that signal. These timer events can be configured
310  * independently and connect to the same or different source signals.
311  * @note For "edge" signals, this function will default to rising edge. To control the edge type,
312  * use @ref cyhal_timer_connect_digital2
313  *
314  * @param[in] obj      Timer obj
315  * @param[in] source   Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
316  * @param[in] signal   The timer input signal
317  * @return The current status of the connection
318  * */
319 cy_rslt_t cyhal_timer_connect_digital(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal);
320 
321 /** Connects a source signal and configures and enables a timer event to be
322  * triggered from that signal with a configurable edge type. These timer events
323  * can be configured independently and connect to the same or different source signals.
324  *
325  * @param[in] obj       Timer obj
326  * @param[in] source    Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
327  * @param[in] signal    The timer input signal
328  * @param[in] edge_type The edge type that should trigger the event. This must be consistent with the
329  *                      edge type of `source`. If `source` produces a "level" signal, the only valid
330  *                      value is @ref CYHAL_EDGE_TYPE_LEVEL. If `source` produces an "edge" signal, then
331  *                      @ref CYHAL_EDGE_TYPE_LEVEL is not a valid value.
332  * @return The current status of the connection
333  * */
334 cy_rslt_t cyhal_timer_connect_digital2(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal, cyhal_edge_type_t edge_type);
335 
336 /** Enables the specified output signal from a tcpwm that will be triggered
337  * when the corresponding event occurs. Multiple output signals can be
338  * configured simultaneously.
339  *
340  * @param[in]  obj      Timer obj
341  * @param[in]  signal   The timer output signal
342  * @param[out] source   Pointer to user-allocated source signal object which
343  * will be initialized by enable_output. \p source should be passed to
344  * (dis)connect_digital functions to (dis)connect the associated endpoints.
345  * @return The current status of the output enable
346  * */
347 cy_rslt_t cyhal_timer_enable_output(cyhal_timer_t *obj, cyhal_timer_output_t signal, cyhal_source_t *source);
348 
349 /** Disconnects a source signal and disables the timer event.
350  *
351  * @param[in] obj      Timer obj
352  * @param[in] source   Source signal from cyhal_<PERIPH>_enable_output to disable
353  * @param[in] signal   The timer input signal
354  * @return The status of the disconnection
355  * */
356 cy_rslt_t cyhal_timer_disconnect_digital(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal);
357 
358 /** Disables the specified output signal from a timer.
359  *
360  * @param[in]  obj      Timer obj
361  * @param[in]  signal   The timer output signal
362  * @return The status of the output disable
363  * */
364 cy_rslt_t cyhal_timer_disable_output(cyhal_timer_t *obj, cyhal_timer_output_t signal);
365 
366 #if defined(__cplusplus)
367 }
368 #endif
369 
370 #ifdef CYHAL_TIMER_IMPL_HEADER
371 #include CYHAL_TIMER_IMPL_HEADER
372 #endif /* CYHAL_TIMER_IMPL_HEADER */
373 
374 /** \} group_hal_timer */
375