diff options
| -rw-r--r-- | ports/esp32/machine_pwm.c | 50 |
1 files changed, 16 insertions, 34 deletions
diff --git a/ports/esp32/machine_pwm.c b/ports/esp32/machine_pwm.c index 71402e1c4..61efdfa18 100644 --- a/ports/esp32/machine_pwm.c +++ b/ports/esp32/machine_pwm.c @@ -34,6 +34,7 @@ #include "py/mphal.h" #include "driver/ledc.h" #include "esp_err.h" +#include "esp_clk_tree.h" #include "soc/gpio_sig_map.h" #define PWM_DBG(...) @@ -209,51 +210,32 @@ static void configure_channel(machine_pwm_obj_t *self) { static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_config_t *timer) { if (freq != timer->freq_hz) { - // Find the highest bit resolution for the requested frequency - unsigned int i = APB_CLK_FREQ; // 80 MHz - #if SOC_LEDC_SUPPORT_REF_TICK - if (freq < EMPIRIC_FREQ) { - i = REF_CLK_FREQ; // 1 MHz - } - #endif - - int divider = (i + freq / 2) / freq; // rounded - if (divider == 0) { - divider = 1; - } - float f = (float)i / divider; // actual frequency - if (f <= 1.0) { - f = 1.0; - } - i = (unsigned int)roundf((float)i / f); - - unsigned int res = 0; - for (; i > 1; i >>= 1) { - ++res; - } - if (res == 0) { - res = 1; - } else if (res > HIGHEST_PWM_RES) { - // Limit resolution to HIGHEST_PWM_RES to match units of our duty - res = HIGHEST_PWM_RES; - } - - // Configure the new resolution and frequency - timer->duty_resolution = res; + // Configure the new frequency and resolution timer->freq_hz = freq; - #if SOC_LEDC_SUPPORT_XTAL_CLOCK + + #if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + timer->clk_cfg = LEDC_USE_PLL_DIV_CLK; + #elif SOC_LEDC_SUPPORT_APB_CLOCK + timer->clk_cfg = LEDC_USE_APB_CLK; + #elif SOC_LEDC_SUPPORT_XTAL_CLOCK timer->clk_cfg = LEDC_USE_XTAL_CLK; #else - timer->clk_cfg = LEDC_USE_APB_CLK; + #error No supported PWM / LEDC clocks. #endif #if SOC_LEDC_SUPPORT_REF_TICK if (freq < EMPIRIC_FREQ) { timer->clk_cfg = LEDC_USE_REF_TICK; } #endif + uint32_t src_clk_freq = 0; + esp_err_t err = esp_clk_tree_src_get_freq_hz(timer->clk_cfg, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_freq); + if (err != ESP_OK) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unable to query source clock frequency %d"), (int)timer->clk_cfg); + } + timer->duty_resolution = ledc_find_suitable_duty_resolution(src_clk_freq, timer->freq_hz); // Set frequency - esp_err_t err = ledc_timer_config(timer); + err = ledc_timer_config(timer); if (err != ESP_OK) { if (err == ESP_FAIL) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unreachable frequency %d"), freq); |
