1 /**************************************************************************//**
2 * @file timer_pwm.c
3 * @version V3.01
4 * @brief Timer PWM Controller(Timer PWM) driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10
11
12 /** @addtogroup Standard_Driver Standard Driver
13 @{
14 */
15
16 /** @addtogroup TIMER_PWM_Driver TIMER PWM Driver
17 @{
18 */
19
20 /** @addtogroup TIMER_PWM_EXPORTED_FUNCTIONS TIMER PWM Exported Functions
21 @{
22 */
23
24 /**
25 * @brief Configure TPWM Output Frequency and Duty Cycle
26 *
27 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
28 * @param[in] u32Frequency Target generator frequency.
29 * @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0~100. 10 means 10%, 20 means 20%...
30 *
31 * @return Nearest frequency clock in nano second
32 *
33 * @details This API is used to configure TPWM output frequency and duty cycle in up count type and auto-reload operation mode.
34 * @note This API is only available if Timer PWM counter clock source is from TMRx_CLK.
35 */
TPWM_ConfigOutputFreqAndDuty(TIMER_T * timer,uint32_t u32Frequency,uint32_t u32DutyCycle)36 uint32_t TPWM_ConfigOutputFreqAndDuty(TIMER_T *timer, uint32_t u32Frequency, uint32_t u32DutyCycle)
37 {
38 uint32_t u32PWMClockFreq, u32TargetFreq;
39 uint32_t u32Prescaler = 0x100UL, u32Period, u32CMP;
40
41 if ((timer == TIMER0) || (timer == TIMER1))
42 {
43 u32PWMClockFreq = CLK_GetPCLK0Freq();
44 }
45 else
46 {
47 u32PWMClockFreq = CLK_GetPCLK1Freq();
48 }
49
50 /* Calculate u8PERIOD and u8PSC */
51 for (u32Prescaler = 1; u32Prescaler <= 0x100UL; u32Prescaler++)
52 {
53 u32Period = (u32PWMClockFreq / u32Prescaler) / u32Frequency;
54
55 /* If target u32Period is larger than 0x10000, need to use a larger prescaler */
56 if (u32Period > 0x10000UL)
57 continue;
58
59 break;
60 }
61
62 if (u32Prescaler == 0x101UL)
63 {
64 u32Prescaler = 0x100UL;
65 u32Period = 0x10000UL;
66 }
67
68 /* Store return value here 'cos we're gonna change u32Prescaler & u32Period to the real value to fill into register */
69 u32TargetFreq = (u32PWMClockFreq / u32Prescaler) / u32Period;
70
71 /* Set PWM to auto-reload mode */
72 timer->PWMCTL = (timer->PWMCTL & ~TIMER_PWMCTL_CNTMODE_Msk) | (TPWM_AUTO_RELOAD_MODE << TIMER_PWMCTL_CNTMODE_Pos);
73
74 /* Convert to real register value */
75 TPWM_SET_PRESCALER(timer, (u32Prescaler - 1UL));
76
77 TPWM_SET_PERIOD(timer, (u32Period - 1UL));
78
79 if (u32DutyCycle)
80 {
81 u32CMP = (u32DutyCycle * u32Period) / 100UL;
82 }
83 else
84 {
85 u32CMP = 0UL;
86 }
87
88 TPWM_SET_CMPDAT(timer, u32CMP);
89 return (u32TargetFreq);
90 }
91
92 /**
93 * @brief Enable TPWM Counter
94 *
95 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
96 *
97 * @return None
98 *
99 * @details This function is used to enable TPWM generator and start counter counting.
100 */
TPWM_EnableCounter(TIMER_T * timer)101 void TPWM_EnableCounter(TIMER_T *timer)
102 {
103 timer->PWMCTL |= TIMER_PWMCTL_CNTEN_Msk;
104 }
105
106 /**
107 * @brief Disable TPWM Generator
108 *
109 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
110 *
111 * @return None
112 *
113 * @details This function is used to disable TPWM counter immediately by clear CNTEN (TIMERx_PWMCTL[0]) bit.
114 */
TPWM_DisableCounter(TIMER_T * timer)115 void TPWM_DisableCounter(TIMER_T *timer)
116 {
117 timer->PWMCTL &= ~TIMER_PWMCTL_CNTEN_Msk;
118 }
119
120 /**
121 * @brief Enable TPWM Trigger ADC/DAC/PDMA/LPADC
122 *
123 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
124 * @param[in] u32TargetMask The mask of modules (EADC/DAC/PDMA/LPADC) trigger by TPWM, the combination of:
125 * - \ref TIMER_PWMTRGCTL_PWMTRGDAC_Msk
126 * - \ref TIMER_PWMTRGCTL_PWMTRGEADC_Msk
127 * - \ref TIMER_PWMTRGCTL_PWMTRGPDMA_Msk
128 * - \ref TIMER_PWMTRGCTL_PWMTRGLPADC_Msk
129 * @param[in] u32Condition The condition to trigger EADC/DAC/PDMA/LPADC. It could be one of following conditions:
130 * - \ref TPWM_TRIGGER_AT_PERIOD_POINT
131 * - \ref TPWM_TRIGGER_AT_COMPARE_POINT
132 * - \ref TPWM_TRIGGER_AT_PERIOD_OR_COMPARE_POINT
133 * @return None
134 *
135 * @details This function is used to enable specified counter event to trigger ADC/DAC/PDMA/LPADC.
136 */
TPWM_EnableTrigger(TIMER_T * timer,uint32_t u32TargetMask,uint32_t u32Condition)137 void TPWM_EnableTrigger(TIMER_T *timer, uint32_t u32TargetMask, uint32_t u32Condition)
138 {
139 timer->PWMTRGCTL &= ~(TIMER_PWMTRGCTL_PWMTRGDAC_Msk | TIMER_PWMTRGCTL_PWMTRGEADC_Msk | TIMER_PWMTRGCTL_PWMTRGPDMA_Msk | TIMER_PWMTRGCTL_PWMTRGLPADC_Msk | TIMER_PWMTRGCTL_TRGSEL_Msk);
140 timer->PWMTRGCTL |= (u32TargetMask) | (u32Condition);
141 }
142
143 /**
144 * @brief Disable Trigger ADC/DAC/PDMA/LPADC
145 *
146 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
147 * @param[in] u32TargetMask The mask of modules (EADC/DAC/PDMA/LPADC) trigger by TPWM, the combination of:
148 * - \ref TIMER_PWMTRGCTL_PWMTRGDAC_Msk
149 * - \ref TIMER_PWMTRGCTL_PWMTRGEADC_Msk
150 * - \ref TIMER_PWMTRGCTL_PWMTRGPDMA_Msk
151 * - \ref TIMER_PWMTRGCTL_PWMTRGLPADC_Msk
152 *
153 * @return None
154 *
155 * @details This function is used to disable counter event to trigger ADC/DAC/PDMA/LPADC.
156 */
TPWM_DisableTrigger(TIMER_T * timer,uint32_t u32TargetMask)157 void TPWM_DisableTrigger(TIMER_T *timer, uint32_t u32TargetMask)
158 {
159 timer->PWMTRGCTL &= ~(u32TargetMask);
160 }
161
162 /**
163 * @brief Enable Interrupt Flag Accumulator
164 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
165 * @param[in] u32IntFlagCnt Interrupt flag counter. Valid values are between 0~65535.
166 * @param[in] u32IntAccSrc Interrupt flag accumulator source selection.
167 * - \ref TPWM_IFA_PERIOD_POINT
168 * - \ref TPWM_IFA_COMPARE_UP_COUNT_POINT
169 * @return None
170 * @details This function is used to enable interrupt flag accumulator.
171 */
TPWM_EnableAcc(TIMER_T * timer,uint32_t u32IntFlagCnt,uint32_t u32IntAccSrc)172 void TPWM_EnableAcc(TIMER_T *timer, uint32_t u32IntFlagCnt, uint32_t u32IntAccSrc)
173 {
174 timer->PWMIFA = (((timer)->PWMIFA & ~(TIMER_PWMIFA_IFACNT_Msk | TIMER_PWMIFA_IFASEL_Msk | TIMER_PWMIFA_STPMOD_Msk))
175 | (TIMER_PWMIFA_IFAEN_Msk | (u32IntFlagCnt << TIMER_PWMIFA_IFACNT_Pos) | (u32IntAccSrc << TIMER_PWMIFA_IFASEL_Pos)));
176 }
177
178 /**
179 * @brief Disable Interrupt Flag Accumulator
180 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
181 * @return None
182 * @details This function is used to disable interrupt flag accumulator.
183 */
TPWM_DisableAcc(TIMER_T * timer)184 void TPWM_DisableAcc(TIMER_T *timer)
185 {
186 timer->PWMIFA &= ~TIMER_PWMIFA_IFAEN_Msk;
187 }
188
189 /**
190 * @brief Enable Interrupt Flag Accumulator Interrupt Function
191 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
192 * @return None
193 * @details This function is used to enable interrupt flag accumulator interrupt.
194 */
TPWM_EnableAccInt(TIMER_T * timer)195 void TPWM_EnableAccInt(TIMER_T *timer)
196 {
197 timer->PWMAINTEN |= TIMER_PWMAINTEN_IFAIEN_Msk;
198 }
199
200 /**
201 * @brief Disable Interrupt Flag Accumulator Interrupt Function
202 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
203 * @return None
204 * @details This function is used to disable interrupt flag accumulator interrupt.
205 */
TPWM_DisableAccInt(TIMER_T * timer)206 void TPWM_DisableAccInt(TIMER_T *timer)
207 {
208 timer->PWMAINTEN &= ~TIMER_PWMAINTEN_IFAIEN_Msk;
209 }
210
211 /**
212 * @brief Clear Interrupt Flag Accumulator Interrupt Flag
213 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
214 * @return None
215 * @details This function is used to clear interrupt flag accumulator interrupt.
216 */
TPWM_ClearAccInt(TIMER_T * timer)217 void TPWM_ClearAccInt(TIMER_T *timer)
218 {
219 timer->PWMAINTSTS = TIMER_PWMAINTSTS_IFAIF_Msk;
220 }
221
222 /**
223 * @brief Get Interrupt Flag Accumulator Interrupt Flag
224 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
225 * @retval 0 Accumulator interrupt did not occur
226 * @retval 1 Accumulator interrupt occurred
227 * @details This function is used to get interrupt flag accumulator interrupt.
228 */
TPWM_GetAccInt(TIMER_T * timer)229 uint32_t TPWM_GetAccInt(TIMER_T *timer)
230 {
231 return (((timer)->PWMAINTSTS & TIMER_PWMAINTSTS_IFAIF_Msk)? 1UL : 0UL);
232 }
233
234 /**
235 * @brief Enable Accumulator Interrupt Trigger PDMA
236 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
237 * @return None
238 * @details This function is used to enable accumulator interrupt trigger PDMA transfer.
239 */
TPWM_EnableAccPDMA(TIMER_T * timer)240 void TPWM_EnableAccPDMA(TIMER_T *timer)
241 {
242 timer->PWMAPDMACTL |= TIMER_PWMAPDMACTL_APDMAEN_Msk;
243 }
244
245 /**
246 * @brief Disable Accumulator Interrupt Trigger PDMA
247 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
248 * @return None
249 * @details This function is used to disable accumulator interrupt trigger PDMA transfer.
250 */
TPWM_DisableAccPDMA(TIMER_T * timer)251 void TPWM_DisableAccPDMA(TIMER_T *timer)
252 {
253 timer->PWMAPDMACTL &= ~TIMER_PWMAPDMACTL_APDMAEN_Msk;
254 }
255
256 /**
257 * @brief Enable Interrupt Flag Accumulator Stop Mode
258 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
259 * @return None
260 * @details This function is used to enable interrupt flag accumulator event to stop PWM counting.
261 */
TPWM_EnableAccStopMode(TIMER_T * timer)262 void TPWM_EnableAccStopMode(TIMER_T *timer)
263 {
264 timer->PWMIFA |= TIMER_PWMIFA_STPMOD_Msk;
265 }
266
267 /**
268 * @brief Disable Interrupt Flag Accumulator Stop Mode
269 * @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
270 * @return None
271 * @details This function is used to disable interrupt flag accumulator event to stop PWM counting.
272 */
TPWM_DisableAccStopMode(TIMER_T * timer)273 void TPWM_DisableAccStopMode(TIMER_T *timer)
274 {
275 timer->PWMIFA &= ~TIMER_PWMIFA_STPMOD_Msk;
276 }
277
278 /*@}*/ /* end of group TIMER_PWM_EXPORTED_FUNCTIONS */
279
280 /*@}*/ /* end of group TIMER_PWM_Driver */
281
282 /*@}*/ /* end of group Standard_Driver */
283
284 /*** (C) COPYRIGHT 2020 Nuvoton Technology Corp. ***/
285