|
34 | 34 | #include "py/mphal.h"
|
35 | 35 | #include "driver/ledc.h"
|
36 | 36 | #include "esp_err.h"
8000
|
| 37 | +#include "esp_clk_tree.h" |
37 | 38 | #include "soc/gpio_sig_map.h"
|
38 | 39 |
|
39 | 40 | #define PWM_DBG(...)
|
@@ -209,51 +210,32 @@ static void configure_channel(machine_pwm_obj_t *self) {
|
209 | 210 |
|
210 | 211 | static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_config_t *timer) {
|
211 | 212 | if (freq != timer->freq_hz) {
|
212 |
| - // Find the highest bit resolution for the requested frequency |
213 |
| - unsigned int i = APB_CLK_FREQ; // 80 MHz |
214 |
| - #if SOC_LEDC_SUPPORT_REF_TICK |
215 |
| - if (freq < EMPIRIC_FREQ) { |
216 |
| - i = REF_CLK_FREQ; // 1 MHz |
217 |
| - } |
218 |
| - #endif |
219 |
| - |
220 |
| - int divider = (i + freq / 2) / freq; // rounded |
221 |
| - if (divider == 0) { <
10000
div aria-hidden="true" style="left:-2px" class="position-absolute top-0 d-flex user-select-none DiffLineTableCellParts-module__in-progress-comment-indicator--hx3m3"> |
222 |
| - divider = 1; |
223 |
| - } |
224 |
| - float f = (float)i / divider; // actual frequency |
225 |
| - if (f <= 1.0) { |
226 |
| - f = 1.0; |
227 |
| - } |
228 |
| - i = (unsigned int)roundf((float)i / f); |
229 |
| - |
230 |
| - unsigned int res = 0; |
231 |
| - for (; i > 1; i >>= 1) { |
232 |
| - ++res; |
233 |
| - } |
234 |
| - if (res == 0) { |
235 |
| - res = 1; |
236 |
| - } else if (res > HIGHEST_PWM_RES) { |
237 |
| - // Limit resolution to HIGHEST_PWM_RES to match units of our duty |
238 |
| - res = HIGHEST_PWM_RES; |
239 |
| - } |
240 |
| - |
241 |
| - // Configure the new resolution and frequency |
242 |
| - timer->duty_resolution = res; |
| 213 | + // Configure the new frequency and resolution |
243 | 214 | timer->freq_hz = freq;
|
244 |
| - #if SOC_LEDC_SUPPORT_XTAL_CLOCK |
| 215 | + |
| 216 | + #if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK |
| 217 | + timer->clk_cfg = LEDC_USE_PLL_DIV_CLK; |
| 218 | + #elif SOC_LEDC_SUPPORT_APB_CLOCK |
| 219 | + timer->clk_cfg = LEDC_USE_APB_CLK; |
| 220 | + #elif SOC_LEDC_SUPPORT_XTAL_CLOCK |
245 | 221 | timer->clk_cfg = LEDC_USE_XTAL_CLK;
|
246 | 222 | #else
|
247 |
| - timer->clk_cfg = LEDC_USE_APB_CLK; |
| 223 | + #error No supported PWM / LEDC clocks. |
248 | 224 | #endif
|
249 | 225 | #if SOC_LEDC_SUPPORT_REF_TICK
|
250 | 226 | if (freq < EMPIRIC_FREQ) {
|
251 | 227 | timer->clk_cfg = LEDC_USE_REF_TICK;
|
252 | 228 | }
|
253 | 229 | #endif
|
| 230 | + uint32_t src_clk_freq = 0; |
| 231 | + esp_err_t err = esp_clk_tree_src_get_freq_hz(timer->clk_cfg, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_freq); |
| 232 | + if (err != ESP_OK) { |
| 233 | + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unable to query source clock frequency %d"), (int)timer->clk_cfg); |
| 234 | + } |
| 235 | + timer->duty_resolution = ledc_find_suitable_duty_resolution(src_clk_freq, timer->freq_hz); |
254 | 236 |
|
255 | 237 | // Set frequency
|
256 |
| - esp_err_t err = ledc_timer_config(timer); |
| 238 | + err = ledc_timer_config(timer); |
257 | 239 | if (err != ESP_OK) {
|
258 | 240 | if (err == ESP_FAIL) {
|
259 | 241 | mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unreachable frequency %d"), freq);
|
|
0 commit comments