36
36
#include "esp_err.h"
37
37
#include "driver/ledc.h"
38
38
#include "soc/gpio_sig_map.h"
39
+ #include "soc/ledc_periph.h"
39
40
#include "esp_clk_tree.h"
40
41
#include "py/mpprint.h"
41
42
42
43
#define debug_printf (...) // mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, " | %d at %s\n", __LINE__, __FILE__);
44
+ #define FADE 1
43
45
44
46
// 10-bit user interface resolution compatible with esp8266 PWM.duty()
45
47
#define UI_RES_10_BIT (10)
@@ -220,14 +222,10 @@ static void reconfigure_pin(machine_pwm_obj_t *self) {
220
222
if (self -> channel_duty == MAX_timer_duty ) {
221
223
invert = !invert ;
222
224
}
225
+ #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL (5 , 4 , 0 )
223
226
gpio_set_direction (self -> pin , GPIO_MODE_INPUT_OUTPUT );
224
- if (self -> mode == LEDC_LOW_SPEED_MODE ) {
225
- esp_rom_gpio_connect_out_signal (self -> pin , LEDC_LS_SIG_OUT0_IDX + self -> channel , invert , false);
226
- #if SOC_LEDC_SUPPORT_HS_MODE
227
- } else if (self -> mode == LEDC_HIGH_SPEED_MODE ) {
228
- esp_rom_gpio_connect_out_signal (self -> pin , LEDC_HS_SIG_OUT0_IDX + self -> channel , invert , false);
229
227
#endif
230
- }
228
+ esp_rom_gpio_connect_out_signal ( self -> pin , ledc_periph_signal [ self -> mode ]. sig_out0_idx + self -> channel , invert , 0 );
231
229
}
232
230
233
231
static void apply_duty (machine_pwm_obj_t * self ) {
@@ -253,6 +251,7 @@ static void apply_duty(machine_pwm_obj_t *self) {
253
251
.intr_type = LEDC_INTR_DISABLE ,
254
252
.speed_mode = self -> mode ,
255
253
.timer_sel = self -> timer ,
254
+ .hpoint = 0 ,
256
255
.flags .output_invert = self -> output_invert ,
257
256
};
258
257
self -> output_is_inverted = false;
@@ -267,10 +266,13 @@ static void apply_duty(machine_pwm_obj_t *self) {
267
266
check_esp_err (gpio_sleep_sel_dis (self -> pin ));
268
267
chans [self -> mode ][self -> channel ].light_sleep_enable = true;
269
268
}
270
- check_esp_err (ledc_bind_channel_timer (self -> mode , self -> channel , self -> timer ));
271
269
} else {
270
+ #if FADE
271
+ check_esp_err (ledc_set_duty_and_update (self -> mode , self -> channel , self -> channel_duty , 0 ));
272
+ #else
272
273
check_esp_err (ledc_set_duty (self -> mode , self -> channel , self -> channel_duty ));
273
274
check_esp_err (ledc_update_duty (self -> mode , self -> channel ));
275
+ #endif
274
276
}
275
277
reconfigure_pin (self );
276
278
register_channel (self -> mode , self -> channel , self -> pin , self -> timer );
@@ -282,6 +284,16 @@ static uint32_t find_suitable_duty_resolution(uint32_t src_clk_freq, uint32_t ti
282
284
// limit resolution to user interface
283
285
resolution = UI_RES_16_BIT ;
284
286
}
287
+ /*
288
+ // Uncomment if duty is 65536!
289
+ // Note: On ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2, ESP32C6, ESP32H2, ESP32P4, due to a hardware bug,
290
+ // 100% duty cycle (i.e. 2**duty_res) is not reachable when the binded timer selects the maximum duty
291
+ // resolution. For example, the max duty resolution on ESP32C3 is 14-bit width, then set duty to (2**14)
292
+ // will mess up the duty calculation in hardware.
293
+ if (resolution >= SOC_LEDC_TIMER_BIT_WIDTH)
294
+ resolution -= 1;
295
+ }
296
+ */
285
297
return resolution ;
286
298
}
287
299
@@ -656,6 +668,9 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type,
656
668
// start the PWM subsystem if it's not already running
657
669
if (!pwm_inited ) {
658
670
pwm_init ();
671
+ #if FADE
672
+ ledc_fade_func_install (0 );
673
+ #endif
659
674
pwm_inited = true;
660
675
}
661
676
0 commit comments