Skip to content

Commit 33ab28f

Browse files
committed
esp32/machine_pwm.c: Fix invert param.
Signed-off-by: Ihor Nehrutsa <[email protected]>
1 parent c546bc6 commit 33ab28f

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

ports/esp32/machine_pwm.c

+31-5
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,19 @@
3333

3434
#include <math.h>
3535
#include "py/mphal.h"
36-
#include "driver/ledc.h"
3736
#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
3844
#include "soc/gpio_sig_map.h"
3945
#include "esp_clk_tree.h"
40-
4146
#include "py/mpprint.h"
4247

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__);
4449

4550
// 10-bit user interface resolution compatible with esp8266 PWM.duty()
4651
#define UI_RES_10_BIT (10)
@@ -87,6 +92,7 @@ typedef struct _machine_pwm_obj_t {
8792
int duty_ui; // saved values of UI duty
8893
int channel_duty; // saved values of UI duty, calculated to raw channel->duty
8994
bool output_invert;
95+
bool output_invert_prev;
9096
} machine_pwm_obj_t;
9197

9298
typedef struct _chans_t {
@@ -213,20 +219,38 @@ static int duty_to_ns(machine_pwm_obj_t *self, int duty) {
213219
return ((int64_t)duty * 1000000000LL + (int64_t)self->freq * (int64_t)(MAX_16_DUTY / 2)) / ((int64_t)self->freq * (int64_t)MAX_16_DUTY);
214220
}
215221

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+
216236
// Reconfigure PWM pin output as input/output. This allows to read the pin level.
217237
static void reconfigure_pin(machine_pwm_obj_t *self) {
218238
bool invert = self->output_invert;
219239
if (self->channel_duty && (self->channel_duty == MAX_timer_duty)) {
220240
invert = !invert;
221241
}
222242
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
223246
if (self->mode == LEDC_LOW_SPEED_MODE) {
224247
esp_rom_gpio_connect_out_signal(self->pin, LEDC_LS_SIG_OUT0_IDX + self->channel, invert, false);
225248
#if SOC_LEDC_SUPPORT_HS_MODE
226249
} else if (self->mode == LEDC_HIGH_SPEED_MODE) {
227250
esp_rom_gpio_connect_out_signal(self->pin, LEDC_HS_SIG_OUT0_IDX + self->channel, invert, false);
228251
#endif
229252
}
253+
#endif
230254
}
231255

232256
static void apply_duty(machine_pwm_obj_t *self) {
@@ -242,7 +266,8 @@ static void apply_duty(machine_pwm_obj_t *self) {
242266
}
243267
self->channel_duty = duty >> (UI_RES_16_BIT - timers[self->mode][self->timer].duty_resolution);
244268

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;
246271
// New PWM assignment
247272
ledc_channel_config_t cfg = {
248273
.channel = self->channel,
@@ -395,7 +420,7 @@ static void set_freq(machine_pwm_obj_t *self, unsigned int freq) {
395420
// Check for clock source conflic
396421
ledc_clk_cfg_t pwm_clk = find_clock_in_use();
397422
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."));
399424
}
400425
#endif
401426

@@ -639,6 +664,7 @@ static void self_reset(machine_pwm_obj_t *self) {
639664
self->duty_ui = 0;
640665
self->channel_duty = -1;
641666
self->output_invert = false;
667+
self->output_invert_prev = false;
642668
self->light_sleep_enable = false;
643669
}
644670

0 commit comments

Comments
 (0)