Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c4b55bb

Browse files
P-R-O-C-H-YSuGliderlucasssvaz
authored
feature(ledc): Add output invert option for LEDC pin + minor fixes (#9257)
* feat(ledc): Add output invert option for LEDC pin + minor fixes * docs(ledc): Document LEDC functions in header file * feat(ledc): Replace log2 with __builtin_ctz * fix(ledc): Fixing free_channel for > 8 supported channels * fix(ledc): Apply suggestions from code review Co-authored-by: Rodrigo Garcia <rodrigo.garcia@espressif.com> * fix(ledc): Added freq check to ledcChangeFrequency * docs(ledc): Fix ledc documentation formatting * docs(migration): Add new functions to the migration guide * docs(ledc): Fix functions name and parameters --------- Co-authored-by: Rodrigo Garcia <rodrigo.garcia@espressif.com> Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>
1 parent 05e2abc commit c4b55bb

File tree

7 files changed

+226
-44
lines changed

7 files changed

+226
-44
lines changed

‎cores/esp32/esp32-hal-ledc.c

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "esp32-hal-ledc.h"
2020
#include "driver/ledc.h"
2121
#include "esp32-hal-periman.h"
22+
#include "soc/gpio_sig_map.h"
23+
#include "esp_rom_gpio.h"
2224

2325
#ifdef SOC_LEDC_SUPPORT_HS_MODE
2426
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM<<1)
@@ -40,7 +42,7 @@ typedef struct {
4042
int used_channels : LEDC_CHANNELS; // Used channels as a bits
4143
} ledc_periph_t;
4244

43-
ledc_periph_t ledc_handle;
45+
ledc_periph_t ledc_handle= {0};
4446

4547
static bool fade_initialized = false;
4648

@@ -58,15 +60,28 @@ static bool ledcDetachBus(void * bus){
5860

5961
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel)
6062
{
61-
if (channel >= LEDC_CHANNELS || resolution > LEDC_MAX_BIT_WIDTH)
62-
{
63-
log_e("Channel %u is not available! (maximum %u) or bit width too big (maximum %u)", channel, LEDC_CHANNELS, LEDC_MAX_BIT_WIDTH);
63+
if(channel >= LEDC_CHANNELS || ledc_handle.used_channels & (1UL << channel)){
64+
log_e("Channel %u is not available (maximum %u) or already used!", channel, LEDC_CHANNELS);
65+
return false;
66+
}
67+
if (freq == 0) {
68+
log_e("LEDC pin %u - frequency can't be zero.", pin);
69+
return false;
70+
}
71+
if (resolution == 0 || resolution > LEDC_MAX_BIT_WIDTH){
72+
log_e("LEDC pin %u - resolution is zero or it is too big (maximum %u)", pin, LEDC_MAX_BIT_WIDTH);
6473
return false;
6574
}
6675

6776
perimanSetBusDeinit(ESP32_BUS_TYPE_LEDC, ledcDetachBus);
6877
ledc_channel_handle_t *bus = (ledc_channel_handle_t*)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
69-
if(bus != NULL && !perimanClearPinBus(pin)){
78+
if(bus != NULL){
79+
log_e("Pin %u is already attached to LEDC (channel %u, resolution %u)", pin, bus->channel, bus->channel_resolution);
80+
return false;
81+
}
82+
83+
if(!perimanClearPinBus(pin)){
84+
log_e("Pin %u is already attached to another bus and failed to detach", pin);
7085
return false;
7186
}
7287

@@ -119,12 +134,12 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
119134

120135
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution)
121136
{
122-
uint8_t free_channel = ~ledc_handle.used_channels & (ledc_handle.used_channels+1);
123-
if (free_channel == 0||resolution>LEDC_MAX_BIT_WIDTH){
124-
log_e("No more LEDC channels available! (maximum %u) or bit width too big (maximum %u)", LEDC_CHANNELS, LEDC_MAX_BIT_WIDTH);
137+
int free_channel = ~ledc_handle.used_channels & (ledc_handle.used_channels+1);
138+
if (free_channel == 0){
139+
log_e("No more LEDC channels available! (maximum is %u channels)", LEDC_CHANNELS);
125140
return false;
126141
}
127-
int channel = log2(free_channel&-free_channel);
142+
uint8_t channel = __builtin_ctz(free_channel); // Convert the free_channel bit to channel number
128143

129144
return ledcAttachChannel(pin, freq, resolution, channel);
130145
}
@@ -239,9 +254,12 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution)
239254
{
240255
ledc_channel_handle_t *bus = (ledc_channel_handle_t*)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
241256
if(bus != NULL){
242-
243-
if(resolution > LEDC_MAX_BIT_WIDTH){
244-
log_e("LEDC resolution too big (maximum %u)", LEDC_MAX_BIT_WIDTH);
257+
if (freq == 0) {
258+
log_e("LEDC pin %u - frequency can't be zero.", pin);
259+
return 0;
260+
}
261+
if (resolution == 0 || resolution > LEDC_MAX_BIT_WIDTH){
262+
log_e("LEDC pin %u - resolution is zero or it is too big (maximum %u)", pin, LEDC_MAX_BIT_WIDTH);
245263
return 0;
246264
}
247265
uint8_t group=(bus->channel/8), timer=((bus->channel/2)%4);
@@ -265,6 +283,21 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution)
265283
return 0;
266284
}
267285

286+
bool ledcOutputInvert(uint8_t pin, bool out_invert)
287+
{
288+
ledc_channel_handle_t *bus = (ledc_channel_handle_t*)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
289+
if(bus != NULL){
290+
gpio_set_level(pin, out_invert);
291+
#ifdef SOC_LEDC_SUPPORT_HS_MODE
292+
esp_rom_gpio_connect_out_signal(pin, ((bus->channel/8 == 0) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX) + ((bus->channel)%8), out_invert, 0);
293+
#else
294+
esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + ((bus->channel)%8), out_invert, 0);
295+
#endif
296+
return true;
297+
}
298+
return false;
299+
}
300+
268301
static IRAM_ATTR bool ledcFnWrapper(const ledc_cb_param_t *param, void *user_arg)
269302
{
270303
if (param->event == LEDC_FADE_END_EVT) {

‎cores/esp32/esp32-hal-ledc.h

Lines changed: 140 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,150 @@ typedef struct {
4545
#endif
4646
} ledc_channel_handle_t;
4747

48-
//channel 0-15 resolution 1-16bits freq limits depend on resolution
49-
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution);
50-
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel);
51-
bool ledcWrite(uint8_t pin, uint32_t duty);
52-
uint32_t ledcWriteTone(uint8_t pin, uint32_t freq);
53-
uint32_t ledcWriteNote(uint8_t pin, note_t note, uint8_t octave);
54-
uint32_t ledcRead(uint8_t pin);
55-
uint32_t ledcReadFreq(uint8_t pin);
56-
bool ledcDetach(uint8_t pin);
57-
uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution);
48+
/**
49+
* @brief Attach a pin to the LEDC driver, with a given frequency and resolution.
50+
* Channel is automatically assigned.
51+
*
52+
* @param pin GPIO pin
53+
* @param freq frequency of PWM signal
54+
* @param resolution resolution for LEDC pin
55+
*
56+
* @return true if configuration is successful and pin was successfully attached, false otherwise.
57+
*/
58+
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution);
59+
60+
/**
61+
* @brief Attach a pin to the LEDC driver, with a given frequency, resolution and channel.
62+
*
63+
* @param pin GPIO pin
64+
* @param freq frequency of PWM signal
65+
* @param resolution resolution for LEDC pin
66+
* @param channel LEDC channel to attach to
67+
*
68+
* @return true if configuration is successful and pin was successfully attached, false otherwise.
69+
*/
70+
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel);
71+
72+
/**
73+
* @brief Set the duty cycle of a given pin.
74+
*
75+
* @param pin GPIO pin
76+
* @param duty duty cycle to set
77+
*
78+
* @return true if duty cycle was successfully set, false otherwise.
79+
*/
80+
bool ledcWrite(uint8_t pin, uint32_t duty);
81+
82+
/**
83+
* @brief Sets the duty to 50 % PWM tone on selected frequency.
84+
*
85+
* @param pin GPIO pin
86+
* @param freq select frequency of pwm signal. If frequency is 0, duty will be set to 0.
87+
*
88+
* @return frequency if tone was successfully set.
89+
* If ``0`` is returned, error occurs and LEDC pin was not configured.
90+
*/
91+
uint32_t ledcWriteTone(uint8_t pin, uint32_t freq);
92+
93+
/**
94+
* @brief Sets the LEDC pin to specific note.
95+
*
96+
* @param pin GPIO pin
97+
* @param note select note to be set (NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_E, NOTE_F, NOTE_Fs, NOTE_G, NOTE_Gs, NOTE_A, NOTE_Bb, NOTE_B).
98+
* @param octave select octave for note.
99+
*
100+
* @return frequency if note was successfully set.
101+
* If ``0`` is returned, error occurs and LEDC pin was not configured.
102+
*/
103+
uint32_t ledcWriteNote(uint8_t pin, note_t note, uint8_t octave);
104+
105+
/**
106+
* @brief Read the duty cycle of a given LEDC pin.
107+
*
108+
* @param pin GPIO pin
109+
*
110+
* @return duty cycle of selected LEDC pin.
111+
*/
112+
uint32_t ledcRead(uint8_t pin);
113+
114+
/**
115+
* @brief Read the frequency of a given LEDC pin.
116+
*
117+
* @param pin GPIO pin
118+
*
119+
* @return frequency of selected LEDC pin.
120+
*/
121+
uint32_t ledcReadFreq(uint8_t pin);
122+
123+
/**
124+
* @brief Detach a pin from the LEDC driver.
125+
*
126+
* @param pin GPIO pin
127+
*
128+
* @return true if pin was successfully detached, false otherwise.
129+
*/
130+
bool ledcDetach(uint8_t pin);
131+
132+
/**
133+
* @brief Change the frequency and resolution of a given LEDC pin.
134+
*
135+
* @param pin GPIO pin
136+
* @param freq frequency of PWM signal
137+
* @param resolution resolution for LEDC pin
138+
*
139+
* @return frequency configured for the LEDC channel.
140+
* If ``0`` is returned, error occurs and LEDC pin was not configured.
141+
*/
142+
uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution);
143+
144+
/**
145+
* @brief Sets inverting of the output signal for a given LEDC pin.
146+
*
147+
* @param pin GPIO pin
148+
* @param out_invert select, if output should be inverted (true = inverting output).
149+
*
150+
* @return true if output inverting was successfully set, false otherwise.
151+
*/
152+
bool ledcOutputInvert(uint8_t pin, bool out_invert);
58153

59154
//Fade functions
155+
/**
156+
* @brief Setup and start a fade on a given LEDC pin.
157+
*
158+
* @param pin GPIO pin
159+
* @param start_duty initial duty cycle of the fade
160+
* @param target_duty target duty cycle of the fade
161+
* @param max_fade_time_ms maximum fade time in milliseconds
162+
*
163+
* @return true if fade was successfully set and started, false otherwise.
164+
*/
60165
bool ledcFade(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms);
166+
167+
/**
168+
* @brief Setup and start a fade on a given LEDC pin with a callback function.
169+
*
170+
* @param pin GPIO pin
171+
* @param start_duty initial duty cycle of the fade
172+
* @param target_duty target duty cycle of the fade
173+
* @param max_fade_time_ms maximum fade time in milliseconds
174+
* @param userFunc callback function to be called after fade is finished
175+
*
176+
* @return true if fade was successfully set and started, false otherwise.
177+
*/
61178
bool ledcFadeWithInterrupt(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void));
179+
180+
/**
181+
* @brief Setup and start a fade on a given LEDC pin with a callback function and argument.
182+
*
183+
* @param pin GPIO pin
184+
* @param start_duty initial duty cycle of the fade
185+
* @param target_duty target duty cycle of the fade
186+
* @param max_fade_time_ms maximum fade time in milliseconds
187+
* @param userFunc callback function to be called after fade is finished
188+
* @param arg argument to be passed to the callback function
189+
*
190+
* @return true if fade was successfully set and started, false otherwise.
191+
*/
62192
bool ledcFadeWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void*), void * arg);
63193

64194
#ifdef __cplusplus

‎cores/esp32/io_pin_remap.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,16 @@ int8_t gpioNumberToDigitalPin(int8_t gpioNumber);
5353
#define i2cSlaveInit(num, sda, scl, slaveID, frequency, rx_len, tx_len) i2cSlaveInit(num, digitalPinToGPIONumber(sda), digitalPinToGPIONumber(scl), slaveID, frequency, rx_len, tx_len)
5454

5555
// cores/esp32/esp32-hal-ledc.h
56-
#define ledcAttach(pin, freq, resolution) ledcAttach(digitalPinToGPIONumber(pin), freq, resolution)
57-
#define ledcWrite(pin, duty) ledcWrite(digitalPinToGPIONumber(pin), duty)
58-
#define ledcWriteTone(pin, freq) ledcWriteTone(digitalPinToGPIONumber(pin), freq)
59-
#define ledcWriteNote(pin, note, octave) ledcWriteNote(digitalPinToGPIONumber(pin), note, octave)
60-
#define ledcRead(pin) ledcRead(digitalPinToGPIONumber(pin))
61-
#define ledcReadFreq(pin) ledcReadFreq(digitalPinToGPIONumber(pin))
62-
#define ledcDetach(pin) ledcDetach(digitalPinToGPIONumber(pin))
63-
#define ledcChangeFrequency(pin, freq, resolution) ledcChangeFrequency(digitalPinToGPIONumber(pin), freq, resolution)
56+
#define ledcAttach(pin, freq, resolution) ledcAttach(digitalPinToGPIONumber(pin), freq, resolution)
57+
#define ledcAttachChannel(pin, freq, resolution, channel) ledcAttachChannel(digitalPinToGPIONumber(pin), freq, resolution, channel)
58+
#define ledcWrite(pin, duty) ledcWrite(digitalPinToGPIONumber(pin), duty)
59+
#define ledcWriteTone(pin, freq) ledcWriteTone(digitalPinToGPIONumber(pin), freq)
60+
#define ledcWriteNote(pin, note, octave) ledcWriteNote(digitalPinToGPIONumber(pin), note, octave)
61+
#define ledcRead(pin) ledcRead(digitalPinToGPIONumber(pin))
62+
#define ledcReadFreq(pin) ledcReadFreq(digitalPinToGPIONumber(pin))
63+
#define ledcDetach(pin) ledcDetach(digitalPinToGPIONumber(pin))
64+
#define ledcChangeFrequency(pin, freq, resolution) ledcChangeFrequency(digitalPinToGPIONumber(pin), freq, resolution)
65+
#define ledcOutputInvert(pin, out_invert) ledcOutputInvert(digitalPinToGPIONumber(pin), out_invert)
6466

6567
#define ledcFade(pin, start_duty, target_duty, max_fade_time_ms) ledcFade(digitalPinToGPIONumber(pin), start_duty, target_duty, max_fade_time_ms)
6668
#define ledcFadeWithInterrupt(pin, start_duty, target_duty, max_fade_time_ms, userFunc) ledcFadeWithInterrupt(digitalPinToGPIONumber(pin), start_duty, target_duty, max_fade_time_ms, userFunc)

‎docs/en/api/ledc.rst

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,18 @@ Arduino-ESP32 LEDC API
2626
ledcAttach
2727
**********
2828

29-
This function is used to setup LEDC pin with given frequency and resolution.
30-
LEDC channel will be selected automatically.
29+
This function is used to setup LEDC pin with given frequency and resolution. LEDC channel will be selected automatically.
3130

3231
.. code-block:: arduino
3332
3433
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution);
3534
3635
* ``pin`` select LEDC pin.
3736
* ``freq`` select frequency of pwm.
38-
* ``resolution`` select resolution for LEDC channel.
39-
37+
* ``resolution`` select resolution for LEDC channel.
38+
4039
* range is 1-14 bits (1-20 bits for ESP32).
41-
40+
4241
This function will return ``true`` if configuration is successful.
4342
If ``false`` is returned, error occurs and LEDC channel was not configured.
4443

@@ -49,15 +48,16 @@ This function is used to setup LEDC pin with given frequency, resolution and cha
4948

5049
.. code-block:: arduino
5150
52-
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel);
51+
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, int8_t channel);
5352
5453
* ``pin`` select LEDC pin.
5554
* ``freq`` select frequency of pwm.
56-
* ``resolution`` select resolution for LEDC channel.
57-
* ``channel`` select LEDC channel.
58-
55+
* ``resolution`` select resolution for LEDC channel.
56+
5957
* range is 1-14 bits (1-20 bits for ESP32).
60-
58+
59+
* ``channel`` select LEDC channel.
60+
6161
This function will return ``true`` if configuration is successful.
6262
If ``false`` is returned, error occurs and LEDC channel was not configured.
6363

@@ -171,6 +171,21 @@ This function is used to set frequency for the LEDC pin.
171171
This function will return ``frequency`` configured for the LEDC channel.
172172
If ``0`` is returned, error occurs and the LEDC channel frequency was not set.
173173

174+
ledcOutputInvert
175+
****************
176+
177+
This function is used to set inverting output for the LEDC pin.
178+
179+
.. code-block:: arduino
180+
181+
bool ledcOutputInvert(uint8_t pin, bool out_invert);
182+
183+
* ``pin`` select LEDC pin.
184+
* ``out_invert`` select, if output should be inverted (true = inverting output).
185+
186+
This function returns ``true`` if setting inverting output was successful.
187+
If ``false`` is returned, an error occurred and the inverting output was not set.
188+
174189
ledcFade
175190
********
176191

‎docs/en/migration_guides/2.x_to_3.0.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ New APIs
6363
********
6464

6565
* ``ledcAttach`` used to set up the LEDC pin (merged ``ledcSetup`` and ``ledcAttachPin`` functions).
66-
* ``timerGetFrequency`` used to get the actual frequency of the timer.
67-
* ``timerAttachInterruptArg`` used to attach the interrupt to a timer using arguments.
66+
* ``ledcOutputInvert`` used to attach the interrupt to a timer using arguments.
67+
* ``ledcFade`` used to set up and start a fade on a given LEDC pin.
68+
* ``ledcFadeWithInterrupt`` used to set up and start a fade on a given LEDC pin with an interrupt.
69+
* ``ledcFadeWithInterruptArg`` used to set up and start a fade on a given LEDC pin with an interrupt using arguments.
6870

6971
Changes in APIs
7072
***************

‎libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void setup() {
3333
Serial.begin(115200);
3434
while(!Serial) delay(10);
3535

36-
// Setup timer and attach timer to a led pins
36+
// Setup timer with given frequency, resolution and attach it to a led pin with auto-selected channel
3737
ledcAttach(LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT);
3838

3939
// Setup and start fade on led (duty from 0 to 4095)

‎libraries/ESP32/examples/AnalogOut/ledcWrite_RGB/ledcWrite_RGB.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ void setup()
2626
delay(10);
2727

2828
// Initialize pins as LEDC channels
29-
// resolution 1-16 bits, freq limits depend on resolution
29+
// resolution 1-16 bits, freq limits depend on resolution, channel is automatically selected
3030
ledcAttach(ledR, 12000, 8); // 12 kHz PWM, 8-bit resolution
3131
ledcAttach(ledG, 12000, 8);
3232
ledcAttach(ledB, 12000, 8);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /