1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #ifndef _FSL_PWM_H_
9 #define _FSL_PWM_H_
10 
11 #include "fsl_common.h"
12 
13 /*!
14  * @addtogroup pwm_driver
15  * @{
16  */
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*! @name Driver version */
23 /*@{*/
24 #define FSL_PWM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
25 /*@}*/
26 
27 /*! @brief PWM clock source select. */
28 typedef enum _pwm_clock_source
29 {
30     kPWM_PeripheralClock = 1U, /*!< The Peripheral clock is used as the clock */
31     kPWM_HighFrequencyClock,   /*!< High-frequency reference clock is used as the clock */
32     kPWM_LowFrequencyClock     /*!< Low-frequency reference clock(32KHz) is used as the clock */
33 } pwm_clock_source_t;
34 
35 /*!
36  * @brief PWM FIFO water mark select.
37  * Sets the data level at which the FIFO empty flag will be set
38  */
39 typedef enum _pwm_fifo_water_mark
40 {
41     kPWM_FIFOWaterMark_1 = 0U, /*!< FIFO empty flag is set when there are more than or equal to 1 empty slots */
42     kPWM_FIFOWaterMark_2,      /*!< FIFO empty flag is set when there are more than or equal to 2 empty slots */
43     kPWM_FIFOWaterMark_3,      /*!< FIFO empty flag is set when there are more than or equal to 3 empty slots */
44     kPWM_FIFOWaterMark_4       /*!< FIFO empty flag is set when there are more than or equal to 4 empty slots */
45 } pwm_fifo_water_mark_t;
46 
47 /*!
48  * @brief PWM byte data swap select.
49  * It determines the byte ordering of the 16-bit data when it goes into the FIFO from the sample register.
50  */
51 typedef enum _pwm_byte_data_swap
52 {
53     kPWM_ByteNoSwap = 0U, /*!< byte ordering remains the same */
54     kPWM_ByteSwap         /*!< byte ordering is reversed */
55 } pwm_byte_data_swap_t;
56 
57 /*! @brief PWM half-word data swap select. */
58 typedef enum _pwm_half_word_data_swap
59 {
60     kPWM_HalfWordNoSwap = 0U, /*!< Half word swapping does not take place */
61     kPWM_HalfWordSwap         /*!< Half word from write data bus are swapped */
62 } pwm_half_word_data_swap_t;
63 
64 /*! @brief PWM Output Configuration */
65 typedef enum _pwm_output_configuration
66 {
67     kPWM_SetAtRolloverAndClearAtcomparison = 0U, /*!< Output pin is set at rollover and cleared at comparison */
68     kPWM_ClearAtRolloverAndSetAtcomparison,      /*!< Output pin is cleared at rollover and set at comparison */
69     kPWM_NoConfigure                             /*!< PWM output is disconnected */
70 } pwm_output_configuration_t;
71 
72 /*!
73  * @brief PWM FIFO sample repeat
74  * It determines the number of times each sample from the FIFO is to be used.
75  */
76 typedef enum _pwm_sample_repeat
77 {
78     kPWM_EachSampleOnce = 0u, /*!< Use each sample once */
79     kPWM_EachSampletwice,     /*!< Use each sample twice */
80     kPWM_EachSampleFourTimes, /*!< Use each sample four times */
81     kPWM_EachSampleEightTimes /*!< Use each sample eight times */
82 } pwm_sample_repeat_t;
83 
84 /*! @brief List of PWM interrupt options */
85 typedef enum _pwm_interrupt_enable
86 {
87     kPWM_FIFOEmptyInterruptEnable = (1U << 0), /*!< This bit controls the generation of the FIFO Empty interrupt. */
88     kPWM_RolloverInterruptEnable  = (1U << 1), /*!< This bit controls the generation of the Rollover interrupt. */
89     kPWM_CompareInterruptEnable   = (1U << 2)  /*!< This bit controls the generation of the Compare interrupt */
90 } pwm_interrupt_enable_t;
91 
92 /*! @brief List of PWM status flags */
93 typedef enum _pwm_status_flags
94 {
95     kPWM_FIFOEmptyFlag = (1U << 3), /*!< This bit indicates the FIFO data level in comparison to the water
96                                          level set by FWM field in the control register. */
97     kPWM_RolloverFlag = (1U << 4),  /*!< This bit shows that a roll-over event has occurred. */
98     kPWM_CompareFlag  = (1U << 5),  /*!< This bit shows that a compare event has occurred. */
99     kPWM_FIFOWriteErrorFlag =
100         (1U << 6) /*!< This bit shows that an attempt has been made to write FIFO when it is full. */
101 } pwm_status_flags_t;
102 
103 /*! @brief List of PWM FIFO available */
104 typedef enum _pwm_fifo_available
105 {
106     kPWM_NoDataInFIFOFlag = 0U, /*!< No data available */
107     kPWM_OneWordInFIFOFlag,     /*!< 1 word of data in FIFO */
108     kPWM_TwoWordsInFIFOFlag,    /*!< 2 word of data in FIFO */
109     kPWM_ThreeWordsInFIFOFlag,  /*!< 3 word of data in FIFO */
110     kPWM_FourWordsInFIFOFlag    /*!< 4 word of data in FIFO */
111 } pwm_fifo_available_t;
112 
113 typedef struct _pwm_config
114 {
115     bool enableStopMode;                     /*!< True: PWM continues to run in stop mode;
116                                                   False: PWM is paused in stop mode. */
117     bool enableDozeMode;                     /*!< True: PWM continues to run in doze mode;
118                                                   False: PWM is paused in doze mode. */
119     bool enableWaitMode;                     /*!< True: PWM continues to run in wait mode;
120                                                   False: PWM is paused in wait mode. */
121     bool enableDebugMode;                    /*!< True: PWM continues to run in debug mode;
122                                                   False: PWM is paused in debug mode. */
123     uint16_t prescale;                       /*!< Pre-scaler to divide down the clock
124                                                   The prescaler value is not more than 0xFFF. Divide by (value + 1)*/
125     pwm_clock_source_t clockSource;          /*!< Clock source for the counter */
126     pwm_output_configuration_t outputConfig; /*!< Set the mode of the PWM output on the output pin. */
127     pwm_fifo_water_mark_t fifoWater;         /*!< Set the data level for FIFO. */
128     pwm_sample_repeat_t sampleRepeat;        /*!< The number of times each sample from the FIFO is to be used. */
129     pwm_byte_data_swap_t byteSwap; /*!< It determines the byte ordering of the 16-bit data when it goes into the
130                                         FIFO from the sample register. */
131     pwm_half_word_data_swap_t halfWordSwap; /*!< It determines which half word data from the 32-bit IP Bus interface is
132                                                  written into the lower 16 bits of the sample register. */
133 } pwm_config_t;
134 
135 /*******************************************************************************
136  * API
137  ******************************************************************************/
138 
139 #if defined(__cplusplus)
140 extern "C" {
141 #endif
142 
143 /*!
144  * @name Initialization and deinitialization
145  * @{
146  */
147 
148 /*!
149  * @brief Ungates the PWM clock and configures the peripheral for basic operation.
150  *
151  * @note This API should be called at the beginning of the application using the PWM driver.
152  *
153  * @param base      PWM peripheral base address
154  * @param config    Pointer to user's PWM config structure.
155  *
156  * @return kStatus_Success means success; else failed.
157  */
158 status_t PWM_Init(PWM_Type *base, const pwm_config_t *config);
159 
160 /*!
161  * @brief Gate the PWM submodule clock
162  *
163  * @param base      PWM peripheral base address
164  */
165 void PWM_Deinit(PWM_Type *base);
166 
167 /*!
168  * @brief  Fill in the PWM config struct with the default settings
169  *
170  * The default values are:
171  * @code
172  *   config->enableStopMode = false;
173  *   config->enableDozeMode = false;
174  *   config->enableWaitMode = false;
175  *   config->enableDozeMode = false;
176  *   config->clockSource = kPWM_LowFrequencyClock;
177  *   config->prescale = 0U;
178  *   config->outputConfig = kPWM_SetAtRolloverAndClearAtcomparison;
179  *   config->fifoWater = kPWM_FIFOWaterMark_2;
180  *   config->sampleRepeat = kPWM_EachSampleOnce;
181  *   config->byteSwap = kPWM_ByteNoSwap;
182  *   config->halfWordSwap = kPWM_HalfWordNoSwap;
183  * @endcode
184  * @param config Pointer to user's PWM config structure.
185  */
186 void PWM_GetDefaultConfig(pwm_config_t *config);
187 
188 /*! @}*/
189 
190 /*!
191  * @name PWM start and stop.
192  * @{
193  */
194 
195 /*!
196  * @brief Starts the PWM counter when the PWM is enabled.
197  *
198  * When the PWM is enabled, it begins a new period, the output pin is set to start a new period while
199  * the prescaler and counter are released and counting begins.
200  *
201  * @param base      PWM peripheral base address
202  */
PWM_StartTimer(PWM_Type * base)203 static inline void PWM_StartTimer(PWM_Type *base)
204 {
205     base->PWMCR |= PWM_PWMCR_EN_MASK;
206 }
207 
208 /*!
209  * @brief Stops the PWM counter when the pwm is disabled.
210  *
211  * @param base      PWM peripheral base address
212  */
PWM_StopTimer(PWM_Type * base)213 static inline void PWM_StopTimer(PWM_Type *base)
214 {
215     base->PWMCR &= ~(PWM_PWMCR_EN_MASK);
216 }
217 
218 /*! @}*/
219 
220 /*!
221  * @brief Sofrware reset.
222  *
223  * PWM is reset when this bit is set to 1. It is a self clearing bit.
224  * Setting this bit resets all the registers to their reset values except for the STOPEN,
225  * DOZEN, WAITEN, and DBGEN bits in this control register.
226  *
227  * @param base      PWM peripheral base address
228  */
PWM_SoftwareReset(PWM_Type * base)229 static inline void PWM_SoftwareReset(PWM_Type *base)
230 {
231     base->PWMCR |= PWM_PWMCR_SWR_MASK;
232 }
233 
234 /*!
235  * @name Interrupt Interface
236  * @{
237  */
238 
239 /*!
240  * @brief Enables the selected PWM interrupts.
241  *
242  * @param base PWM peripheral base address
243  * @param mask The interrupts to enable. This is a logical OR of members of the
244  *             enumeration ::pwm_interrupt_enable_t
245  */
PWM_EnableInterrupts(PWM_Type * base,uint32_t mask)246 static inline void PWM_EnableInterrupts(PWM_Type *base, uint32_t mask)
247 {
248     base->PWMIR |= (mask & (PWM_PWMIR_FIE_MASK | PWM_PWMIR_RIE_MASK | PWM_PWMIR_CIE_MASK));
249 }
250 
251 /*!
252  * @brief Disables the selected PWM interrupts.
253  *
254  * @param base PWM peripheral base address
255  * @param mask The interrupts to disable. This is a logical OR of members of the
256  *             enumeration ::pwm_interrupt_enable_t
257  */
PWM_DisableInterrupts(PWM_Type * base,uint32_t mask)258 static inline void PWM_DisableInterrupts(PWM_Type *base, uint32_t mask)
259 {
260     base->PWMIR &= ~(mask & (PWM_PWMIR_FIE_MASK | PWM_PWMIR_RIE_MASK | PWM_PWMIR_CIE_MASK));
261 }
262 
263 /*!
264  * @brief Gets the enabled PWM interrupts.
265  *
266  * @param base PWM peripheral base address
267  *
268  * @return The enabled interrupts. This is the logical OR of members of the
269  *         enumeration ::pwm_interrupt_enable_t
270  */
PWM_GetEnabledInterrupts(PWM_Type * base)271 static inline uint32_t PWM_GetEnabledInterrupts(PWM_Type *base)
272 {
273     return base->PWMIR;
274 }
275 
276 /*! @}*/
277 
278 /*!
279  * @name Status Interface
280  * @{
281  */
282 
283 /*!
284  * @brief Gets the PWM status flags.
285  *
286  * @param base PWM peripheral base address
287  *
288  * @return The status flags. This is the logical OR of members of the
289  *         enumeration ::pwm_status_flags_t
290  */
PWM_GetStatusFlags(PWM_Type * base)291 static inline uint32_t PWM_GetStatusFlags(PWM_Type *base)
292 {
293     uint32_t statusFlags = base->PWMSR;
294 
295     statusFlags &= (PWM_PWMSR_FE_MASK | PWM_PWMSR_ROV_MASK | PWM_PWMSR_CMP_MASK | PWM_PWMSR_FWE_MASK);
296     return statusFlags;
297 }
298 
299 /*!
300  * @brief Clears the PWM status flags.
301  *
302  * @param base PWM peripheral base address
303  * @param mask The status flags to clear. This is a logical OR of members of the
304  *             enumeration ::pwm_status_flags_t
305  */
PWM_clearStatusFlags(PWM_Type * base,uint32_t mask)306 static inline void PWM_clearStatusFlags(PWM_Type *base, uint32_t mask)
307 {
308     base->PWMSR = (mask & (PWM_PWMSR_FE_MASK | PWM_PWMSR_ROV_MASK | PWM_PWMSR_CMP_MASK | PWM_PWMSR_FWE_MASK));
309 }
310 
311 /*!
312  * @brief Gets the PWM FIFO available.
313  *
314  * @param base PWM peripheral base address
315  *
316  * @return The status flags. This is the logical OR of members of the
317  *         enumeration ::pwm_fifo_available_t
318  */
PWM_GetFIFOAvailable(PWM_Type * base)319 static inline uint32_t PWM_GetFIFOAvailable(PWM_Type *base)
320 {
321     return (base->PWMSR & PWM_PWMSR_FIFOAV_MASK);
322 }
323 
324 /*! @}*/
325 
326 /*!
327  * @name Sample Interface
328  * @{
329  */
330 
331 /*!
332  * @brief Sets the PWM sample value.
333  *
334  * @param base PWM peripheral base address
335  * @param value The sample value. This is the input to the 4x16 FIFO. The value in this register denotes
336  *             the value of the sample being currently used.
337  */
PWM_SetSampleValue(PWM_Type * base,uint32_t value)338 static inline void PWM_SetSampleValue(PWM_Type *base, uint32_t value)
339 {
340     base->PWMSAR = (value & PWM_PWMSAR_SAMPLE_MASK);
341 }
342 
343 /*!
344  * @brief Gets the PWM sample value.
345  *
346  * @param base PWM peripheral base address
347  *
348  * @return The sample value. It can be read only when the PWM is enable.
349  */
PWM_GetSampleValue(PWM_Type * base)350 static inline uint32_t PWM_GetSampleValue(PWM_Type *base)
351 {
352     return base->PWMSAR;
353 }
354 
355 /*! @}*/
356 
357 /*!
358  * @brief Sets the PWM period value.
359  *
360  * @param base PWM peripheral base address
361  * @param value The period value. The PWM period register (PWM_PWMPR) determines the period of
362  *             the PWM output signal.
363  *             Writing 0xFFFF to this register will achieve the same result as writing 0xFFFE.
364  *             PWMO (Hz) = PCLK(Hz) / (period +2)
365  */
PWM_SetPeriodValue(PWM_Type * base,uint32_t value)366 static inline void PWM_SetPeriodValue(PWM_Type *base, uint32_t value)
367 {
368     base->PWMPR = (value & PWM_PWMPR_PERIOD_MASK);
369 }
370 
371 /*!
372  * @brief Gets the PWM period value.
373  *
374  * @param base PWM peripheral base address
375  *
376  * @return The period value. The PWM period register (PWM_PWMPR) determines the period of
377  *             the PWM output signal.
378  */
PWM_GetPeriodValue(PWM_Type * base)379 static inline uint32_t PWM_GetPeriodValue(PWM_Type *base)
380 {
381     return (base->PWMPR & PWM_PWMPR_PERIOD_MASK);
382 }
383 
384 /*!
385  * @brief Gets the PWM counter value.
386  *
387  * @param base PWM peripheral base address
388  *
389  * @return The counter value. The current count value.
390  */
PWM_GetCounterValue(PWM_Type * base)391 static inline uint32_t PWM_GetCounterValue(PWM_Type *base)
392 {
393     return (base->PWMCNR & PWM_PWMCNR_COUNT_MASK);
394 }
395 
396 #if defined(__cplusplus)
397 }
398 #endif
399 
400 /*! @}*/
401 
402 #endif /* _FSL_PWM_H_ */
403