1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include "esp_err.h"
10 #include "esp_intr_alloc.h"
11 #include "soc/soc.h"
12 #include "hal/ledc_types.h"
13 #include "driver/gpio.h"
14 #include "driver/periph_ctrl.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #define LEDC_APB_CLK_HZ  (APB_CLK_FREQ)
21 #define LEDC_REF_CLK_HZ  (REF_CLK_FREQ)
22 #define LEDC_ERR_DUTY    (0xFFFFFFFF)
23 #define LEDC_ERR_VAL     (-1)
24 
25 typedef intr_handle_t ledc_isr_handle_t;
26 
27 /**
28  * @brief LEDC callback event type
29  */
30 typedef enum {
31     LEDC_FADE_END_EVT                   /**< LEDC fade end event */
32 } ledc_cb_event_t;
33 
34 /**
35  * @brief LEDC callback parameter
36  */
37 typedef struct {
38     ledc_cb_event_t event;              /**< Event name */
39     uint32_t speed_mode;                /**< Speed mode of the LEDC channel group */
40     uint32_t channel;                   /**< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
41     uint32_t duty;                      /**< LEDC current duty of the channel, the range of duty is [0, (2**duty_resolution) - 1] */
42 } ledc_cb_param_t;
43 
44 /**
45  * @brief Type of LEDC event callback
46  * @param param LEDC callback parameter
47  * @param user_arg User registered data
48  */
49 typedef bool (* ledc_cb_t)(const ledc_cb_param_t *param, void *user_arg);
50 
51 /**
52  * @brief Group of supported LEDC callbacks
53  * @note The callbacks are all running under ISR environment
54  */
55 typedef struct {
56     ledc_cb_t fade_cb;                  /**< LEDC fade_end callback function */
57 } ledc_cbs_t;
58 
59 /**
60  * @brief LEDC channel configuration
61  *        Configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC duty resolution
62  *
63  * @param ledc_conf Pointer of LEDC channel configure struct
64  *
65  * @return
66  *     - ESP_OK Success
67  *     - ESP_ERR_INVALID_ARG Parameter error
68  */
69 esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf);
70 
71 /**
72  * @brief LEDC timer configuration
73  *        Configure LEDC timer with the given source timer/frequency(Hz)/duty_resolution
74  *
75  * @param  timer_conf Pointer of LEDC timer configure struct
76  *
77  * @return
78  *     - ESP_OK Success
79  *     - ESP_ERR_INVALID_ARG Parameter error
80  *     - ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current duty_resolution.
81  */
82 esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf);
83 
84 /**
85  * @brief LEDC update channel parameters
86  * @note  Call this function to activate the LEDC updated parameters.
87  *        After ledc_set_duty, we need to call this function to update the settings.
88  *        And the new LEDC parameters don't take effect until the next PWM cycle.
89  * @note  ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
90  *        control one LEDC channel in different tasks at the same time.
91  *        A thread-safe version of API is ledc_set_duty_and_update
92  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
93  * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
94  *
95  * @return
96  *     - ESP_OK Success
97  *     - ESP_ERR_INVALID_ARG Parameter error
98  *
99  */
100 esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
101 
102 /**
103  * @brief Set LEDC output gpio.
104  * @deprecated This function is redundant, please use ledc_channel_config to set gpio pins.
105  *
106  * @param  gpio_num The LEDC output gpio
107  * @param  speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
108  * @param  ledc_channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
109  *
110  * @return
111  *     - ESP_OK Success
112  *     - ESP_ERR_INVALID_ARG Parameter error
113  */
114 esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel)
115     __attribute__((deprecated("use ledc_channel_config instead")));
116 /**
117  * @brief LEDC stop.
118  *        Disable LEDC output, and set idle level
119  *
120  * @param  speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
121  * @param  channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
122  * @param  idle_level Set output idle level after LEDC stops.
123  *
124  * @return
125  *     - ESP_OK Success
126  *     - ESP_ERR_INVALID_ARG Parameter error
127  */
128 esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level);
129 
130 /**
131  * @brief LEDC set channel frequency (Hz)
132  *
133  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
134  * @param  timer_num LEDC timer index (0-3), select from ledc_timer_t
135  * @param  freq_hz Set the LEDC frequency
136  *
137  * @return
138  *     - ESP_OK Success
139  *     - ESP_ERR_INVALID_ARG Parameter error
140  *     - ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current duty_resolution.
141  */
142 esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz);
143 
144 /**
145  * @brief      LEDC get channel frequency (Hz)
146  *
147  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
148  * @param timer_num LEDC timer index (0-3), select from ledc_timer_t
149  *
150  * @return
151  *     - 0  error
152  *     - Others Current LEDC frequency
153  */
154 uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
155 
156 /**
157  * @brief LEDC set duty and hpoint value
158  *        Only after calling ledc_update_duty will the duty update.
159  * @note  ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
160  *        control one LEDC channel in different tasks at the same time.
161  *        A thread-safe version of API is ledc_set_duty_and_update
162  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
163  *        Other duty operations will have to wait until the fade operation has finished.
164  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
165  * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
166  * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1]
167  * @param hpoint Set the LEDC hpoint value(max: 0xfffff)
168  *
169  * @return
170  *     - ESP_OK Success
171  *     - ESP_ERR_INVALID_ARG Parameter error
172  */
173 esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
174 
175 /**
176  * @brief LEDC get hpoint value, the counter value when the output is set high level.
177  *
178  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
179  * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
180  * @return
181  *     - LEDC_ERR_VAL if parameter error
182  *     - Others Current hpoint value of LEDC channel
183  */
184 int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel);
185 
186 /**
187  * @brief LEDC set duty
188  *        This function do not change the hpoint value of this channel. if needed, please call ledc_set_duty_with_hpoint.
189  *        only after calling ledc_update_duty will the duty update.
190  * @note  ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
191  *        control one LEDC channel in different tasks at the same time.
192  *        A thread-safe version of API is ledc_set_duty_and_update.
193  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
194  *        Other duty operations will have to wait until the fade operation has finished.
195  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
196  * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
197  * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1]
198  *
199  * @return
200  *     - ESP_OK Success
201  *     - ESP_ERR_INVALID_ARG Parameter error
202  */
203 esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty);
204 
205 /**
206  * @brief LEDC get duty
207  *        This function returns the duty at the present PWM cycle.
208  *        You shouldn't expect the function to return the new duty in the same cycle of calling ledc_update_duty,
209  *        because duty update doesn't take effect until the next cycle.
210  *
211  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
212  * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
213  *
214  * @return
215  *     - LEDC_ERR_DUTY if parameter error
216  *     - Others Current LEDC duty
217  */
218 uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
219 
220 /**
221  * @brief LEDC set gradient
222  *        Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
223  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
224  *        Other duty operations will have to wait until the fade operation has finished.
225  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
226  * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
227  * @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution) - 1]
228  * @param fade_direction Set the direction of the gradient
229  * @param step_num Set the number of the gradient
230  * @param duty_cycle_num Set how many LEDC tick each time the gradient lasts
231  * @param duty_scale Set gradient change amplitude
232  *
233  * @return
234  *     - ESP_OK Success
235  *     - ESP_ERR_INVALID_ARG Parameter error
236  */
237 esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t fade_direction,
238                         uint32_t step_num, uint32_t duty_cycle_num, uint32_t duty_scale);
239 
240 /**
241  * @brief Register LEDC interrupt handler, the handler is an ISR.
242  *        The handler will be attached to the same CPU core that this function is running on.
243  *
244  * @param fn Interrupt handler function.
245  * @param arg User-supplied argument passed to the handler function.
246  * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
247  *        ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
248  * @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
249  *        be returned here.
250  *
251  * @return
252  *     - ESP_OK Success
253  *     - ESP_ERR_INVALID_ARG Function pointer error.
254  */
255 esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
256 
257 /**
258  * @brief Configure LEDC settings
259  *
260  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
261  * @param timer_sel  Timer index (0-3), there are 4 timers in LEDC module
262  * @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
263  * @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution)]
264  * @param clk_src Select LEDC source clock.
265  *
266  * @return
267  *     - (-1) Parameter error
268  *     - Other Current LEDC duty
269  */
270 esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, ledc_clk_src_t clk_src);
271 
272 /**
273  * @brief Reset LEDC timer
274  *
275  * @param  speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
276  * @param  timer_sel LEDC timer index (0-3), select from ledc_timer_t
277  *
278  * @return
279  *     - ESP_ERR_INVALID_ARG Parameter error
280  *     - ESP_OK Success
281  */
282 esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
283 
284 /**
285  * @brief Pause LEDC timer counter
286  *
287  * @param  speed_mode  Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
288  * @param  timer_sel LEDC timer index (0-3), select from ledc_timer_t
289  *
290  * @return
291  *     - ESP_ERR_INVALID_ARG Parameter error
292  *     - ESP_OK Success
293  *
294  */
295 esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
296 
297 /**
298  * @brief Resume LEDC timer
299  *
300  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
301  * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
302  *
303  * @return
304  *     - ESP_ERR_INVALID_ARG Parameter error
305  *     - ESP_OK Success
306  */
307 esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
308 
309 /**
310  * @brief Bind LEDC channel with the selected timer
311  *
312  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
313  * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
314  * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
315  *
316  * @return
317  *     - ESP_ERR_INVALID_ARG Parameter error
318  *     - ESP_OK Success
319  */
320 esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_timer_t timer_sel);
321 
322 /**
323  * @brief Set LEDC fade function.
324  * @note  Call ledc_fade_func_install() once before calling this function.
325  *        Call ledc_fade_start() after this to start fading.
326  * @note  ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to
327  *        control one LEDC channel in different tasks at the same time.
328  *        A thread-safe version of API is ledc_set_fade_step_and_start
329  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
330  *        Other duty operations will have to wait until the fade operation has finished.
331  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. ,
332  * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
333  * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
334  * @param scale Controls the increase or decrease step scale.
335  * @param cycle_num increase or decrease the duty every cycle_num cycles
336  *
337  * @return
338  *     - ESP_ERR_INVALID_ARG Parameter error
339  *     - ESP_OK Success
340  *     - ESP_ERR_INVALID_STATE Fade function not installed.
341  *     - ESP_FAIL Fade function init error
342  */
343 esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num);
344 
345 /**
346  * @brief Set LEDC fade function, with a limited time.
347  * @note  Call ledc_fade_func_install() once before calling this function.
348  *        Call ledc_fade_start() after this to start fading.
349  * @note  ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to
350  *        control one LEDC channel in different tasks at the same time.
351  *        A thread-safe version of API is ledc_set_fade_step_and_start
352  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
353  *        Other duty operations will have to wait until the fade operation has finished.
354  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. ,
355  * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
356  * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
357  * @param max_fade_time_ms The maximum time of the fading ( ms ).
358  *
359  * @return
360  *     - ESP_ERR_INVALID_ARG Parameter error
361  *     - ESP_OK Success
362  *     - ESP_ERR_INVALID_STATE Fade function not installed.
363  *     - ESP_FAIL Fade function init error
364  */
365 esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms);
366 
367 /**
368  * @brief Install LEDC fade function. This function will occupy interrupt of LEDC module.
369  * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
370  *        ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
371  *
372  * @return
373  *     - ESP_OK Success
374  *     - ESP_ERR_INVALID_STATE Fade function already installed.
375  */
376 esp_err_t ledc_fade_func_install(int intr_alloc_flags);
377 
378 /**
379  * @brief Uninstall LEDC fade function.
380  *
381  */
382 void ledc_fade_func_uninstall(void);
383 
384 /**
385  * @brief Start LEDC fading.
386  * @note  Call ledc_fade_func_install() once before calling this function.
387  *        Call this API right after ledc_set_fade_with_time or ledc_set_fade_with_step before to start fading.
388  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
389  *        Other duty operations will have to wait until the fade operation has finished.
390  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
391  * @param channel LEDC channel number
392  * @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info.
393  *        Note that this function will not return until fading to the target duty if LEDC_FADE_WAIT_DONE mode is selected.
394  *
395  * @return
396  *     - ESP_OK Success
397  *     - ESP_ERR_INVALID_STATE Fade function not installed.
398  *     - ESP_ERR_INVALID_ARG Parameter error.
399  */
400 esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode);
401 
402 /**
403  * @brief A thread-safe API to set duty for LEDC channel and return when duty updated.
404  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
405  *        Other duty operations will have to wait until the fade operation has finished.
406  *
407  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
408  * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
409  * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1]
410  * @param hpoint Set the LEDC hpoint value(max: 0xfffff)
411  *
412  */
413 esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
414 
415 /**
416  * @brief A thread-safe API to set and start LEDC fade function, with a limited time.
417  * @note  Call ledc_fade_func_install() once, before calling this function.
418  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
419  *        Other duty operations will have to wait until the fade operation has finished.
420  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
421  * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
422  * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
423  * @param max_fade_time_ms The maximum time of the fading ( ms ).
424  * @param fade_mode choose blocking or non-blocking mode
425  * @return
426  *     - ESP_ERR_INVALID_ARG Parameter error
427  *     - ESP_OK Success
428  *     - ESP_ERR_INVALID_STATE Fade function not installed.
429  *     - ESP_FAIL Fade function init error
430  */
431 esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode);
432 
433 /**
434  * @brief A thread-safe API to set and start LEDC fade function.
435  * @note  Call ledc_fade_func_install() once before calling this function.
436  * @note  If a fade operation is running in progress on that channel, the driver would not allow it to be stopped.
437  *        Other duty operations will have to wait until the fade operation has finished.
438  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
439  * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
440  * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
441  * @param scale Controls the increase or decrease step scale.
442  * @param cycle_num increase or decrease the duty every cycle_num cycles
443  * @param fade_mode choose blocking or non-blocking mode
444  * @return
445  *     - ESP_ERR_INVALID_ARG Parameter error
446  *     - ESP_OK Success
447  *     - ESP_ERR_INVALID_STATE Fade function not installed.
448  *     - ESP_FAIL Fade function init error
449  */
450 esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode);
451 
452 /**
453  * @brief LEDC callback registration function
454  * @note  The callback is called from an ISR, it must never attempt to block, and any FreeRTOS API called must be ISR capable.
455  * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
456  * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
457  * @param cbs Group of LEDC callback functions
458  * @param user_arg user registered data for the callback function
459  * @return
460  *     - ESP_ERR_INVALID_ARG Parameter error
461  *     - ESP_OK Success
462  *     - ESP_ERR_INVALID_STATE Fade function not installed.
463  *     - ESP_FAIL Fade function init error
464  */
465 esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg);
466 #ifdef __cplusplus
467 }
468 #endif
469