ChibiOS/HAL  6.1.0
hal_pwm.h
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 /**
18  * @file hal_pwm.h
19  * @brief PWM Driver macros and structures.
20  *
21  * @addtogroup PWM
22  * @{
23  */
24 
25 #ifndef HAL_PWM_H
26 #define HAL_PWM_H
27 
28 #if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
29 
30 /*===========================================================================*/
31 /* Driver constants. */
32 /*===========================================================================*/
33 
34 /**
35  * @name PWM output mode macros
36  * @{
37  */
38 /**
39  * @brief Standard output modes mask.
40  */
41 #define PWM_OUTPUT_MASK 0x0FU
42 
43 /**
44  * @brief Output not driven, callback only.
45  */
46 #define PWM_OUTPUT_DISABLED 0x00U
47 
48 /**
49  * @brief Positive PWM logic, active is logic level one.
50  */
51 #define PWM_OUTPUT_ACTIVE_HIGH 0x01U
52 
53 /**
54  * @brief Inverse PWM logic, active is logic level zero.
55  */
56 #define PWM_OUTPUT_ACTIVE_LOW 0x02U
57 /** @} */
58 
59 /*===========================================================================*/
60 /* Driver pre-compile time settings. */
61 /*===========================================================================*/
62 
63 /*===========================================================================*/
64 /* Derived constants and error checks. */
65 /*===========================================================================*/
66 
67 /*===========================================================================*/
68 /* Driver data structures and types. */
69 /*===========================================================================*/
70 
71 /**
72  * @brief Driver state machine possible states.
73  */
74 typedef enum {
75  PWM_UNINIT = 0, /**< Not initialized. */
76  PWM_STOP = 1, /**< Stopped. */
77  PWM_READY = 2 /**< Ready. */
78 } pwmstate_t;
79 
80 /**
81  * @brief Type of a structure representing a PWM driver.
82  */
83 typedef struct PWMDriver PWMDriver;
84 
85 /**
86  * @brief Type of a PWM notification callback.
87  *
88  * @param[in] pwmp pointer to a @p PWMDriver object
89  */
90 typedef void (*pwmcallback_t)(PWMDriver *pwmp);
91 
92 #include "hal_pwm_lld.h"
93 
94 /*===========================================================================*/
95 /* Driver macros. */
96 /*===========================================================================*/
97 
98 /**
99  * @name PWM duty cycle conversion
100  * @{
101  */
102 /**
103  * @brief Converts from fraction to pulse width.
104  * @note Be careful with rounding errors, this is integer math not magic.
105  * You can specify tenths of thousandth but make sure you have the
106  * proper hardware resolution by carefully choosing the clock source
107  * and prescaler settings, see @p PWM_COMPUTE_PSC.
108  *
109  * @param[in] pwmp pointer to a @p PWMDriver object
110  * @param[in] denominator denominator of the fraction
111  * @param[in] numerator numerator of the fraction
112  * @return The pulse width to be passed to @p pwmEnableChannel().
113  *
114  * @api
115  */
116 #define PWM_FRACTION_TO_WIDTH(pwmp, denominator, numerator) \
117  ((pwmcnt_t)((((pwmcnt_t)(pwmp)->period) * \
118  (pwmcnt_t)(numerator)) / (pwmcnt_t)(denominator)))
119 
120 /**
121  * @brief Converts from degrees to pulse width.
122  * @note Be careful with rounding errors, this is integer math not magic.
123  * You can specify hundredths of degrees but make sure you have the
124  * proper hardware resolution by carefully choosing the clock source
125  * and prescaler settings, see @p PWM_COMPUTE_PSC.
126  *
127  * @param[in] pwmp pointer to a @p PWMDriver object
128  * @param[in] degrees degrees as an integer between 0 and 36000
129  * @return The pulse width to be passed to @p pwmEnableChannel().
130  *
131  * @api
132  */
133 #define PWM_DEGREES_TO_WIDTH(pwmp, degrees) \
134  PWM_FRACTION_TO_WIDTH(pwmp, 36000, degrees)
135 
136 /**
137  * @brief Converts from percentage to pulse width.
138  * @note Be careful with rounding errors, this is integer math not magic.
139  * You can specify tenths of thousandth but make sure you have the
140  * proper hardware resolution by carefully choosing the clock source
141  * and prescaler settings, see @p PWM_COMPUTE_PSC.
142  *
143  * @param[in] pwmp pointer to a @p PWMDriver object
144  * @param[in] percentage percentage as an integer between 0 and 10000
145  * @return The pulse width to be passed to @p pwmEnableChannel().
146  *
147  * @api
148  */
149 #define PWM_PERCENTAGE_TO_WIDTH(pwmp, percentage) \
150  PWM_FRACTION_TO_WIDTH(pwmp, 10000, percentage)
151 /** @} */
152 
153 /**
154  * @name Macro Functions
155  * @{
156  */
157 /**
158  * @brief Changes the period the PWM peripheral.
159  * @details This function changes the period of a PWM unit that has already
160  * been activated using @p pwmStart().
161  * @pre The PWM unit must have been activated using @p pwmStart().
162  * @post The PWM unit period is changed to the new value.
163  * @note If a period is specified that is shorter than the pulse width
164  * programmed in one of the channels then the behavior is not
165  * guaranteed.
166  *
167  * @param[in] pwmp pointer to a @p PWMDriver object
168  * @param[in] value new cycle time in ticks
169  *
170  * @iclass
171  */
172 #define pwmChangePeriodI(pwmp, value) { \
173  (pwmp)->period = (value); \
174  pwm_lld_change_period(pwmp, value); \
175 }
176 
177 /**
178  * @brief Enables a PWM channel.
179  * @pre The PWM unit must have been activated using @p pwmStart().
180  * @post The channel is active using the specified configuration.
181  * @note Depending on the hardware implementation this function has
182  * effect starting on the next cycle (recommended implementation)
183  * or immediately (fallback implementation).
184  *
185  * @param[in] pwmp pointer to a @p PWMDriver object
186  * @param[in] channel PWM channel identifier (0...channels-1)
187  * @param[in] width PWM pulse width as clock pulses number
188  *
189  * @iclass
190  */
191 #define pwmEnableChannelI(pwmp, channel, width) do { \
192  (pwmp)->enabled |= ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \
193  pwm_lld_enable_channel(pwmp, channel, width); \
194 } while (false)
195 
196 /**
197  * @brief Disables a PWM channel.
198  * @pre The PWM unit must have been activated using @p pwmStart().
199  * @post The channel is disabled and its output line returned to the
200  * idle state.
201  * @note Depending on the hardware implementation this function has
202  * effect starting on the next cycle (recommended implementation)
203  * or immediately (fallback implementation).
204  *
205  * @param[in] pwmp pointer to a @p PWMDriver object
206  * @param[in] channel PWM channel identifier (0...channels-1)
207  *
208  * @iclass
209  */
210 #define pwmDisableChannelI(pwmp, channel) do { \
211  (pwmp)->enabled &= ~((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \
212  pwm_lld_disable_channel(pwmp, channel); \
213 } while (false)
214 
215 /**
216  * @brief Returns a PWM channel status.
217  * @pre The PWM unit must have been activated using @p pwmStart().
218  *
219  * @param[in] pwmp pointer to a @p PWMDriver object
220  * @param[in] channel PWM channel identifier (0...channels-1)
221  *
222  * @iclass
223  */
224 #define pwmIsChannelEnabledI(pwmp, channel) \
225  (((pwmp)->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel))) != 0U)
226 
227 /**
228  * @brief Enables the periodic activation edge notification.
229  * @pre The PWM unit must have been activated using @p pwmStart().
230  * @note If the notification is already enabled then the call has no effect.
231  *
232  * @param[in] pwmp pointer to a @p PWMDriver object
233  *
234  * @iclass
235  */
236 #define pwmEnablePeriodicNotificationI(pwmp) \
237  pwm_lld_enable_periodic_notification(pwmp)
238 
239 /**
240  * @brief Disables the periodic activation edge notification.
241  * @pre The PWM unit must have been activated using @p pwmStart().
242  * @note If the notification is already disabled then the call has no effect.
243  *
244  * @param[in] pwmp pointer to a @p PWMDriver object
245  *
246  * @iclass
247  */
248 #define pwmDisablePeriodicNotificationI(pwmp) \
249  pwm_lld_disable_periodic_notification(pwmp)
250 
251 /**
252  * @brief Enables a channel de-activation edge notification.
253  * @pre The PWM unit must have been activated using @p pwmStart().
254  * @pre The channel must have been activated using @p pwmEnableChannel().
255  * @note If the notification is already enabled then the call has no effect.
256  *
257  * @param[in] pwmp pointer to a @p PWMDriver object
258  * @param[in] channel PWM channel identifier (0...channels-1)
259  *
260  * @iclass
261  */
262 #define pwmEnableChannelNotificationI(pwmp, channel) \
263  pwm_lld_enable_channel_notification(pwmp, channel)
264 
265 /**
266  * @brief Disables a channel de-activation edge notification.
267  * @pre The PWM unit must have been activated using @p pwmStart().
268  * @pre The channel must have been activated using @p pwmEnableChannel().
269  * @note If the notification is already disabled then the call has no effect.
270  *
271  * @param[in] pwmp pointer to a @p PWMDriver object
272  * @param[in] channel PWM channel identifier (0...channels-1)
273  *
274  * @iclass
275  */
276 #define pwmDisableChannelNotificationI(pwmp, channel) \
277  pwm_lld_disable_channel_notification(pwmp, channel)
278 /** @} */
279 
280 /*===========================================================================*/
281 /* External declarations. */
282 /*===========================================================================*/
283 
284 #ifdef __cplusplus
285 extern "C" {
286 #endif
287  void pwmInit(void);
288  void pwmObjectInit(PWMDriver *pwmp);
289  void pwmStart(PWMDriver *pwmp, const PWMConfig *config);
290  void pwmStop(PWMDriver *pwmp);
292  void pwmEnableChannel(PWMDriver *pwmp,
293  pwmchannel_t channel,
294  pwmcnt_t width);
295  void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel);
300 #ifdef __cplusplus
301 }
302 #endif
303 
304 #endif /* HAL_USE_PWM == TRUE */
305 
306 #endif /* HAL_PWM_H */
307 
308 /** @} */
void pwmEnableChannel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width)
Enables a PWM channel.
Definition: hal_pwm.c:167
const PWMConfig * config
Current driver configuration data.
Definition: hal_pwm_lld.h:142
void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period)
Changes the period the PWM peripheral.
Definition: hal_pwm.c:143
PLATFORM PWM subsystem low level driver header.
Type of a PWM driver configuration structure.
Definition: hal_pwm_lld.h:105
uint32_t pwmcnt_t
Type of a PWM counter.
Definition: hal_pwm_lld.h:83
void pwmEnablePeriodicNotification(PWMDriver *pwmp)
Enables the periodic activation edge notification.
Definition: hal_pwm.c:218
void pwmStop(PWMDriver *pwmp)
Deactivates the PWM peripheral.
Definition: hal_pwm.c:111
void pwmStart(PWMDriver *pwmp, const PWMConfig *config)
Configures and activates the PWM peripheral.
Definition: hal_pwm.c:89
pwmstate_t
Driver state machine possible states.
Definition: hal_pwm.h:74
Structure representing a PWM driver.
Definition: hal_pwm_lld.h:134
void pwmInit(void)
PWM Driver initialization.
Definition: hal_pwm.c:56
void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel)
Disables a PWM channel and its notification.
Definition: hal_pwm.c:196
void pwmDisablePeriodicNotification(PWMDriver *pwmp)
Disables the periodic activation edge notification.
Definition: hal_pwm.c:241
void(* pwmcallback_t)(PWMDriver *pwmp)
Type of a PWM notification callback.
Definition: hal_pwm.h:90
uint8_t pwmchannel_t
Type of a PWM channel.
Definition: hal_pwm_lld.h:73
void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel)
Enables a channel de-activation edge notification.
Definition: hal_pwm.c:266
void pwmObjectInit(PWMDriver *pwmp)
Initializes the standard part of a PWMDriver structure.
Definition: hal_pwm.c:68
void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel)
Disables a channel de-activation edge notification.
Definition: hal_pwm.c:294
pwmcnt_t period
Current PWM period in ticks.
Definition: hal_pwm_lld.h:146