Skip to content
61 changes: 38 additions & 23 deletions cores/esp32/esp32-hal-ledc.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,12 @@ bool ledcWrite(uint8_t pin, uint32_t duty) {
if (bus != NULL) {

uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);
uint32_t max_duty = (1 << bus->channel_resolution); // Max LEDC duty

//Fixing if all bits in resolution is set = LEDC FULL ON
uint32_t max_duty = (1 << bus->channel_resolution) - 1;

if ((duty == max_duty) && (max_duty != 1)) {
duty = max_duty + 1;
if (duty > max_duty) {
log_w("Target duty %d was adjusted to the maximum duty %d", duty, max_duty);
duty = max_duty;
}

ledc_set_duty(group, channel, duty);
ledc_update_duty(group, channel);

Expand All @@ -210,13 +208,12 @@ bool ledcWriteChannel(uint8_t channel, uint32_t duty) {
//Fixing if all bits in resolution is set = LEDC FULL ON
uint32_t resolution = 0;
ledc_ll_get_duty_resolution(LEDC_LL_GET_HW(), group, timer, &resolution);
uint32_t max_duty = (1 << resolution); // Max LEDC duty

uint32_t max_duty = (1 << resolution) - 1;

if ((duty == max_duty) && (max_duty != 1)) {
duty = max_duty + 1;
if (duty > max_duty) {
log_w("Target duty %d was adjusted to the maximum duty %d", duty, max_duty);
duty = max_duty;
}

ledc_set_duty(group, channel, duty);
ledc_update_duty(group, channel);

Expand Down Expand Up @@ -265,15 +262,16 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
bus->channel_resolution = 10;

uint32_t res_freq = ledc_get_freq(group, timer);
ledcWrite(pin, 0x1FF);
ledcWrite(pin, 0x200); // LEDC 50% duty is 2^10 / 2 = 0x200
return res_freq;
}
return 0;
}

uint32_t ledcWriteNote(uint8_t pin, note_t note, uint8_t octave) {
const uint16_t noteFrequencyBase[12] = {// C C# D Eb E F F# G G# A Bb B
4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902
const uint16_t noteFrequencyBase[12] = {
// C C# D Eb E F F# G G# A Bb B
4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902
};

if (octave > 8 || note >= NOTE_MAX) {
Expand Down Expand Up @@ -379,6 +377,21 @@ static bool ledcFadeConfig(uint8_t pin, uint32_t start_duty, uint32_t target_dut
#endif
uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);

uint32_t max_duty = (1 << bus->channel_resolution); // Max LEDC duty

if (target_duty > max_duty) {
log_w("Final duty %d was adjusted to the maximum duty %d", target_duty, max_duty);
target_duty = max_duty;
}
if (start_duty > max_duty) {
log_w("Starting duty %d was adjusted to the maximum duty %d", start_duty, max_duty);
start_duty = max_duty;
}
if (start_duty >= target_duty) {
log_e("Starting duty must be lower than the final duty");
return false;
}

// Initialize fade service.
if (!fade_initialized) {
ledc_fade_func_install(0);
Expand All @@ -391,15 +404,6 @@ static bool ledcFadeConfig(uint8_t pin, uint32_t start_duty, uint32_t target_dut
ledc_cbs_t callbacks = {.fade_cb = ledcFnWrapper};
ledc_cb_register(group, channel, &callbacks, (void *)bus);

//Fixing if all bits in resolution is set = LEDC FULL ON
uint32_t max_duty = (1 << bus->channel_resolution) - 1;

if ((target_duty == max_duty) && (max_duty != 1)) {
target_duty = max_duty + 1;
} else if ((start_duty == max_duty) && (max_duty != 1)) {
start_duty = max_duty + 1;
}

#if SOC_LEDC_SUPPORT_FADE_STOP
ledc_fade_stop(group, channel);
#endif
Expand Down Expand Up @@ -446,6 +450,17 @@ void analogWrite(uint8_t pin, int value) {
return;
}
}
// Arduino API says that duty goes from 0 to (2^resolution) - 1
// But LEDC works with duty from 0 to (2^resolution)
// Therefore, it will adjust Arduino MAX Duty to be the LEDC MAx Duty
uint32_t max_duty = (1 << bus->channel_resolution) - 1;
if (value < 0 || value > max_duty) {
log_e("Duty is out of range. Valid duty range for pin d is 0 to %d", pin, max_duty);
return;
}
if (value == max_duty) {
value = max_duty + 1;
}
ledcWrite(pin, value);
}
}
Expand Down
Loading