1 /**************************************************************************//**
2 * @file lptmr_pwm.c
3 * @version V3.01
4 * @brief LPTMR PWM Controller(LPTMR 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 LPTMR_PWM_Driver LPTMR PWM Driver
17 @{
18 */
19
20 /** @addtogroup LPTMR_PWM_EXPORTED_FUNCTIONS LPTMR PWM Exported Functions
21 @{
22 */
23
24 /**
25 * @brief Configure LPTPWM Output Frequency and Duty Cycle
26 *
27 * @param[in] lptmr The pointer of the specified LPTMR module. It could be LPTMR0, LPTMR1.
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 LPTPWM output frequency and duty cycle in up count type and auto-reload operation mode.
34 * @note This API is only available if LPTMR PWM counter clock source is from TMRx_CLK.
35 */
LPTPWM_ConfigOutputFreqAndDuty(LPTMR_T * lptmr,uint32_t u32Frequency,uint32_t u32DutyCycle)36 uint32_t LPTPWM_ConfigOutputFreqAndDuty(LPTMR_T *lptmr, uint32_t u32Frequency, uint32_t u32DutyCycle)
37 {
38 uint32_t u32PWMClockFreq, u32TargetFreq;
39 uint32_t u32Prescaler = 0x100UL, u32Period, u32CMP;
40 const uint32_t u32ClkTbl[4] = {__HIRC, __MIRC, __LXT, __LIRC};
41 uint32_t u32Src;
42
43 if (lptmr == LPTMR0)
44 {
45 u32Src = (LPSCC->CLKSEL0 & LPSCC_CLKSEL0_LPTMR0SEL_Msk) >> LPSCC_CLKSEL0_LPTMR0SEL_Pos;
46 }
47 else if (lptmr == LPTMR1)
48 {
49 u32Src = (LPSCC->CLKSEL0 & LPSCC_CLKSEL0_LPTMR1SEL_Msk) >> LPSCC_CLKSEL0_LPTMR1SEL_Pos;
50 }
51
52 u32PWMClockFreq = u32ClkTbl[u32Src];
53
54 /* Calculate u8PERIOD and u8PSC */
55 for (u32Prescaler = 1; u32Prescaler <= 0x100UL; u32Prescaler++)
56 {
57 u32Period = (u32PWMClockFreq / u32Prescaler) / u32Frequency;
58
59 /* If target u32Period is larger than 0x10000, need to use a larger prescaler */
60 if (u32Period > 0x10000UL)
61 continue;
62
63 break;
64 }
65
66 if (u32Prescaler == 0x101UL)
67 {
68 u32Prescaler = 0x100UL;
69 u32Period = 0x10000UL;
70 }
71
72 /* Store return value here 'cos we're gonna change u32Prescaler & u32Period to the real value to fill into register */
73 u32TargetFreq = (u32PWMClockFreq / u32Prescaler) / u32Period;
74
75 /* Set PWM to auto-reload mode */
76 lptmr->PWMCTL = (lptmr->PWMCTL & ~LPTMR_PWMCTL_CNTMODE_Msk) | (LPTPWM_AUTO_RELOAD_MODE << LPTMR_PWMCTL_CNTMODE_Pos);
77
78 /* Convert to real register value */
79 LPTPWM_SET_PRESCALER(lptmr, (u32Prescaler - 1UL));
80
81 LPTPWM_SET_PERIOD(lptmr, (u32Period - 1UL));
82
83 if (u32DutyCycle)
84 {
85 u32CMP = (u32DutyCycle * u32Period) / 100UL;
86 }
87 else
88 {
89 u32CMP = 0UL;
90 }
91
92 LPTPWM_SET_CMPDAT(lptmr, u32CMP);
93 return (u32TargetFreq);
94 }
95
96 /**
97 * @brief Enable LPTPWM Counter
98 *
99 * @param[in] lptmr The pointer of the specified LPTMR module. It could be LPTMR0, LPTMR1.
100 *
101 * @return None
102 *
103 * @details This function is used to enable LPTPWM generator and start counter counting.
104 */
LPTPWM_EnableCounter(LPTMR_T * lptmr)105 void LPTPWM_EnableCounter(LPTMR_T *lptmr)
106 {
107 lptmr->PWMCTL |= LPTMR_PWMCTL_CNTEN_Msk;
108 }
109
110 /**
111 * @brief Disable LPTPWM Generator
112 *
113 * @param[in] lptmr The pointer of the specified LPTMR module. It could be LPTMR0, LPTMR1.
114 *
115 * @return None
116 *
117 * @details This function is used to disable LPTPWM counter immediately by clear CNTEN (LPTMRx_PWMCTL[0]) bit.
118 */
LPTPWM_DisableCounter(LPTMR_T * lptmr)119 void LPTPWM_DisableCounter(LPTMR_T *lptmr)
120 {
121 lptmr->PWMCTL &= ~LPTMR_PWMCTL_CNTEN_Msk;
122 }
123
124 /**
125 * @brief Enable LPTPWM Trigger LPPDMA
126 *
127 * @param[in] lptmr The pointer of the specified LPTMR module. It could be LPTMR0, LPTMR1
128 * @param[in] u32TargetMask The mask of modules (LPPDMA) trigger by LPTPWM, the combination of:
129 * - \ref LPTMR_PWMTRGCTL_PWMTRGLPPDMA_Msk
130 * @param[in] u32Condition The condition to trigger LPPDMA. It could be one of following conditions:
131 * - \ref LPTPWM_TRIGGER_AT_PERIOD_POINT
132 * - \ref LPTPWM_TRIGGER_AT_COMPARE_POINT
133 * - \ref LPTPWM_TRIGGER_AT_PERIOD_OR_COMPARE_POINT
134 * @return None
135 *
136 * @details This function is used to enable specified counter event to trigger ADC/DAC/PDMA.
137 */
LPTPWM_EnableTrigger(LPTMR_T * lptmr,uint32_t u32TargetMask,uint32_t u32Condition)138 void LPTPWM_EnableTrigger(LPTMR_T *lptmr, uint32_t u32TargetMask, uint32_t u32Condition)
139 {
140 lptmr->PWMTRGCTL &= ~( LPTMR_PWMTRGCTL_PWMTRGLPPDMA_Msk | LPTMR_PWMTRGCTL_TRGEN_Msk| LPTMR_PWMTRGCTL_TRGSEL_Msk);
141 lptmr->PWMTRGCTL |= (u32TargetMask) | (u32Condition);
142 }
143
144 /**
145 * @brief Disable Trigger LPPDMA
146 *
147 * @param[in] lptmr The pointer of the specified LPTMR module. It could be LPTMR0, LPTMR1
148 * @param[in] u32TargetMask The mask of modules (LPPDMA) trigger by LPTPWM, the combination of:
149 * - \ref LPTMR_PWMTRGCTL_PWMTRGLPPDMA_Msk
150 *
151 * @return None
152 *
153 * @details This function is used to disable counter event to trigger LPPDMA.
154 */
LPTPWM_DisableTrigger(LPTMR_T * lptmr,uint32_t u32TargetMask)155 void LPTPWM_DisableTrigger(LPTMR_T *lptmr, uint32_t u32TargetMask)
156 {
157 lptmr->PWMTRGCTL &= ~(u32TargetMask);
158 }
159
160 /**
161 * @brief Enable Interrupt Flag Accumulator
162 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
163 * @param[in] u32IntFlagCnt Interrupt flag counter. Valid values are between 0~65535.
164 * @param[in] u32IntAccSrc Interrupt flag accumulator source selection.
165 * - \ref LPTPWM_IFA_PERIOD_POINT
166 * - \ref LPTPWM_IFA_COMPARE_UP_COUNT_POINT
167 * @return None
168 * @details This function is used to enable interrupt flag accumulator.
169 */
LPTPWM_EnableAcc(LPTMR_T * lptmr,uint32_t u32IntFlagCnt,uint32_t u32IntAccSrc)170 void LPTPWM_EnableAcc(LPTMR_T *lptmr, uint32_t u32IntFlagCnt, uint32_t u32IntAccSrc)
171 {
172 lptmr->PWMIFA = (((lptmr)->PWMIFA & ~(LPTMR_PWMIFA_IFACNT_Msk | LPTMR_PWMIFA_IFASEL_Msk | LPTMR_PWMIFA_STPMOD_Msk))
173 | (LPTMR_PWMIFA_IFAEN_Msk | (u32IntFlagCnt << LPTMR_PWMIFA_IFACNT_Pos) | (u32IntAccSrc << LPTMR_PWMIFA_IFASEL_Pos)));
174 }
175
176 /**
177 * @brief Disable Interrupt Flag Accumulator
178 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
179 * @return None
180 * @details This function is used to disable interrupt flag accumulator.
181 */
LPTPWM_DisableAcc(LPTMR_T * lptmr)182 void LPTPWM_DisableAcc(LPTMR_T *lptmr)
183 {
184 lptmr->PWMIFA &= ~LPTMR_PWMIFA_IFAEN_Msk;
185 }
186
187 /**
188 * @brief Enable Interrupt Flag Accumulator Interrupt Function
189 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
190 * @return None
191 * @details This function is used to enable interrupt flag accumulator interrupt.
192 */
LPTPWM_EnableAccInt(LPTMR_T * lptmr)193 void LPTPWM_EnableAccInt(LPTMR_T *lptmr)
194 {
195 lptmr->PWMAINTEN |= LPTMR_PWMAINTEN_IFAIEN_Msk;
196 }
197
198 /**
199 * @brief Disable Interrupt Flag Accumulator Interrupt Function
200 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
201 * @return None
202 * @details This function is used to disable interrupt flag accumulator interrupt.
203 */
LPTPWM_DisableAccInt(LPTMR_T * lptmr)204 void LPTPWM_DisableAccInt(LPTMR_T *lptmr)
205 {
206 lptmr->PWMAINTEN &= ~LPTMR_PWMAINTEN_IFAIEN_Msk;
207 }
208
209 /**
210 * @brief Clear Interrupt Flag Accumulator Interrupt Flag
211 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
212 * @return None
213 * @details This function is used to clear interrupt flag accumulator interrupt.
214 */
LPTPWM_ClearAccInt(LPTMR_T * lptmr)215 void LPTPWM_ClearAccInt(LPTMR_T *lptmr)
216 {
217 lptmr->PWMAINTSTS = LPTMR_PWMAINTSTS_IFAIF_Msk;
218 }
219
220 /**
221 * @brief Get Interrupt Flag Accumulator Interrupt Flag
222 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
223 * @retval 0 Accumulator interrupt did not occur
224 * @retval 1 Accumulator interrupt occurred
225 * @details This function is used to get interrupt flag accumulator interrupt.
226 */
LPTPWM_GetAccInt(LPTMR_T * lptmr)227 uint32_t LPTPWM_GetAccInt(LPTMR_T *lptmr)
228 {
229 return (((lptmr)->PWMAINTSTS & LPTMR_PWMAINTSTS_IFAIF_Msk)? 1UL : 0UL);
230 }
231
232 /**
233 * @brief Enable Accumulator Interrupt Trigger LPPDMA
234 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
235 * @return None
236 * @details This function is used to enable accumulator interrupt trigger PDMA transfer.
237 */
LPTPWM_EnableAccLPPDMA(LPTMR_T * lptmr)238 void LPTPWM_EnableAccLPPDMA(LPTMR_T *lptmr)
239 {
240 lptmr->PWMAPDMACTL |= LPTMR_PWMAPDMACTL_APDMAEN_Msk;
241 }
242
243 /**
244 * @brief Disable Accumulator Interrupt Trigger PDMA
245 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
246 * @return None
247 * @details This function is used to disable accumulator interrupt trigger PDMA transfer.
248 */
LPTPWM_DisableAccPDMA(LPTMR_T * lptmr)249 void LPTPWM_DisableAccPDMA(LPTMR_T *lptmr)
250 {
251 lptmr->PWMAPDMACTL &= ~LPTMR_PWMAPDMACTL_APDMAEN_Msk;
252 }
253
254 /**
255 * @brief Enable Interrupt Flag Accumulator Stop Mode
256 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
257 * @return None
258 * @details This function is used to enable interrupt flag accumulator event to stop PWM counting.
259 */
LPTPWM_EnableAccStopMode(LPTMR_T * lptmr)260 void LPTPWM_EnableAccStopMode(LPTMR_T *lptmr)
261 {
262 lptmr->PWMIFA |= LPTMR_PWMIFA_STPMOD_Msk;
263 }
264
265 /**
266 * @brief Disable Interrupt Flag Accumulator Stop Mode
267 * @param[in] lptmr The pointer of the specified Timer module. It could be LPTMR0, LPTMR1
268 * @return None
269 * @details This function is used to disable interrupt flag accumulator event to stop PWM counting.
270 */
LPTPWM_DisableAccStopMode(LPTMR_T * lptmr)271 void LPTPWM_DisableAccStopMode(LPTMR_T *lptmr)
272 {
273 lptmr->PWMIFA &= ~LPTMR_PWMIFA_STPMOD_Msk;
274 }
275
276 /*@}*/ /* end of group LPTMR_PWM_EXPORTED_FUNCTIONS */
277
278 /*@}*/ /* end of group LPTMR_PWM_Driver */
279
280 /*@}*/ /* end of group Standard_Driver */
281
282 /*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/
283