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