1 /**************************************************************************//**
2 * @file timer_pwm.c
3 * @brief M480 Timer PWM Controller(Timer PWM) driver source file
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
7 *****************************************************************************/
8 #include "NuMicro.h"
9
10
11 /** @addtogroup Standard_Driver Standard Driver
12 @{
13 */
14
15 /** @addtogroup TIMER_PWM_Driver TIMER PWM Driver
16 @{
17 */
18
19 /** @addtogroup TIMER_PWM_EXPORTED_FUNCTIONS TIMER PWM Exported Functions
20 @{
21 */
22
23 /**
24 * @brief Set PWM Counter Clock Source
25 *
26 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
27 * @param[in] u32CntClkSrc PWM counter clock source, could be one of following source
28 * - \ref TPWM_CNTR_CLKSRC_TMR_CLK
29 * - \ref TPWM_CNTR_CLKSRC_TIMER0_INT
30 * - \ref TPWM_CNTR_CLKSRC_TIMER1_INT
31 * - \ref TPWM_CNTR_CLKSRC_TIMER2_INT
32 * - \ref TPWM_CNTR_CLKSRC_TIMER3_INT
33 *
34 * @return None
35 *
36 * @details This function is used to set PWM counter clock source.
37 */
TPWM_SetCounterClockSource(TIMER_T * timer,uint32_t u32CntClkSrc)38 void TPWM_SetCounterClockSource(TIMER_T *timer, uint32_t u32CntClkSrc)
39 {
40 (timer)->PWMCLKSRC = ((timer)->PWMCLKSRC & ~TIMER_PWMCLKSRC_CLKSRC_Msk) | u32CntClkSrc;
41 }
42
43 /**
44 * @brief Configure PWM Output Frequency and Duty Cycle
45 *
46 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
47 * @param[in] u32Frequency Target generator frequency.
48 * @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0~100. 10 means 10%, 20 means 20%...
49 *
50 * @return Nearest frequency clock in nano second
51 *
52 * @details This API is used to configure PWM output frequency and duty cycle in up count type and auto-reload operation mode.
53 * @note This API is only available if Timer PWM counter clock source is from TMRx_CLK.
54 */
TPWM_ConfigOutputFreqAndDuty(TIMER_T * timer,uint32_t u32Frequency,uint32_t u32DutyCycle)55 uint32_t TPWM_ConfigOutputFreqAndDuty(TIMER_T *timer, uint32_t u32Frequency, uint32_t u32DutyCycle)
56 {
57 uint32_t u32PWMClockFreq, u32TargetFreq;
58 uint32_t u32Prescaler = 0x1000UL, u32Period, u32CMP;
59
60 if((timer == TIMER0) || (timer == TIMER1))
61 {
62 u32PWMClockFreq = CLK_GetPCLK0Freq();
63 }
64 else
65 {
66 u32PWMClockFreq = CLK_GetPCLK1Freq();
67 }
68
69 /* Calculate u16PERIOD and u16PSC */
70 for(u32Prescaler = 1UL; u32Prescaler <= 0x1000UL; u32Prescaler++)
71 {
72 u32Period = (u32PWMClockFreq / u32Prescaler) / u32Frequency;
73
74 /* If target u32Period is larger than 0x10000, need to use a larger prescaler */
75 if(u32Period <= 0x10000UL)
76 {
77 break;
78 }
79 }
80 /* Store return value here 'cos we're gonna change u32Prescaler & u32Period to the real value to fill into register */
81 u32TargetFreq = (u32PWMClockFreq / u32Prescaler) / u32Period;
82
83 /* Set PWM to up count type */
84 timer->PWMCTL = (timer->PWMCTL & ~TIMER_PWMCTL_CNTTYPE_Msk) | (TPWM_UP_COUNT << TIMER_PWMCTL_CNTTYPE_Pos);
85
86 /* Set PWM to auto-reload mode */
87 timer->PWMCTL = (timer->PWMCTL & ~TIMER_PWMCTL_CNTMODE_Msk) | TPWM_AUTO_RELOAD_MODE;
88
89 /* Convert to real register value */
90 TPWM_SET_PRESCALER(timer, (u32Prescaler - 1UL));
91
92 TPWM_SET_PERIOD(timer, (u32Period - 1UL));
93 if(u32DutyCycle)
94 {
95 u32CMP = (u32DutyCycle * u32Period) / 100UL;
96 }
97 else
98 {
99 u32CMP = 0UL;
100 }
101
102 TPWM_SET_CMPDAT(timer, u32CMP);
103
104 return (u32TargetFreq);
105 }
106
107 /**
108 * @brief Enable Dead-Time Function
109 *
110 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
111 * @param[in] u32DTCount Dead-Time duration in PWM clock count, valid values are between 0x0~0xFFF, but 0x0 means there is no Dead-Time insertion.
112 *
113 * @return None
114 *
115 * @details This function is used to enable Dead-Time function and counter source is the same as Timer PWM clock source.
116 * @note The register write-protection function should be disabled before using this function.
117 */
TPWM_EnableDeadTime(TIMER_T * timer,uint32_t u32DTCount)118 void TPWM_EnableDeadTime(TIMER_T *timer, uint32_t u32DTCount)
119 {
120 timer->PWMDTCTL = TIMER_PWMDTCTL_DTEN_Msk | u32DTCount;
121 }
122
123 /**
124 * @brief Enable Dead-Time Function
125 *
126 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
127 * @param[in] u32DTCount Dead-Time duration in PWM clock count, valid values are between 0x0~0xFFF, but 0x0 means there is no Dead-Time insertion.
128 *
129 * @return None
130 *
131 * @details This function is used to enable Dead-Time function and counter source is the Timer PWM clock source with prescale.
132 * @note The register write-protection function should be disabled before using this function.
133 */
TPWM_EnableDeadTimeWithPrescale(TIMER_T * timer,uint32_t u32DTCount)134 void TPWM_EnableDeadTimeWithPrescale(TIMER_T *timer, uint32_t u32DTCount)
135 {
136 timer->PWMDTCTL = TIMER_PWMDTCTL_DTCKSEL_Msk | TIMER_PWMDTCTL_DTEN_Msk | u32DTCount;
137 }
138
139 /**
140 * @brief Disable Dead-Time Function
141 *
142 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
143 *
144 * @return None
145 *
146 * @details This function is used to enable Dead-time of selected channel.
147 * @note The register write-protection function should be disabled before using this function.
148 */
TPWM_DisableDeadTime(TIMER_T * timer)149 void TPWM_DisableDeadTime(TIMER_T *timer)
150 {
151 timer->PWMDTCTL = 0x0UL;
152 }
153
154 /**
155 * @brief Enable PWM Counter
156 *
157 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
158 *
159 * @return None
160 *
161 * @details This function is used to enable PWM generator and start counter counting.
162 */
TPWM_EnableCounter(TIMER_T * timer)163 void TPWM_EnableCounter(TIMER_T *timer)
164 {
165 timer->PWMCTL |= TIMER_PWMCTL_CNTEN_Msk;
166 }
167
168 /**
169 * @brief Disable PWM Generator
170 *
171 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
172 *
173 * @return None
174 *
175 * @details This function is used to disable PWM counter immediately by clear CNTEN (TIMERx_PWMCTL[0]) bit.
176 */
TPWM_DisableCounter(TIMER_T * timer)177 void TPWM_DisableCounter(TIMER_T *timer)
178 {
179 timer->PWMCTL &= ~TIMER_PWMCTL_CNTEN_Msk;
180 }
181
182 /**
183 * @brief Enable Trigger ADC
184 *
185 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
186 * @param[in] u32Condition The condition to trigger ADC. It could be one of following conditions:
187 * - \ref TPWM_TRIGGER_ADC_AT_ZERO_POINT
188 * - \ref TPWM_TRIGGER_ADC_AT_PERIOD_POINT
189 * - \ref TPWM_TRIGGER_ADC_AT_ZERO_OR_PERIOD_POINT
190 * - \ref TPWM_TRIGGER_ADC_AT_COMPARE_UP_COUNT_POINT
191 * - \ref TPWM_TRIGGER_ADC_AT_COMPARE_DOWN_COUNT_POINT
192 *
193 * @return None
194 *
195 * @details This function is used to enable specified counter compare event to trigger ADC.
196 */
TPWM_EnableTriggerADC(TIMER_T * timer,uint32_t u32Condition)197 void TPWM_EnableTriggerADC(TIMER_T *timer, uint32_t u32Condition)
198 {
199 timer->PWMEADCTS = TIMER_PWMEADCTS_TRGEN_Msk | u32Condition;
200 }
201
202 /**
203 * @brief Disable Trigger ADC
204 *
205 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
206 *
207 * @return None
208 *
209 * @details This function is used to disable counter compare event to trigger ADC.
210 */
TPWM_DisableTriggerADC(TIMER_T * timer)211 void TPWM_DisableTriggerADC(TIMER_T *timer)
212 {
213 timer->PWMEADCTS = 0x0UL;
214 }
215
216 /**
217 * @brief Enable Fault Brake Function
218 *
219 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
220 * @param[in] u32CH0Level PWMx_CH0 output level while fault brake event occurs. Valid value is one of following setting
221 * - \ref TPWM_OUTPUT_TOGGLE
222 * - \ref TPWM_OUTPUT_NOTHING
223 * - \ref TPWM_OUTPUT_LOW
224 * - \ref TPWM_OUTPUT_HIGH
225 * @param[in] u32CH1Level PWMx_CH1 output level while fault brake event occurs. Valid value is one of following setting
226 * - \ref TPWM_OUTPUT_TOGGLE
227 * - \ref TPWM_OUTPUT_NOTHING
228 * - \ref TPWM_OUTPUT_LOW
229 * - \ref TPWM_OUTPUT_HIGH
230 * @param[in] u32BrakeSource Fault brake source, combination of following source
231 * - \ref TPWM_BRAKE_SOURCE_EDGE_ACMP0
232 * - \ref TPWM_BRAKE_SOURCE_EDGE_ACMP1
233 * - \ref TPWM_BRAKE_SOURCE_EDGE_BKPIN
234 * - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_CSS
235 * - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_BOD
236 * - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_COR
237 * - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_RAM
238 * - \ref TPWM_BRAKE_SOURCE_LEVEL_ACMP0
239 * - \ref TPWM_BRAKE_SOURCE_LEVEL_ACMP1
240 * - \ref TPWM_BRAKE_SOURCE_LEVEL_BKPIN
241 * - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_CSS
242 * - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_BOD
243 * - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_COR
244 * - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_RAM
245 *
246 * @return None
247 *
248 * @details This function is used to enable fault brake function.
249 * @note The register write-protection function should be disabled before using this function.
250 */
TPWM_EnableFaultBrake(TIMER_T * timer,uint32_t u32CH0Level,uint32_t u32CH1Level,uint32_t u32BrakeSource)251 void TPWM_EnableFaultBrake(TIMER_T *timer, uint32_t u32CH0Level, uint32_t u32CH1Level, uint32_t u32BrakeSource)
252 {
253 timer->PWMFAILBRK |= ((u32BrakeSource >> 16) & 0xFUL);
254 timer->PWMBRKCTL = (timer->PWMBRKCTL & ~(TIMER_PWMBRKCTL_BRKAEVEN_Msk | TIMER_PWMBRKCTL_BRKAODD_Msk)) |
255 (u32BrakeSource & 0xFFFFUL) | (u32CH0Level << TIMER_PWMBRKCTL_BRKAEVEN_Pos) | (u32CH1Level << TIMER_PWMBRKCTL_BRKAODD_Pos);
256 }
257
258 /**
259 * @brief Enable Fault Brake Interrupt
260 *
261 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
262 * @param[in] u32IntSource Interrupt source, could be one of following source
263 * - \ref TPWM_BRAKE_EDGE
264 * - \ref TPWM_BRAKE_LEVEL
265 *
266 * @return None
267 *
268 * @details This function is used to enable fault brake interrupt.
269 * @note The register write-protection function should be disabled before using this function.
270 */
TPWM_EnableFaultBrakeInt(TIMER_T * timer,uint32_t u32IntSource)271 void TPWM_EnableFaultBrakeInt(TIMER_T *timer, uint32_t u32IntSource)
272 {
273 timer->PWMINTEN1 |= u32IntSource;
274 }
275
276 /**
277 * @brief Disable Fault Brake Interrupt
278 *
279 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
280 * @param[in] u32IntSource Interrupt source, could be one of following source
281 * - \ref TPWM_BRAKE_EDGE
282 * - \ref TPWM_BRAKE_LEVEL
283 *
284 * @return None
285 *
286 * @details This function is used to disable fault brake interrupt.
287 * @note The register write-protection function should be disabled before using this function.
288 */
TPWM_DisableFaultBrakeInt(TIMER_T * timer,uint32_t u32IntSource)289 void TPWM_DisableFaultBrakeInt(TIMER_T *timer, uint32_t u32IntSource)
290 {
291 timer->PWMINTEN1 &= ~u32IntSource;
292 }
293
294 /**
295 * @brief Indicate Fault Brake Interrupt Flag
296 *
297 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
298 * @param[in] u32IntSource Interrupt source, could be one of following source
299 * - \ref TPWM_BRAKE_EDGE
300 * - \ref TPWM_BRAKE_LEVEL
301 *
302 * @return Fault brake interrupt flag of specified source
303 * @retval 0 Fault brake interrupt did not occurred
304 * @retval 1 Fault brake interrupt occurred
305 *
306 * @details This function is used to indicate fault brake interrupt flag occurred or not of selected source.
307 */
TPWM_GetFaultBrakeIntFlag(TIMER_T * timer,uint32_t u32IntSource)308 uint32_t TPWM_GetFaultBrakeIntFlag(TIMER_T *timer, uint32_t u32IntSource)
309 {
310 return ((timer->PWMINTSTS1 & (0x3UL << u32IntSource))? 1UL : 0UL);
311 }
312
313 /**
314 * @brief Clear Fault Brake Interrupt Flags
315 *
316 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
317 * @param[in] u32IntSource Interrupt source, could be one of following source
318 * - \ref TPWM_BRAKE_EDGE
319 * - \ref TPWM_BRAKE_LEVEL
320 *
321 * @return None
322 *
323 * @details This function is used to clear fault brake interrupt flags of selected source.
324 * @note The register write-protection function should be disabled before using this function.
325 */
TPWM_ClearFaultBrakeIntFlag(TIMER_T * timer,uint32_t u32IntSource)326 void TPWM_ClearFaultBrakeIntFlag(TIMER_T *timer, uint32_t u32IntSource)
327 {
328 timer->PWMINTSTS1 = (0x3UL << u32IntSource);
329 }
330
331 /**
332 * @brief Enable load mode of selected channel
333 *
334 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
335 * @param[in] u32LoadMode Timer PWM counter loading mode, could be one of following mode
336 * - \ref TPWM_LOAD_MODE_PERIOD
337 * - \ref TPWM_LOAD_MODE_IMMEDIATE
338 * - \ref TPWM_LOAD_MODE_CENTER
339 *
340 * @return None
341 *
342 * @details This function is used to enable load mode of selected channel.
343 * @note The default loading mode is period loading mode.
344 */
TPWM_SetLoadMode(TIMER_T * timer,uint32_t u32LoadMode)345 void TPWM_SetLoadMode(TIMER_T *timer, uint32_t u32LoadMode)
346 {
347 timer->PWMCTL = (timer->PWMCTL & ~(TIMER_PWMCTL_IMMLDEN_Msk | TIMER_PWMCTL_CTRLD_Msk)) | u32LoadMode;
348 }
349
350 /**
351 * @brief Enable brake pin noise filter function
352 *
353 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
354 * @param[in] u32BrakePinSrc The external brake pin source, could be one of following source
355 * - \ref TPWM_TM_BRAKE0
356 * - \ref TPWM_TM_BRAKE1
357 * - \ref TPWM_TM_BRAKE2
358 * - \ref TPWM_TM_BRAKE3
359 * @param[in] u32DebounceCnt This value controls the real debounce sample time.
360 * The target debounce sample time is (debounce sample clock period) * (u32DebounceCnt).
361 * @param[in] u32ClkSrcSel Brake pin detector debounce clock source, could be one of following source
362 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_1
363 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_2
364 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_4
365 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_8
366 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_16
367 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_32
368 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_64
369 * - \ref TPWM_BKP_DBCLK_PCLK_DIV_128
370 *
371 * @return None
372 *
373 * @details This function is used to enable external brake pin detector noise filter function.
374 */
TPWM_EnableBrakePinDebounce(TIMER_T * timer,uint32_t u32BrakePinSrc,uint32_t u32DebounceCnt,uint32_t u32ClkSrcSel)375 void TPWM_EnableBrakePinDebounce(TIMER_T *timer, uint32_t u32BrakePinSrc, uint32_t u32DebounceCnt, uint32_t u32ClkSrcSel)
376 {
377 timer->PWMBNF = (timer->PWMBNF & ~(TIMER_PWMBNF_BKPINSRC_Msk | TIMER_PWMBNF_BRKFCNT_Msk | TIMER_PWMBNF_BRKNFSEL_Msk)) |
378 (u32BrakePinSrc << TIMER_PWMBNF_BKPINSRC_Pos) |
379 (u32DebounceCnt << TIMER_PWMBNF_BRKFCNT_Pos) |
380 (u32ClkSrcSel << TIMER_PWMBNF_BRKNFSEL_Pos) | TIMER_PWMBNF_BRKNFEN_Msk;
381 }
382
383 /**
384 * @brief Disable brake pin noise filter function
385 *
386 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
387 *
388 * @return None
389 *
390 * @details This function is used to disable external brake pin detector noise filter function.
391 */
TPWM_DisableBrakePinDebounce(TIMER_T * timer)392 void TPWM_DisableBrakePinDebounce(TIMER_T *timer)
393 {
394 timer->PWMBNF &= ~TIMER_PWMBNF_BRKNFEN_Msk;
395 }
396
397
398 /**
399 * @brief Enable brake pin inverse function
400 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
401 * @return None
402 * @details This function is used to enable PWM brake pin inverse function.
403 */
TPWM_EnableBrakePinInverse(TIMER_T * timer)404 void TPWM_EnableBrakePinInverse(TIMER_T *timer)
405 {
406 timer->PWMBNF |= TIMER_PWMBNF_BRKPINV_Msk;
407 }
408
409 /**
410 * @brief Disable brake pin inverse function
411 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
412 * @return None
413 * @details This function is used to disable PWM brake pin inverse function.
414 */
TPWM_DisableBrakePinInverse(TIMER_T * timer)415 void TPWM_DisableBrakePinInverse(TIMER_T *timer)
416 {
417 timer->PWMBNF &= ~TIMER_PWMBNF_BRKPINV_Msk;
418 }
419
420 /**
421 * @brief Set brake pin source
422 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
423 * @param[in] u32BrakePinNum Brake pin selection. One of the following:
424 * - \ref TPWM_TM_BRAKE0
425 * - \ref TPWM_TM_BRAKE1
426 * - \ref TPWM_TM_BRAKE2
427 * - \ref TPWM_TM_BRAKE3
428 * @return None
429 * @details This function is used to set PWM brake pin source.
430 */
TPWM_SetBrakePinSource(TIMER_T * timer,uint32_t u32BrakePinNum)431 void TPWM_SetBrakePinSource(TIMER_T *timer, uint32_t u32BrakePinNum)
432 {
433 timer->PWMBNF = (((timer)->PWMBNF & ~TIMER_PWMBNF_BKPINSRC_Msk) | (u32BrakePinNum << TIMER_PWMBNF_BKPINSRC_Pos));
434 }
435
436
437 /*@}*/ /* end of group TIMER_PWM_EXPORTED_FUNCTIONS */
438
439 /*@}*/ /* end of group TIMER_PWM_Driver */
440
441 /*@}*/ /* end of group Standard_Driver */
442
443 /*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/
444