Skip to content

Commit c15582b

Browse files
committed
feat(ledc): Add output invert option for LEDC pin + minor fixes
1 parent bc769fd commit c15582b

File tree

6 files changed

+70
-29
lines changed

6 files changed

+70
-29
lines changed

Diff for: cores/esp32/esp32-hal-ledc.c

+36-9
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,25 @@ 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+
68+
if (resolution > LEDC_MAX_BIT_WIDTH){
69+
log_e("LEDC resolution too big (maximum %u)", LEDC_MAX_BIT_WIDTH);
6470
return false;
6571
}
6672

6773
perimanSetBusDeinit(ESP32_BUS_TYPE_LEDC, ledcDetachBus);
6874
ledc_channel_handle_t *bus = (ledc_channel_handle_t*)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
69-
if(bus != NULL && !perimanClearPinBus(pin)){
75+
if(bus != NULL){
76+
log_e("Pin %u is already attached to LEDC (channel %u, resolution %u)", pin, bus->channel, bus->channel_resolution);
77+
return false;
78+
}
79+
80+
if(!perimanClearPinBus(pin)){
81+
log_e("Pin %u is already attached to another bus and failed to detach", pin);
7082
return false;
7183
}
7284

@@ -120,11 +132,11 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
120132
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution)
121133
{
122134
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);
135+
if (free_channel == 0){
136+
log_e("No more LEDC channels available! (maximum is %u channels)", LEDC_CHANNELS);
125137
return false;
126138
}
127-
int channel = log2(free_channel & -free_channel);
139+
uint8_t channel = log2(free_channel & -free_channel);
128140

129141
return ledcAttachChannel(pin, freq, resolution, channel);
130142
}
@@ -265,6 +277,21 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution)
265277
return 0;
266278
}
267279

280+
bool ledcOutputInvert(uint8_t pin, bool out_invert)
281+
{
282+
ledc_channel_handle_t *bus = (ledc_channel_handle_t*)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
283+
if(bus != NULL){
284+
gpio_set_level(pin, out_invert);
285+
#ifdef SOC_LEDC_SUPPORT_HS_MODE
286+
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);
287+
#else
288+
esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + ((bus->channel)%8), out_invert, 0);
289+
#endif
290+
return true;
291+
}
292+
return false;
293+
}
294+
268295
static IRAM_ATTR bool ledcFnWrapper(const ledc_cb_param_t *param, void *user_arg)
269296
{
270297
if (param->event == LEDC_FADE_END_EVT) {
@@ -373,7 +400,7 @@ void analogWrite(uint8_t pin, int value) {
373400
if (pin < SOC_GPIO_PIN_COUNT) {
374401
ledc_channel_handle_t *bus = (ledc_channel_handle_t*)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
375402
if(bus == NULL && perimanClearPinBus(pin)){
376-
if(ledcAttach(pin, analog_frequency, analog_resolution) == 0){
403+
if(ledcAttach(pin, analog_frequency, analog_resolution, LEDC_CHANNEL_AUTO) == 0){
377404
log_e("analogWrite setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency");
378405
return;
379406
}

Diff for: cores/esp32/esp32-hal-ledc.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ typedef struct {
4545
#endif
4646
} ledc_channel_handle_t;
4747

48-
//channel 0-15 resolution 1-16bits freq limits depend on resolution
4948
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution);
5049
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel);
5150
bool ledcWrite(uint8_t pin, uint32_t duty);
@@ -55,6 +54,7 @@ uint32_t ledcRead(uint8_t pin);
5554
uint32_t ledcReadFreq(uint8_t pin);
5655
bool ledcDetach(uint8_t pin);
5756
uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution);
57+
bool ledcOutputInvert(uint8_t pin, bool out_invert);
5858

5959
//Fade functions
6060
bool ledcFade(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms);

Diff for: cores/esp32/io_pin_remap.h

+10-8
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)

Diff for: docs/en/api/ledc.rst

+21-9
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,17 @@ 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
34-
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution);
33+
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution, int8_t channel);
3534
3635
* ``pin`` select LEDC pin.
3736
* ``freq`` select frequency of pwm.
3837
* ``resolution`` select resolution for LEDC channel.
39-
4038
* range is 1-14 bits (1-20 bits for ESP32).
41-
39+
4240
This function will return ``true`` if configuration is successful.
4341
If ``false`` is returned, error occurs and LEDC channel was not configured.
4442

@@ -49,15 +47,14 @@ This function is used to setup LEDC pin with given frequency, resolution and cha
4947

5048
.. code-block:: arduino
5149
52-
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel);
50+
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution, int8_t channel);
5351
5452
* ``pin`` select LEDC pin.
5553
* ``freq`` select frequency of pwm.
5654
* ``resolution`` select resolution for LEDC channel.
57-
* ``channel`` select LEDC channel.
58-
5955
* range is 1-14 bits (1-20 bits for ESP32).
60-
56+
* ``channel`` select LEDC channel.
57+
6158
This function will return ``true`` if configuration is successful.
6259
If ``false`` is returned, error occurs and LEDC channel was not configured.
6360

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

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

Diff for: libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino

+1-1
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)

Diff for: libraries/ESP32/examples/AnalogOut/ledcWrite_RGB/ledcWrite_RGB.ino

+1-1
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)