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