Skip to content

feat(ledc): max resolution review #11226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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_w("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