1 /*
2  * Copyright 2017-2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_qtmr.h"
9 
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.qtmr"
13 #endif
14 
15 /*******************************************************************************
16  * Prototypes
17  ******************************************************************************/
18 /*!
19  * @brief Gets the instance from the base address to be used to gate or ungate the module clock
20  *
21  * @param base Quad Timer peripheral base address
22  *
23  * @return The Quad Timer instance
24  */
25 static uint32_t QTMR_GetInstance(TMR_Type *base);
26 
27 /*******************************************************************************
28  * Variables
29  ******************************************************************************/
30 /*! @brief Pointers to Quad Timer bases for each instance. */
31 static TMR_Type *const s_qtmrBases[] = TMR_BASE_PTRS;
32 
33 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
34 /*! @brief Pointers to Quad Timer clocks for each instance. */
35 static const clock_ip_name_t s_qtmrClocks[] = TMR_CLOCKS;
36 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
37 
38 static uint8_t s_qtmrGetPwmDutyCycle[FSL_FEATURE_SOC_TMR_COUNT] = {0U};
39 
40 /*******************************************************************************
41  * Code
42  ******************************************************************************/
QTMR_GetInstance(TMR_Type * base)43 static uint32_t QTMR_GetInstance(TMR_Type *base)
44 {
45     uint32_t instance;
46 
47     /* Find the instance index from base address mappings. */
48     for (instance = 0; instance < ARRAY_SIZE(s_qtmrBases); instance++)
49     {
50         if (s_qtmrBases[instance] == base)
51         {
52             break;
53         }
54     }
55 
56     assert(instance < ARRAY_SIZE(s_qtmrBases));
57 
58     return instance;
59 }
60 
61 /*!
62  * brief Ungates the Quad Timer clock and configures the peripheral for basic operation.
63  *
64  * note This API should be called at the beginning of the application using the Quad Timer driver.
65  *
66  * param base     Quad Timer peripheral base address
67  * param channel  Quad Timer channel number
68  * param config   Pointer to user's Quad Timer config structure
69  */
QTMR_Init(TMR_Type * base,qtmr_channel_selection_t channel,const qtmr_config_t * config)70 void QTMR_Init(TMR_Type *base, qtmr_channel_selection_t channel, const qtmr_config_t *config)
71 {
72     assert(NULL != config);
73 
74 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
75     /* Enable the module clock */
76     CLOCK_EnableClock(s_qtmrClocks[QTMR_GetInstance(base)]);
77 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
78 
79     /* Setup the counter sources */
80     base->CHANNEL[channel].CTRL = (TMR_CTRL_PCS(config->primarySource) | TMR_CTRL_SCS(config->secondarySource));
81 
82     /* Setup the master mode operation */
83     base->CHANNEL[channel].SCTRL =
84         (TMR_SCTRL_EEOF(config->enableExternalForce) | TMR_SCTRL_MSTR(config->enableMasterMode));
85 
86     /* Setup debug mode */
87     base->CHANNEL[channel].CSCTRL = TMR_CSCTRL_DBG_EN(config->debugMode);
88 
89     base->CHANNEL[channel].FILT &= (uint16_t)(~(TMR_FILT_FILT_CNT_MASK | TMR_FILT_FILT_PER_MASK));
90     /* Setup input filter */
91     base->CHANNEL[channel].FILT =
92         (TMR_FILT_FILT_CNT(config->faultFilterCount) | TMR_FILT_FILT_PER(config->faultFilterPeriod));
93 }
94 
95 /*!
96  * brief Stops the counter and gates the Quad Timer clock
97  *
98  * param base     Quad Timer peripheral base address
99  * param channel  Quad Timer channel number
100  */
QTMR_Deinit(TMR_Type * base,qtmr_channel_selection_t channel)101 void QTMR_Deinit(TMR_Type *base, qtmr_channel_selection_t channel)
102 {
103     /* Stop the counter */
104     base->CHANNEL[channel].CTRL &= (uint16_t)(~TMR_CTRL_CM_MASK);
105 
106 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
107     /* Disable the module clock */
108     CLOCK_DisableClock(s_qtmrClocks[QTMR_GetInstance(base)]);
109 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
110 }
111 
112 /*!
113  * brief  Fill in the Quad Timer config struct with the default settings
114  *
115  * The default values are:
116  * code
117  *    config->debugMode = kQTMR_RunNormalInDebug;
118  *    config->enableExternalForce = false;
119  *    config->enableMasterMode = false;
120  *    config->faultFilterCount = 0;
121  *    config->faultFilterPeriod = 0;
122  *    config->primarySource = kQTMR_ClockDivide_2;
123  *    config->secondarySource = kQTMR_Counter0InputPin;
124  * endcode
125  * param config Pointer to user's Quad Timer config structure.
126  */
QTMR_GetDefaultConfig(qtmr_config_t * config)127 void QTMR_GetDefaultConfig(qtmr_config_t *config)
128 {
129     assert(NULL != config);
130 
131     /* Initializes the configure structure to zero. */
132     (void)memset(config, 0, sizeof(*config));
133 
134     /* Halt counter during debug mode */
135     config->debugMode = kQTMR_RunNormalInDebug;
136     /* Another counter cannot force state of OFLAG signal */
137     config->enableExternalForce = false;
138     /* Compare function's output from this counter is not broadcast to other counters */
139     config->enableMasterMode = false;
140     /* Fault filter count is set to 0 */
141     config->faultFilterCount = 0;
142     /* Fault filter period is set to 0 which disables the fault filter */
143     config->faultFilterPeriod = 0;
144     /* Primary count source is IP bus clock divide by 2 */
145     config->primarySource = kQTMR_ClockDivide_2;
146     /* Secondary count source is counter 0 input pin */
147     config->secondarySource = kQTMR_Counter0InputPin;
148 }
149 
150 /*!
151  * brief Sets up Quad timer module for PWM signal output.
152  *
153  * The function initializes the timer module according to the parameters passed in by the user. The
154  * function also sets up the value compare registers to match the PWM signal requirements.
155  *
156  * param base             Quad Timer peripheral base address
157  * param channel          Quad Timer channel number
158  * param pwmFreqHz        PWM signal frequency in Hz
159  * param dutyCyclePercent PWM pulse width, value should be between 0 to 100
160  *                         0=inactive signal(0% duty cycle)...
161  *                         100=active signal (100% duty cycle)
162  * param outputPolarity   true: invert polarity of the output signal, false: no inversion
163  * param srcClock_Hz      Main counter clock in Hz.
164  *
165  * return Returns an error if there was error setting up the signal.
166  */
QTMR_SetupPwm(TMR_Type * base,qtmr_channel_selection_t channel,uint32_t pwmFreqHz,uint8_t dutyCyclePercent,bool outputPolarity,uint32_t srcClock_Hz)167 status_t QTMR_SetupPwm(TMR_Type *base,
168                        qtmr_channel_selection_t channel,
169                        uint32_t pwmFreqHz,
170                        uint8_t dutyCyclePercent,
171                        bool outputPolarity,
172                        uint32_t srcClock_Hz)
173 {
174     uint32_t periodCount, highCount, lowCount;
175     uint16_t reg;
176     status_t status;
177 
178     if (dutyCyclePercent <= 100U)
179     {
180         /* Set OFLAG pin for output mode and force out a low on the pin */
181         base->CHANNEL[channel].SCTRL |= (TMR_SCTRL_FORCE_MASK | TMR_SCTRL_OEN_MASK);
182 
183         /* Counter values to generate a PWM signal */
184         periodCount = srcClock_Hz / pwmFreqHz;
185         highCount   = periodCount * dutyCyclePercent / 100U;
186         lowCount    = periodCount - highCount;
187 
188         if (highCount > 0U)
189         {
190             highCount -= 1U;
191         }
192         if (lowCount > 0U)
193         {
194             lowCount -= 1U;
195         }
196 
197         if ((highCount > 0xFFFFU) || (lowCount > 0xFFFFU))
198         {
199             /* This should not be a 16-bit overflow value. If it is, change to a larger divider for clock source. */
200             return kStatus_Fail;
201         }
202 
203         /* Setup the compare registers for PWM output */
204         base->CHANNEL[channel].COMP1 = (uint16_t)lowCount;
205         base->CHANNEL[channel].COMP2 = (uint16_t)highCount;
206 
207         /* Setup the pre-load registers for PWM output */
208         base->CHANNEL[channel].CMPLD1 = (uint16_t)lowCount;
209         base->CHANNEL[channel].CMPLD2 = (uint16_t)highCount;
210 
211         reg = base->CHANNEL[channel].CSCTRL;
212         /* Setup the compare load control for COMP1 and COMP2.
213          * Load COMP1 when CSCTRL[TCF2] is asserted, load COMP2 when CSCTRL[TCF1] is asserted
214          */
215         reg &= (uint16_t)(~(TMR_CSCTRL_CL1_MASK | TMR_CSCTRL_CL2_MASK));
216         reg |= (TMR_CSCTRL_CL1(kQTMR_LoadOnComp2) | TMR_CSCTRL_CL2(kQTMR_LoadOnComp1));
217         base->CHANNEL[channel].CSCTRL = reg;
218 
219         if (outputPolarity)
220         {
221             /* Invert the polarity */
222             base->CHANNEL[channel].SCTRL |= TMR_SCTRL_OPS_MASK;
223         }
224         else
225         {
226             /* True polarity, no inversion */
227             base->CHANNEL[channel].SCTRL &= ~(uint16_t)TMR_SCTRL_OPS_MASK;
228         }
229 
230         reg = base->CHANNEL[channel].CTRL;
231         reg &= ~(uint16_t)TMR_CTRL_OUTMODE_MASK;
232         if (dutyCyclePercent == 100U)
233         {
234             /* Set OFLAG output on compare */
235             reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_SetOnCompare));
236         }
237         else if (dutyCyclePercent == 0U)
238         {
239             /* Clear OFLAG output on compare */
240             reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ClearOnCompare));
241         }
242         else
243         {
244             /* Toggle OFLAG output using alternating compare register */
245             reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg));
246         }
247 
248         base->CHANNEL[channel].CTRL = reg;
249 
250         /* Get pwm duty cycle */
251         s_qtmrGetPwmDutyCycle[channel] = dutyCyclePercent;
252 
253         status = kStatus_Success;
254     }
255     else
256     {
257         /* Invalid dutycycle */
258         status = kStatus_Fail;
259     }
260 
261     return status;
262 }
263 
264 /*!
265  * brief Allows the user to count the source clock cycles until a capture event arrives.
266  *
267  * The count is stored in the capture register.
268  *
269  * param base            Quad Timer peripheral base address
270  * param channel         Quad Timer channel number
271  * param capturePin      Pin through which we receive the input signal to trigger the capture
272  * param inputPolarity   true: invert polarity of the input signal, false: no inversion
273  * param reloadOnCapture true: reload the counter when an input capture occurs, false: no reload
274  * param captureMode     Specifies which edge of the input signal  triggers a capture
275  */
QTMR_SetupInputCapture(TMR_Type * base,qtmr_channel_selection_t channel,qtmr_input_source_t capturePin,bool inputPolarity,bool reloadOnCapture,qtmr_input_capture_edge_t captureMode)276 void QTMR_SetupInputCapture(TMR_Type *base,
277                             qtmr_channel_selection_t channel,
278                             qtmr_input_source_t capturePin,
279                             bool inputPolarity,
280                             bool reloadOnCapture,
281                             qtmr_input_capture_edge_t captureMode)
282 {
283     uint16_t reg;
284 
285     /* Clear the prior value for the input source for capture */
286     reg = base->CHANNEL[channel].CTRL & (uint16_t)(~TMR_CTRL_SCS_MASK);
287 
288     /* Set the new input source */
289     reg |= TMR_CTRL_SCS(capturePin);
290     base->CHANNEL[channel].CTRL = reg;
291 
292     /* Clear the prior values for input polarity, capture mode. Set the external pin as input */
293     reg = base->CHANNEL[channel].SCTRL &
294           (uint16_t)(~(TMR_SCTRL_IPS_MASK | TMR_SCTRL_CAPTURE_MODE_MASK | TMR_SCTRL_OEN_MASK));
295     /* Set the new values */
296     reg |= (TMR_SCTRL_IPS(inputPolarity) | TMR_SCTRL_CAPTURE_MODE(captureMode));
297     base->CHANNEL[channel].SCTRL = reg;
298 
299     /* Setup if counter should reload when a capture occurs */
300     if (reloadOnCapture)
301     {
302         base->CHANNEL[channel].CSCTRL |= TMR_CSCTRL_ROC_MASK;
303     }
304     else
305     {
306         base->CHANNEL[channel].CSCTRL &= (uint16_t)(~TMR_CSCTRL_ROC_MASK);
307     }
308 }
309 
310 /*!
311  * brief Enables the selected Quad Timer interrupts
312  *
313  * param base      Quad Timer peripheral base address
314  * param channel   Quad Timer channel number
315  * param mask      The interrupts to enable. This is a logical OR of members of the
316  *                  enumeration ::qtmr_interrupt_enable_t
317  */
QTMR_EnableInterrupts(TMR_Type * base,qtmr_channel_selection_t channel,uint32_t mask)318 void QTMR_EnableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
319 {
320     uint16_t reg;
321 
322     reg = base->CHANNEL[channel].SCTRL;
323     /* Compare interrupt */
324     if ((mask & (uint16_t)kQTMR_CompareInterruptEnable) != 0UL)
325     {
326         reg |= TMR_SCTRL_TCFIE_MASK;
327     }
328     /* Overflow interrupt */
329     if ((mask & (uint16_t)kQTMR_OverflowInterruptEnable) != 0UL)
330     {
331         reg |= TMR_SCTRL_TOFIE_MASK;
332     }
333     /* Input edge interrupt */
334     if ((mask & (uint16_t)kQTMR_EdgeInterruptEnable) != 0UL)
335     {
336         /* Restriction: Do not set both SCTRL[IEFIE] and DMA[IEFDE] */
337         base->CHANNEL[channel].DMA &= ~(uint16_t)TMR_DMA_IEFDE_MASK;
338         reg |= TMR_SCTRL_IEFIE_MASK;
339     }
340     base->CHANNEL[channel].SCTRL = reg;
341 
342     reg = base->CHANNEL[channel].CSCTRL;
343     /* Compare 1 interrupt */
344     if ((mask & (uint16_t)kQTMR_Compare1InterruptEnable) != 0UL)
345     {
346         reg |= TMR_CSCTRL_TCF1EN_MASK;
347     }
348     /* Compare 2 interrupt */
349     if ((mask & (uint16_t)kQTMR_Compare2InterruptEnable) != 0UL)
350     {
351         reg |= TMR_CSCTRL_TCF2EN_MASK;
352     }
353     base->CHANNEL[channel].CSCTRL = reg;
354 }
355 
356 /*!
357  * brief Disables the selected Quad Timer interrupts
358  *
359  * param base     Quad Timer peripheral base addres
360  * param channel  Quad Timer channel number
361  * param mask The interrupts to enable. This is a logical OR of members of the
362  *             enumeration ::qtmr_interrupt_enable_t
363  */
QTMR_DisableInterrupts(TMR_Type * base,qtmr_channel_selection_t channel,uint32_t mask)364 void QTMR_DisableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
365 {
366     uint16_t reg;
367 
368     reg = base->CHANNEL[channel].SCTRL;
369     /* Compare interrupt */
370     if ((mask & (uint16_t)kQTMR_CompareInterruptEnable) != 0UL)
371     {
372         reg &= (uint16_t)(~TMR_SCTRL_TCFIE_MASK);
373     }
374     /* Overflow interrupt */
375     if ((mask & (uint16_t)kQTMR_OverflowInterruptEnable) != 0UL)
376     {
377         reg &= (uint16_t)(~TMR_SCTRL_TOFIE_MASK);
378     }
379     /* Input edge interrupt */
380     if ((mask & (uint16_t)kQTMR_EdgeInterruptEnable) != 0UL)
381     {
382         reg &= (uint16_t)(~TMR_SCTRL_IEFIE_MASK);
383     }
384     base->CHANNEL[channel].SCTRL = reg;
385 
386     reg = base->CHANNEL[channel].CSCTRL;
387     /* Compare 1 interrupt */
388     if ((mask & (uint16_t)kQTMR_Compare1InterruptEnable) != 0UL)
389     {
390         reg &= ~(uint16_t)TMR_CSCTRL_TCF1EN_MASK;
391     }
392     /* Compare 2 interrupt */
393     if ((mask & (uint16_t)kQTMR_Compare2InterruptEnable) != 0UL)
394     {
395         reg &= ~(uint16_t)TMR_CSCTRL_TCF2EN_MASK;
396     }
397     base->CHANNEL[channel].CSCTRL = reg;
398 }
399 
400 /*!
401  * brief Gets the enabled Quad Timer interrupts
402  *
403  * param base    Quad Timer peripheral base address
404  * param channel Quad Timer channel number
405  *
406  * return The enabled interrupts. This is the logical OR of members of the
407  *         enumeration ::qtmr_interrupt_enable_t
408  */
QTMR_GetEnabledInterrupts(TMR_Type * base,qtmr_channel_selection_t channel)409 uint32_t QTMR_GetEnabledInterrupts(TMR_Type *base, qtmr_channel_selection_t channel)
410 {
411     uint32_t enabledInterrupts = 0;
412     uint16_t reg;
413 
414     reg = base->CHANNEL[channel].SCTRL;
415     /* Compare interrupt */
416     if ((reg & TMR_SCTRL_TCFIE_MASK) != 0U)
417     {
418         enabledInterrupts |= (uint32_t)kQTMR_CompareFlag;
419     }
420     /* Overflow interrupt */
421     if ((reg & TMR_SCTRL_TOFIE_MASK) != 0U)
422     {
423         enabledInterrupts |= (uint32_t)kQTMR_OverflowInterruptEnable;
424     }
425     /* Input edge interrupt */
426     if ((reg & TMR_SCTRL_IEFIE_MASK) != 0U)
427     {
428         enabledInterrupts |= (uint32_t)kQTMR_EdgeInterruptEnable;
429     }
430 
431     reg = base->CHANNEL[channel].CSCTRL;
432     /* Compare 1 interrupt */
433     if ((reg & TMR_CSCTRL_TCF1EN_MASK) != 0U)
434     {
435         enabledInterrupts |= (uint32_t)kQTMR_Compare1InterruptEnable;
436     }
437     /* Compare 2 interrupt */
438     if ((reg & TMR_CSCTRL_TCF2EN_MASK) != 0U)
439     {
440         enabledInterrupts |= (uint32_t)kQTMR_Compare2InterruptEnable;
441     }
442 
443     return enabledInterrupts;
444 }
445 
446 /*!
447  * brief Gets the Quad Timer status flags
448  *
449  * param base     Quad Timer peripheral base address
450  * param channel  Quad Timer channel number
451  *
452  * return The status flags. This is the logical OR of members of the
453  *         enumeration ::qtmr_status_flags_t
454  */
QTMR_GetStatus(TMR_Type * base,qtmr_channel_selection_t channel)455 uint32_t QTMR_GetStatus(TMR_Type *base, qtmr_channel_selection_t channel)
456 {
457     uint32_t statusFlags = 0;
458     uint16_t reg;
459 
460     reg = base->CHANNEL[channel].SCTRL;
461     /* Timer compare flag */
462     if ((reg & TMR_SCTRL_TCF_MASK) != 0U)
463     {
464         statusFlags |= (uint32_t)kQTMR_CompareFlag;
465     }
466     /* Timer overflow flag */
467     if ((reg & TMR_SCTRL_TOF_MASK) != 0U)
468     {
469         statusFlags |= (uint32_t)kQTMR_OverflowFlag;
470     }
471     /* Input edge flag */
472     if ((reg & TMR_SCTRL_IEF_MASK) != 0U)
473     {
474         statusFlags |= (uint32_t)kQTMR_EdgeFlag;
475     }
476 
477     reg = base->CHANNEL[channel].CSCTRL;
478     /* Compare 1 flag */
479     if ((reg & TMR_CSCTRL_TCF1_MASK) != 0U)
480     {
481         statusFlags |= (uint32_t)kQTMR_Compare1Flag;
482     }
483     /* Compare 2 flag */
484     if ((reg & TMR_CSCTRL_TCF2_MASK) != 0U)
485     {
486         statusFlags |= (uint32_t)kQTMR_Compare2Flag;
487     }
488 
489     return statusFlags;
490 }
491 
492 /*!
493  * brief Clears the Quad Timer status flags.
494  *
495  * param base     Quad Timer peripheral base address
496  * param channel  Quad Timer channel number
497  * param mask The status flags to clear. This is a logical OR of members of the
498  *             enumeration ::qtmr_status_flags_t
499  */
QTMR_ClearStatusFlags(TMR_Type * base,qtmr_channel_selection_t channel,uint32_t mask)500 void QTMR_ClearStatusFlags(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
501 {
502     uint16_t reg;
503 
504     reg = base->CHANNEL[channel].SCTRL;
505     /* Timer compare flag */
506     if ((mask & (uint32_t)kQTMR_CompareFlag) != 0U)
507     {
508         reg &= (uint16_t)(~TMR_SCTRL_TCF_MASK);
509     }
510     /* Timer overflow flag */
511     if ((mask & (uint32_t)kQTMR_OverflowFlag) != 0U)
512     {
513         reg &= (uint16_t)(~TMR_SCTRL_TOF_MASK);
514     }
515     /* Input edge flag */
516     if ((mask & (uint32_t)kQTMR_EdgeFlag) != 0U)
517     {
518         reg &= (uint16_t)(~TMR_SCTRL_IEF_MASK);
519     }
520     base->CHANNEL[channel].SCTRL = reg;
521 
522     reg = base->CHANNEL[channel].CSCTRL;
523     /* Compare 1 flag */
524     if ((mask & (uint32_t)kQTMR_Compare1Flag) != 0U)
525     {
526         reg &= ~(uint16_t)TMR_CSCTRL_TCF1_MASK;
527     }
528     /* Compare 2 flag */
529     if ((mask & (uint32_t)kQTMR_Compare2Flag) != 0U)
530     {
531         reg &= ~(uint16_t)TMR_CSCTRL_TCF2_MASK;
532     }
533     base->CHANNEL[channel].CSCTRL = reg;
534 }
535 
536 /*!
537  * brief Sets the timer period in ticks.
538  *
539  * Timers counts from initial value till it equals the count value set here. The counter
540  * will then reinitialize to the value specified in the Load register.
541  *
542  * note
543  * 1. This function will write the time period in ticks to COMP1 or COMP2 register
544  *    depending on the count direction
545  * 2. User can call the utility macros provided in fsl_common.h to convert to ticks
546  * 3. This function supports cases, providing only primary source clock without secondary source clock.
547  * 4. The load register is reset before the counter is reinitialized to the value
548       specified in the load register.
549  *
550  * param base     Quad Timer peripheral base address
551  * param channel  Quad Timer channel number
552  * param ticks Timer period in units of ticks
553  */
QTMR_SetTimerPeriod(TMR_Type * base,qtmr_channel_selection_t channel,uint16_t ticks)554 void QTMR_SetTimerPeriod(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t ticks)
555 {
556     /* Set the length bit to reinitialize the counters on a match */
557     base->CHANNEL[channel].CTRL |= TMR_CTRL_LENGTH_MASK;
558 
559     /* Reset LOAD register to reinitialize the counters */
560     base->CHANNEL[channel].LOAD &= (uint16_t)(~TMR_LOAD_LOAD_MASK);
561 
562     if ((base->CHANNEL[channel].CTRL & TMR_CTRL_DIR_MASK) != 0U)
563     {
564         /* Counting down */
565         base->CHANNEL[channel].COMP2 = ticks - 1U;
566     }
567     else
568     {
569         /* Counting up */
570         base->CHANNEL[channel].COMP1 = ticks - 1U;
571     }
572 }
573 
574 /*!
575  * brief Set compare value.
576  *
577  * This function sets the value used for comparison with the counter value.
578  *
579  * param base     Quad Timer peripheral base address
580  * param channel  Quad Timer channel number
581  * param ticks    Timer period in units of ticks.
582  */
QTMR_SetCompareValue(TMR_Type * base,qtmr_channel_selection_t channel,uint16_t ticks)583 void QTMR_SetCompareValue(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t ticks)
584 {
585     base->CHANNEL[channel].CTRL |= TMR_CTRL_LENGTH_MASK;
586 
587     if ((base->CHANNEL[channel].CTRL & TMR_CTRL_DIR_MASK) != 0U)
588     {
589         /* Counting down */
590         base->CHANNEL[channel].COMP2 = ticks;
591     }
592     else
593     {
594         /* Counting up */
595         base->CHANNEL[channel].COMP1 = ticks;
596     }
597 }
598 
599 /*!
600  * brief Enable the Quad Timer DMA.
601  *
602  * param base     Quad Timer peripheral base address
603  * param channel  Quad Timer channel number
604  * param mask     The DMA to enable. This is a logical OR of members of the
605  *                  enumeration ::qtmr_dma_enable_t
606  */
QTMR_EnableDma(TMR_Type * base,qtmr_channel_selection_t channel,uint32_t mask)607 void QTMR_EnableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
608 {
609     uint16_t reg;
610 
611     reg = base->CHANNEL[channel].DMA;
612     /* Input Edge Flag DMA Enable */
613     if ((mask & (uint32_t)kQTMR_InputEdgeFlagDmaEnable) != 0U)
614     {
615         /* Restriction: Do not set both DMA[IEFDE] and SCTRL[IEFIE] */
616         base->CHANNEL[channel].SCTRL &= (uint16_t)(~TMR_SCTRL_IEFIE_MASK);
617         reg |= TMR_DMA_IEFDE_MASK;
618     }
619     /* Comparator Preload Register 1 DMA Enable */
620     if ((mask & (uint32_t)kQTMR_ComparatorPreload1DmaEnable) != 0U)
621     {
622         reg |= TMR_DMA_CMPLD1DE_MASK;
623     }
624     /* Comparator Preload Register 2 DMA Enable */
625     if ((mask & (uint32_t)kQTMR_ComparatorPreload2DmaEnable) != 0U)
626     {
627         reg |= TMR_DMA_CMPLD2DE_MASK;
628     }
629     base->CHANNEL[channel].DMA = reg;
630 }
631 
632 /*!
633  * brief Disable the Quad Timer DMA.
634  *
635  * param base     Quad Timer peripheral base address
636  * param channel  Quad Timer channel number
637  * param mask     The DMA to enable. This is a logical OR of members of the
638  *                  enumeration ::qtmr_dma_enable_t
639  */
QTMR_DisableDma(TMR_Type * base,qtmr_channel_selection_t channel,uint32_t mask)640 void QTMR_DisableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
641 {
642     uint16_t reg;
643 
644     reg = base->CHANNEL[channel].DMA;
645     /* Input Edge Flag DMA Enable */
646     if ((mask & (uint32_t)kQTMR_InputEdgeFlagDmaEnable) != 0U)
647     {
648         reg &= ~(uint16_t)TMR_DMA_IEFDE_MASK;
649     }
650     /* Comparator Preload Register 1 DMA Enable */
651     if ((mask & (uint32_t)kQTMR_ComparatorPreload1DmaEnable) != 0U)
652     {
653         reg &= ~(uint16_t)TMR_DMA_CMPLD1DE_MASK;
654     }
655     /* Comparator Preload Register 2 DMA Enable */
656     if ((mask & (uint32_t)kQTMR_ComparatorPreload2DmaEnable) != 0U)
657     {
658         reg &= ~(uint16_t)TMR_DMA_CMPLD2DE_MASK;
659     }
660     base->CHANNEL[channel].DMA = reg;
661 }
662 
663 /*!
664  * brief Set PWM output in idle status (high or low).
665  *
666  * Note: When the PWM is set again, the counting needs to be restarted.
667  *
668  * param base     Quad Timer peripheral base address
669  * param channel  Quad Timer channel number
670  * param idleStatus   True: PWM output is high in idle status; false: PWM output is low in idle status.
671  */
QTMR_SetPwmOutputToIdle(TMR_Type * base,qtmr_channel_selection_t channel,bool idleStatus)672 void QTMR_SetPwmOutputToIdle(TMR_Type *base, qtmr_channel_selection_t channel, bool idleStatus)
673 {
674     uint16_t reg = base->CHANNEL[channel].SCTRL;
675 
676     /* Stop qtimer channel counter first */
677     base->CHANNEL[channel].CTRL &= (uint16_t)(~TMR_CTRL_CM_MASK);
678     /* Clear count value */
679     base->CHANNEL[channel].CNTR = 0U;
680 
681     if (0U != (reg & ((uint16_t)TMR_SCTRL_OPS_MASK)))
682     {
683         /* Inverted polarity. */
684         reg |= (uint16_t)(TMR_SCTRL_FORCE_MASK | TMR_SCTRL_VAL(!idleStatus));
685     }
686     else
687     {
688         /* True polarity. */
689         reg |= (uint16_t)(TMR_SCTRL_FORCE_MASK | TMR_SCTRL_VAL(idleStatus));
690     }
691     base->CHANNEL[channel].SCTRL = reg;
692 
693     s_qtmrGetPwmDutyCycle[channel] = 0x0;
694 }
695 
696 /*!
697  * brief Get the PWM channel dutycycle value.
698  *
699  * param base     Quad Timer peripheral base address
700  * param channel  Quad Timer channel number
701  *
702  * return Current channel dutycycle value.
703  */
QTMR_GetPwmChannelStatus(TMR_Type * base,qtmr_channel_selection_t channel)704 uint8_t QTMR_GetPwmChannelStatus(TMR_Type *base, qtmr_channel_selection_t channel)
705 {
706     return s_qtmrGetPwmDutyCycle[channel];
707 }
708 
709 /*!
710  * brief This function set the value of the prescaler on QTimer channels.
711  *
712  * param base         Quad Timer peripheral base address
713  * param channel      Quad Timer channel number
714  * param prescaler    Set prescaler value
715  */
QTMR_SetPwmClockMode(TMR_Type * base,qtmr_channel_selection_t channel,qtmr_primary_count_source_t prescaler)716 void QTMR_SetPwmClockMode(TMR_Type *base, qtmr_channel_selection_t channel, qtmr_primary_count_source_t prescaler)
717 {
718     assert((uint32_t)prescaler > 7U);
719 
720     uint16_t reg = base->CHANNEL[channel].CTRL;
721 
722     /* Clear qtimer channel counter mode */
723     base->CHANNEL[channel].CTRL = reg & (uint16_t)(~TMR_CTRL_CM_MASK);
724 
725     /* Set the new clock prescaler value and restore qtimer channel counter mode*/
726     reg &= (uint16_t)(~(TMR_CTRL_PCS_MASK));
727     reg |= TMR_CTRL_PCS(prescaler);
728     base->CHANNEL[channel].CTRL = reg;
729 }
730