1 /*
2  * Copyright 2017-2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 #ifndef _FSL_QTMR_H_
8 #define _FSL_QTMR_H_
9 
10 #include "fsl_common.h"
11 
12 /*!
13  * @addtogroup qtmr
14  * @{
15  */
16 
17 /*******************************************************************************
18  * Definitions
19  ******************************************************************************/
20 #ifndef TMR_CSCTRL_OFLAG_MASK
21 #define TMR_CSCTRL_OFLAG_MASK (0x100UL)
22 #endif
23 
24 #ifndef TMR_CSCTRL_OFLAG_SHIFT
25 #define TMR_CSCTRL_OFLAG_SHIFT (8UL)
26 #endif
27 
28 /*! @name Driver version */
29 /*@{*/
30 #define FSL_QTMR_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*!< Version */
31 /*@}*/
32 
33 /*! @brief Quad Timer primary clock source selection*/
34 typedef enum _qtmr_primary_count_source
35 {
36     kQTMR_ClockCounter0InputPin = 0, /*!< Use counter 0 input pin */
37     kQTMR_ClockCounter1InputPin,     /*!< Use counter 1 input pin */
38     kQTMR_ClockCounter2InputPin,     /*!< Use counter 2 input pin */
39     kQTMR_ClockCounter3InputPin,     /*!< Use counter 3 input pin */
40     kQTMR_ClockCounter0Output,       /*!< Use counter 0 output */
41     kQTMR_ClockCounter1Output,       /*!< Use counter 1 output */
42     kQTMR_ClockCounter2Output,       /*!< Use counter 2 output */
43     kQTMR_ClockCounter3Output,       /*!< Use counter 3 output */
44     kQTMR_ClockDivide_1,             /*!< IP bus clock divide by 1 prescaler */
45     kQTMR_ClockDivide_2,             /*!< IP bus clock divide by 2 prescaler */
46     kQTMR_ClockDivide_4,             /*!< IP bus clock divide by 4 prescaler */
47     kQTMR_ClockDivide_8,             /*!< IP bus clock divide by 8 prescaler */
48     kQTMR_ClockDivide_16,            /*!< IP bus clock divide by 16 prescaler */
49     kQTMR_ClockDivide_32,            /*!< IP bus clock divide by 32 prescaler */
50     kQTMR_ClockDivide_64,            /*!< IP bus clock divide by 64 prescaler */
51     kQTMR_ClockDivide_128            /*!< IP bus clock divide by 128 prescaler */
52 } qtmr_primary_count_source_t;
53 
54 /*! @brief Quad Timer input sources selection*/
55 typedef enum _qtmr_input_source
56 {
57     kQTMR_Counter0InputPin = 0, /*!< Use counter 0 input pin */
58     kQTMR_Counter1InputPin,     /*!< Use counter 1 input pin */
59     kQTMR_Counter2InputPin,     /*!< Use counter 2 input pin */
60     kQTMR_Counter3InputPin      /*!< Use counter 3 input pin */
61 } qtmr_input_source_t;
62 
63 /*! @brief Quad Timer counting mode selection */
64 typedef enum _qtmr_counting_mode
65 {
66     kQTMR_NoOperation = 0,          /*!< No operation */
67     kQTMR_PriSrcRiseEdge,           /*!< Count rising edges of primary source */
68     kQTMR_PriSrcRiseAndFallEdge,    /*!< Count rising and falling edges of primary source */
69     kQTMR_PriSrcRiseEdgeSecInpHigh, /*!< Count rise edges of pri SRC while sec inp high active */
70     kQTMR_QuadCountMode,            /*!< Quadrature count mode, uses pri and sec sources */
71     kQTMR_PriSrcRiseEdgeSecDir,     /*!< Count rising edges of pri SRC; sec SRC specifies dir */
72     kQTMR_SecSrcTrigPriCnt,         /*!< Edge of sec SRC trigger primary count until compare*/
73     kQTMR_CascadeCount              /*!< Cascaded count mode (up/down) */
74 } qtmr_counting_mode_t;
75 
76 /*! @brief Quad Timer PWM output state */
77 typedef enum _qtmr_pwm_out_state
78 {
79     kQTMR_PwmLow = 0, /*!< The output state of PWM channel is low */
80     kQTMR_PwmHigh,    /*!< The output state of PWM channel is low  */
81 } qtmr_pwm_out_state_t;
82 
83 /*! @brief Quad Timer output mode selection*/
84 typedef enum _qtmr_output_mode
85 {
86     kQTMR_AssertWhenCountActive = 0,    /*!< Assert OFLAG while counter is active*/
87     kQTMR_ClearOnCompare,               /*!< Clear OFLAG on successful compare */
88     kQTMR_SetOnCompare,                 /*!< Set OFLAG on successful compare */
89     kQTMR_ToggleOnCompare,              /*!< Toggle OFLAG on successful compare */
90     kQTMR_ToggleOnAltCompareReg,        /*!< Toggle OFLAG using alternating compare registers */
91     kQTMR_SetOnCompareClearOnSecSrcInp, /*!< Set OFLAG on compare, clear on sec SRC input edge */
92     kQTMR_SetOnCompareClearOnCountRoll, /*!< Set OFLAG on compare, clear on counter rollover */
93     kQTMR_EnableGateClock               /*!< Enable gated clock output while count is active */
94 } qtmr_output_mode_t;
95 
96 /*! @brief Quad Timer input capture edge mode, rising edge, or falling edge */
97 typedef enum _qtmr_input_capture_edge
98 {
99     kQTMR_NoCapture = 0,       /*!< Capture is disabled */
100     kQTMR_RisingEdge,          /*!< Capture on rising edge (IPS=0) or falling edge (IPS=1)*/
101     kQTMR_FallingEdge,         /*!< Capture on falling edge (IPS=0) or rising edge (IPS=1)*/
102     kQTMR_RisingAndFallingEdge /*!< Capture on both edges */
103 } qtmr_input_capture_edge_t;
104 
105 /*! @brief Quad Timer input capture edge mode, rising edge, or falling edge */
106 typedef enum _qtmr_preload_control
107 {
108     kQTMR_NoPreload = 0, /*!< Never preload */
109     kQTMR_LoadOnComp1,   /*!< Load upon successful compare with value in COMP1 */
110     kQTMR_LoadOnComp2    /*!< Load upon successful compare with value in COMP2*/
111 } qtmr_preload_control_t;
112 
113 /*! @brief List of Quad Timer run options when in Debug mode */
114 typedef enum _qtmr_debug_action
115 {
116     kQTMR_RunNormalInDebug = 0U, /*!< Continue with normal operation */
117     kQTMR_HaltCounter,           /*!< Halt counter */
118     kQTMR_ForceOutToZero,        /*!< Force output to logic 0 */
119     kQTMR_HaltCountForceOutZero  /*!< Halt counter and force output to logic 0 */
120 } qtmr_debug_action_t;
121 
122 /*! @brief List of Quad Timer interrupts */
123 // typedef enum _qtmr_interrupt_enable
124 typedef enum _qtmr_interrupt_enable
125 {
126     kQTMR_CompareInterruptEnable  = (1U << 0), /*!< Compare interrupt.*/
127     kQTMR_Compare1InterruptEnable = (1U << 1), /*!< Compare 1 interrupt.*/
128     kQTMR_Compare2InterruptEnable = (1U << 2), /*!< Compare 2 interrupt.*/
129     kQTMR_OverflowInterruptEnable = (1U << 3), /*!< Timer overflow interrupt.*/
130     kQTMR_EdgeInterruptEnable     = (1U << 4)  /*!< Input edge interrupt.*/
131 } qtmr_interrupt_enable_t;
132 
133 /*! @brief List of Quad Timer flags */
134 typedef enum _qtmr_status_flags
135 {
136     kQTMR_CompareFlag  = (1U << 0), /*!< Compare flag */
137     kQTMR_Compare1Flag = (1U << 1), /*!< Compare 1 flag */
138     kQTMR_Compare2Flag = (1U << 2), /*!< Compare 2 flag */
139     kQTMR_OverflowFlag = (1U << 3), /*!< Timer overflow flag */
140     kQTMR_EdgeFlag     = (1U << 4)  /*!< Input edge flag */
141 } qtmr_status_flags_t;
142 
143 /*! @brief List of channel selection */
144 typedef enum _qtmr_channel_selection
145 {
146     kQTMR_Channel_0 = 0U, /*!< TMR Channel 0 */
147     kQTMR_Channel_1,      /*!< TMR Channel 1 */
148     kQTMR_Channel_2,      /*!< TMR Channel 2 */
149     kQTMR_Channel_3,      /*!< TMR Channel 3 */
150 } qtmr_channel_selection_t;
151 
152 /*! @brief List of Quad Timer DMA enable */
153 typedef enum _qtmr_dma_enable
154 {
155     kQTMR_InputEdgeFlagDmaEnable      = (1U << 0), /*!< Input Edge Flag DMA Enable.*/
156     kQTMR_ComparatorPreload1DmaEnable = (1U << 1), /*!< Comparator Preload Register 1 DMA Enable.*/
157     kQTMR_ComparatorPreload2DmaEnable = (1U << 2), /*!< Comparator Preload Register 2 DMA Enable.*/
158 } qtmr_dma_enable_t;
159 
160 /*!
161  * @brief Quad Timer config structure
162  *
163  * This structure holds the configuration settings for the Quad Timer peripheral. To initialize this
164  * structure to reasonable defaults, call the QTMR_GetDefaultConfig() function and pass a
165  * pointer to your config structure instance.
166  *
167  * The config struct can be made const so it resides in flash
168  */
169 typedef struct _qtmr_config
170 {
171     qtmr_primary_count_source_t primarySource; /*!< Specify the primary count source */
172     qtmr_input_source_t secondarySource;       /*!< Specify the secondary count source */
173     bool enableMasterMode;                     /*!< true: Broadcast compare function output to other counters;
174                                                     false no broadcast */
175     bool enableExternalForce;                  /*!< true: Compare from another counter force state of OFLAG signal
176                                                     false: OFLAG controlled by local counter */
177     uint8_t faultFilterCount;                  /*!< Fault filter count */
178     uint8_t faultFilterPeriod;                 /*!< Fault filter period;value of 0 will bypass the filter */
179     qtmr_debug_action_t debugMode;             /*!< Operation in Debug mode */
180 } qtmr_config_t;
181 
182 /*******************************************************************************
183  * API
184  ******************************************************************************/
185 
186 #if defined(__cplusplus)
187 extern "C" {
188 #endif
189 
190 /*!
191  * @name Initialization and deinitialization
192  * @{
193  */
194 
195 /*!
196  * @brief Ungates the Quad Timer clock and configures the peripheral for basic operation.
197  *
198  * @note This API should be called at the beginning of the application using the Quad Timer driver.
199  *
200  * @param base     Quad Timer peripheral base address
201  * @param channel  Quad Timer channel number
202  * @param config   Pointer to user's Quad Timer config structure
203  */
204 void QTMR_Init(TMR_Type *base, qtmr_channel_selection_t channel, const qtmr_config_t *config);
205 
206 /*!
207  * @brief Stops the counter and gates the Quad Timer clock
208  *
209  * @param base     Quad Timer peripheral base address
210  * @param channel  Quad Timer channel number
211  */
212 void QTMR_Deinit(TMR_Type *base, qtmr_channel_selection_t channel);
213 
214 /*!
215  * @brief  Fill in the Quad Timer config struct with the default settings
216  *
217  * The default values are:
218  * @code
219  *    config->debugMode = kQTMR_RunNormalInDebug;
220  *    config->enableExternalForce = false;
221  *    config->enableMasterMode = false;
222  *    config->faultFilterCount = 0;
223  *    config->faultFilterPeriod = 0;
224  *    config->primarySource = kQTMR_ClockDivide_2;
225  *    config->secondarySource = kQTMR_Counter0InputPin;
226  * @endcode
227  * @param config Pointer to user's Quad Timer config structure.
228  */
229 void QTMR_GetDefaultConfig(qtmr_config_t *config);
230 
231 /*! @}*/
232 
233 /*!
234  * @brief Sets up Quad timer module for PWM signal output.
235  *
236  * The function initializes the timer module according to the parameters passed in by the user. The
237  * function also sets up the value compare registers to match the PWM signal requirements.
238  *
239  * @param base             Quad Timer peripheral base address
240  * @param channel          Quad Timer channel number
241  * @param pwmFreqHz        PWM signal frequency in Hz
242  * @param dutyCyclePercent PWM pulse width, value should be between 0 to 100
243  *                         0=inactive signal(0% duty cycle)...
244  *                         100=active signal (100% duty cycle)
245  * @param outputPolarity   true: invert polarity of the output signal, false: no inversion
246  * @param srcClock_Hz      Main counter clock in Hz.
247  *
248  * @return Returns an error if there was error setting up the signal.
249  */
250 status_t QTMR_SetupPwm(TMR_Type *base,
251                        qtmr_channel_selection_t channel,
252                        uint32_t pwmFreqHz,
253                        uint8_t dutyCyclePercent,
254                        bool outputPolarity,
255                        uint32_t srcClock_Hz);
256 
257 /*!
258  * @brief Allows the user to count the source clock cycles until a capture event arrives.
259  *
260  * The count is stored in the capture register.
261  *
262  * @param base            Quad Timer peripheral base address
263  * @param channel         Quad Timer channel number
264  * @param capturePin      Pin through which we receive the input signal to trigger the capture
265  * @param inputPolarity   true: invert polarity of the input signal, false: no inversion
266  * @param reloadOnCapture true: reload the counter when an input capture occurs, false: no reload
267  * @param captureMode     Specifies which edge of the input signal  triggers a capture
268  */
269 void QTMR_SetupInputCapture(TMR_Type *base,
270                             qtmr_channel_selection_t channel,
271                             qtmr_input_source_t capturePin,
272                             bool inputPolarity,
273                             bool reloadOnCapture,
274                             qtmr_input_capture_edge_t captureMode);
275 
276 /*!
277  * @name Interrupt Interface
278  * @{
279  */
280 
281 /*!
282  * @brief Enables the selected Quad Timer interrupts
283  *
284  * @param base      Quad Timer peripheral base address
285  * @param channel   Quad Timer channel number
286  * @param mask      The interrupts to enable. This is a logical OR of members of the
287  *                  enumeration ::qtmr_interrupt_enable_t
288  */
289 void QTMR_EnableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask);
290 
291 /*!
292  * @brief Disables the selected Quad Timer interrupts
293  *
294  * @param base     Quad Timer peripheral base addres
295  * @param channel  Quad Timer channel number
296  * @param mask The interrupts to enable. This is a logical OR of members of the
297  *             enumeration ::qtmr_interrupt_enable_t
298  */
299 void QTMR_DisableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask);
300 
301 /*!
302  * @brief Gets the enabled Quad Timer interrupts
303  *
304  * @param base    Quad Timer peripheral base address
305  * @param channel Quad Timer channel number
306  *
307  * @return The enabled interrupts. This is the logical OR of members of the
308  *         enumeration ::qtmr_interrupt_enable_t
309  */
310 uint32_t QTMR_GetEnabledInterrupts(TMR_Type *base, qtmr_channel_selection_t channel);
311 
312 /*! @}*/
313 
314 /*!
315  * @name Status Interface
316  * @{
317  */
318 
319 /*!
320  * @brief Gets the Quad Timer status flags
321  *
322  * @param base     Quad Timer peripheral base address
323  * @param channel  Quad Timer channel number
324  *
325  * @return The status flags. This is the logical OR of members of the
326  *         enumeration ::qtmr_status_flags_t
327  */
328 uint32_t QTMR_GetStatus(TMR_Type *base, qtmr_channel_selection_t channel);
329 
330 /*!
331  * @brief Clears the Quad Timer status flags.
332  *
333  * @param base     Quad Timer peripheral base address
334  * @param channel  Quad Timer channel number
335  * @param mask The status flags to clear. This is a logical OR of members of the
336  *             enumeration ::qtmr_status_flags_t
337  */
338 void QTMR_ClearStatusFlags(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask);
339 
340 /*! @}*/
341 
342 /*!
343  * @name Read and Write the timer period
344  * @{
345  */
346 
347 /*!
348  * @brief Sets the timer period in ticks.
349  *
350  * Timers counts from initial value till it equals the count value set here. The counter
351  * will then reinitialize to the value specified in the Load register.
352  *
353  * @note
354  * 1. This function will write the time period in ticks to COMP1 or COMP2 register
355  *    depending on the count direction
356  * 2. User can call the utility macros provided in fsl_common.h to convert to ticks
357  * 3. This function supports cases, providing only primary source clock without secondary source clock.
358  *
359  * @param base     Quad Timer peripheral base address
360  * @param channel  Quad Timer channel number
361  * @param ticks Timer period in units of ticks
362  */
363 void QTMR_SetTimerPeriod(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t ticks);
364 
365 /*!
366  * @brief Set compare value.
367  *
368  * This function sets the value used for comparison with the counter value.
369  *
370  * @param base     Quad Timer peripheral base address
371  * @param channel  Quad Timer channel number
372  * @param ticks    Timer period in units of ticks.
373  */
374 void QTMR_SetCompareValue(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t ticks);
375 
376 /*!
377  * @brief Set load value.
378  *
379  * This function sets the value used to initialize the counter after a counter comparison.
380  *
381  * @param base     Quad Timer peripheral base address
382  * @param channel  Quad Timer channel number
383  * @param value    Load register initialization value.
384  */
QTMR_SetLoadValue(TMR_Type * base,qtmr_channel_selection_t channel,uint16_t value)385 static inline void QTMR_SetLoadValue(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t value)
386 {
387     base->CHANNEL[channel].LOAD &= (uint16_t)(~TMR_LOAD_LOAD_MASK);
388     base->CHANNEL[channel].LOAD = value;
389 }
390 
391 /*!
392  * @brief Reads the current timer counting value.
393  *
394  * This function returns the real-time timer counting value, in a range from 0 to a
395  * timer period.
396  *
397  * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec
398  *
399  * @param base     Quad Timer peripheral base address
400  * @param channel  Quad Timer channel number
401  *
402  * @return Current counter value in ticks
403  */
QTMR_GetCurrentTimerCount(TMR_Type * base,qtmr_channel_selection_t channel)404 static inline uint16_t QTMR_GetCurrentTimerCount(TMR_Type *base, qtmr_channel_selection_t channel)
405 {
406     return base->CHANNEL[channel].CNTR;
407 }
408 
409 /*! @}*/
410 
411 /*!
412  * @name Timer Start and Stop
413  * @{
414  */
415 
416 /*!
417  * @brief Starts the Quad Timer counter.
418  *
419  *
420  * @param base        Quad Timer peripheral base address
421  * @param channel     Quad Timer channel number
422  * @param clockSource Quad Timer clock source
423  */
QTMR_StartTimer(TMR_Type * base,qtmr_channel_selection_t channel,qtmr_counting_mode_t clockSource)424 static inline void QTMR_StartTimer(TMR_Type *base, qtmr_channel_selection_t channel, qtmr_counting_mode_t clockSource)
425 {
426     uint16_t reg = base->CHANNEL[channel].CTRL;
427 
428     reg &= (uint16_t)(~(TMR_CTRL_CM_MASK));
429     reg |= TMR_CTRL_CM(clockSource);
430     base->CHANNEL[channel].CTRL = reg;
431 }
432 
433 /*!
434  * @brief Stops the Quad Timer counter.
435  *
436  * @param base     Quad Timer peripheral base address
437  * @param channel  Quad Timer channel number
438  */
QTMR_StopTimer(TMR_Type * base,qtmr_channel_selection_t channel)439 static inline void QTMR_StopTimer(TMR_Type *base, qtmr_channel_selection_t channel)
440 {
441     base->CHANNEL[channel].CTRL &= (uint16_t)(~TMR_CTRL_CM_MASK);
442 }
443 
444 /*! @}*/
445 
446 /*!
447  * @name Enable and Disable the Quad Timer DMA
448  * @{
449  */
450 
451 /*!
452  * @brief Enable the Quad Timer DMA.
453  *
454  * @param base     Quad Timer peripheral base address
455  * @param channel  Quad Timer channel number
456  * @param mask     The DMA to enable. This is a logical OR of members of the
457  *                  enumeration ::qtmr_dma_enable_t
458  */
459 void QTMR_EnableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask);
460 
461 /*!
462  * @brief Disable the Quad Timer DMA.
463  *
464  * @param base     Quad Timer peripheral base address
465  * @param channel  Quad Timer channel number
466  * @param mask     The DMA to enable. This is a logical OR of members of the
467  *                  enumeration ::qtmr_dma_enable_t
468  */
469 void QTMR_DisableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask);
470 
471 /*!
472  * @brief Set PWM output in idle status (high or low).
473  *
474  * @note When the PWM is set again, the counting needs to be restarted.
475  *
476  * @param base     Quad Timer peripheral base address
477  * @param channel  Quad Timer channel number
478  * @param idleStatus   True: PWM output is high in idle status; false: PWM output is low in idle status.
479  */
480 void QTMR_SetPwmOutputToIdle(TMR_Type *base, qtmr_channel_selection_t channel, bool idleStatus);
481 
482 /*!
483  * @brief Get the channel output status
484  *
485  * @param base     Quad Timer peripheral base address
486  * @param channel  Quad Timer channel number
487  *
488  * @return Current channel output status.
489  */
QTMR_GetPwmOutputStatus(TMR_Type * base,qtmr_channel_selection_t channel)490 static inline qtmr_pwm_out_state_t QTMR_GetPwmOutputStatus(TMR_Type *base, qtmr_channel_selection_t channel)
491 {
492     if (0U != ((base->CHANNEL[channel].CSCTRL) & TMR_CSCTRL_OFLAG_MASK))
493     {
494         return kQTMR_PwmHigh;
495     }
496     else
497     {
498         return kQTMR_PwmLow;
499     }
500 }
501 
502 /*!
503  * @brief Get the PWM channel dutycycle value.
504  *
505  * @param base     Quad Timer peripheral base address
506  * @param channel  Quad Timer channel number
507  *
508  * @return Current channel dutycycle value.
509  */
510 uint8_t QTMR_GetPwmChannelStatus(TMR_Type *base, qtmr_channel_selection_t channel);
511 
512 /*!
513  * @brief This function set the value of the prescaler on QTimer channels.
514  *
515  * @param base         Quad Timer peripheral base address
516  * @param channel      Quad Timer channel number
517  * @param prescaler    Set prescaler value
518  */
519 void QTMR_SetPwmClockMode(TMR_Type *base, qtmr_channel_selection_t channel, qtmr_primary_count_source_t prescaler);
520 
521 /*! @}*/
522 
523 #if defined(__cplusplus)
524 }
525 #endif
526 
527 /*! @}*/
528 
529 #endif /* _FSL_QTMR_H_ */
530