33
33
34
34
#include <math.h>
35
35
#include "py/mphal.h"
36
- #include "driver/ledc.h"
37
36
#include "esp_err.h"
37
+ #include "driver/ledc.h"
38
+ #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL (5 , 3 , 0 )
39
+ #include "soc/ledc_periph.h"
40
+ #include "esp_private/gpio.h"
41
+ #include "esp_private/esp_gpio_reserve.h"
42
+ #include "soc/io_mux_reg.h"
43
+ #endif
38
44
#include "soc/gpio_sig_map.h"
39
45
#include "esp_clk_tree.h"
40
-
41
46
#include "py/mpprint.h"
42
47
43
- #define debug_printf (...) // mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, ", LINE=%d\n", __LINE__);
48
+ #define debug_printf (...) // mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, " | LINE=%d at %s \n", __LINE__, __FILE__ );
44
49
45
50
// 10-bit user interface resolution compatible with esp8266 PWM.duty()
46
51
#define UI_RES_10_BIT (10)
@@ -87,6 +92,7 @@ typedef struct _machine_pwm_obj_t {
87
92
int duty_ui ; // saved values of UI duty
88
93
int channel_duty ; // saved values of UI duty, calculated to raw channel->duty
89
94
bool output_invert ;
95
+ bool output_invert_prev ;
90
96
} machine_pwm_obj_t ;
91
97
92
98
typedef struct _chans_t {
@@ -213,20 +219,38 @@ static int duty_to_ns(machine_pwm_obj_t *self, int duty) {
213
219
return ((int64_t )duty * 1000000000LL + (int64_t )self -> freq * (int64_t )(MAX_16_DUTY / 2 )) / ((int64_t )self -> freq * (int64_t )MAX_16_DUTY );
214
220
}
215
221
222
+ #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL (5 , 3 , 0 )
223
+ static esp_err_t _ledc_set_pin (int gpio_num , bool out_inv , ledc_mode_t speed_mode , ledc_channel_t channel ) {
224
+ gpio_func_sel (gpio_num , PIN_FUNC_GPIO );
225
+ // reserve the GPIO output path, because we don't expect another peripheral to signal to the same GPIO
226
+ uint64_t old_gpio_rsv_mask = esp_gpio_reserve (BIT64 (gpio_num ));
227
+ // check if the GPIO is already used by others, LEDC signal only uses the output path of the GPIO
228
+ if (old_gpio_rsv_mask & BIT64 (gpio_num )) {
229
+ mp_raise_msg_varg (& mp_type_RuntimeError , MP_ERROR_TEXT ("GPIO %d is not usable, maybe conflict with others" ), gpio_num );
230
+ }
231
+ esp_rom_gpio_connect_out_signal (gpio_num , ledc_periph_signal [speed_mode ].sig_out0_idx + channel , out_inv , 0 );
232
+ return ESP_OK ;
233
+ }
234
+ #endif
235
+
216
236
// Reconfigure PWM pin output as input/output. This allows to read the pin level.
217
237
static void reconfigure_pin (machine_pwm_obj_t * self ) {
218
238
bool invert = self -> output_invert ;
219
239
if (self -> channel_duty && (self -> channel_duty == MAX_timer_duty )) {
220
240
invert = !invert ;
221
241
}
222
242
gpio_set_direction (self -> pin , GPIO_MODE_INPUT_OUTPUT );
243
+ #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL (5 , 3 , 0 )
244
+ _ledc_set_pin (self -> pin , invert , self -> mode , self -> channel );
245
+ #else
223
246
if (self -> mode == LEDC_LOW_SPEED_MODE ) {
224
247
esp_rom_gpio_connect_out_signal (self -> pin , LEDC_LS_SIG_OUT0_IDX + self -> channel , invert , false);
225
248
#if SOC_LEDC_SUPPORT_HS_MODE
226
249
} else if (self -> mode == LEDC_HIGH_SPEED_MODE ) {
227
250
esp_rom_gpio_connect_out_signal (self -> pin , LEDC_HS_SIG_OUT0_IDX + self -> channel , invert , false);
228
251
#endif
229
252
}
253
+ #endif
230
254
}
231
255
232
256
static void apply_duty (machine_pwm_obj_t * self ) {
@@ -242,7 +266,8 @@ static void apply_duty(machine_pwm_obj_t *self) {
242
266
}
243
267
self -> channel_duty = duty >> (UI_RES_16_BIT - timers [self -> mode ][self -> timer ].duty_resolution );
244
268
245
- if ((chans [self -> mode ][self -> channel ].pin == -1 ) || (self -> channel_duty == 0 ) || (self -> channel_duty == MAX_timer_duty )) {
269
+ if ((chans [self -> mode ][self -> channel ].pin == -1 ) || (self -> channel_duty == 0 ) || (self -> channel_duty == MAX_timer_duty ) || (self -> output_invert_prev != self -> output_invert )) {
270
+ self -> output_invert_prev = self -> output_invert ;
246
271
// New PWM assignment
247
272
ledc_channel_config_t cfg = {
248
273
.channel = self -> channel ,
@@ -395,7 +420,7 @@ static void set_freq(machine_pwm_obj_t *self, unsigned int freq) {
395
420
// Check for clock source conflic
396
421
ledc_clk_cfg_t pwm_clk = find_clock_in_use ();
397
422
if ((pwm_clk != LEDC_AUTO_CLK ) && (pwm_clk != timer .clk_cfg )) {
398
- mp_raise_msg_varg (& mp_type_RuntimeError , MP_ERROR_TEXT ("one or more active timers use a different clock source, not supported by the current SoC." ));
423
+ mp_raise_msg (& mp_type_RuntimeError , MP_ERROR_TEXT ("one or more active timers use a different clock source, not supported by the current SoC." ));
399
424
}
400
425
#endif
401
426
@@ -639,6 +664,7 @@ static void self_reset(machine_pwm_obj_t *self) {
639
664
self -> duty_ui = 0 ;
640
665
self -> channel_duty = -1 ;
641
666
self -> output_invert = false;
667
+ self -> output_invert_prev = false;
642
668
self -> light_sleep_enable = false;
643
669
}
644
670
0 commit comments