@@ -71,28 +71,31 @@ STATIC ledc_timer_config_t timers[PWM_TIMER_MAX];
71
71
#define TIMER_IDX_TO_MODE (timer_idx ) (timer_idx / LEDC_TIMER_MAX)
72
72
#define TIMER_IDX_TO_TIMER (timer_idx ) (timer_idx % LEDC_TIMER_MAX)
73
73
74
- // Params for PWM operation
74
+ // Params for PW operation
75
75
// 5khz is default frequency
76
- #define PWM_FREQ (5000)
77
- // default 10-bit resolution (compatible with esp8266 PWM)
78
- #define PWM_RES_10_BIT (LEDC_TIMER_10_BIT)
76
+ #define PWFREQ (5000)
77
+
78
+ // 10-bit resolution (compatible with esp8266 PWM)
79
+ #define PWRES (LEDC_TIMER_10_BIT)
79
80
80
81
// Maximum duty value on 10-bit resolution
81
- #define MAX_DUTY_U10 ((1 << PWM_RES_10_BIT ) - 1)
82
+ #define MAX_DUTY_U10 ((1 << PWRES ) - 1)
82
83
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/ledc.html#supported-range-of-frequency-and-duty-resolutions
83
84
// duty() uses 10-bit resolution or less
84
85
// duty_u16() and duty_ns() use 16-bit resolution or less
85
86
86
87
// Possible highest resolution in device
87
- #if CONFIG_IDF_TARGET_ESP32
88
- #define HIGHEST_PWM_RES (LEDC_TIMER_16_BIT) // 20 bit for ESP32, but 16 bit is used
88
+ #if ( LEDC_TIMER_BIT_MAX - 1 ) < LEDC_TIMER_16_BIT
89
+ #define HIGHEST_PWM_RES (LEDC_TIMER_BIT_MAX - 1)
89
90
#else
90
- #define HIGHEST_PWM_RES (LEDC_TIMER_BIT_MAX - 1 ) // 14 bit is used
91
+ #define HIGHEST_PWM_RES (LEDC_TIMER_16_BIT ) // 20 bit for ESP32, but 16 bit is used
91
92
#endif
92
93
// Duty resolution of user interface in `duty_u16()` and `duty_u16` parameter in constructor/initializer
93
94
#define UI_RES_16_BIT (16)
94
95
// Maximum duty value on highest user interface resolution
95
96
#define UI_MAX_DUTY ((1 << UI_RES_16_BIT) - 1)
97
+ // How much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT
98
+ #define UI_RES_SHIFT (UI_RES_16_BIT - HIGHEST_PWM_RES) // 0 for ESP32, 2 for S2, S3, C3
96
99
97
100
// If the PWM frequency is less than EMPIRIC_FREQ, then LEDC_REF_CLK_HZ(1 MHz) source is used, else LEDC_APB_CLK_HZ(80 MHz) source is used
98
101
#define EMPIRIC_FREQ (10) // Hz
@@ -108,7 +111,7 @@ typedef struct _machine_pwm_obj_t {
108
111
int mode ;
109
112
int channel ;
110
113
int timer ;
111
- int duty_x ; // PWM_RES_10_BIT if duty(), UI_RES_16_BIT if duty_u16(), -UI_RES_16_BIT if duty_ns()
114
+ int duty_x ; // PWRES if duty(), HIGHEST_PWM_RES if duty_u16(), -HIGHEST_PWM_RES if duty_ns()
112
115
int duty_u10 ; // stored values from previous duty setters
113
116
int duty_u16 ; // - / -
114
117
int duty_ns ; // - / -
@@ -208,7 +211,6 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
208
211
if (freq < EMPIRIC_FREQ ) {
209
212
i = LEDC_REF_CLK_HZ ; // 1 MHz
210
213
}
211
-
212
214
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL (5 , 0 , 0 )
213
215
// original code
214
216
i /= freq ;
@@ -237,7 +239,6 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
237
239
}
238
240
239
241
// Configure the new resolution and frequency
240
- unsigned int save_duty_resolution = timer -> duty_resolution ;
241
242
timer -> duty_resolution = res ;
242
243
timer -> freq_hz = freq ;
243
244
timer -> clk_cfg = LEDC_USE_APB_CLK ;
@@ -258,17 +259,15 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
258
259
if (self -> mode == LEDC_LOW_SPEED_MODE ) {
259
260
check_esp_err (ledc_timer_rst (self -> mode , self -> timer ));
260
261
}
262
+ }
261
263
262
- // Save the same duty cycle when frequency is changed
263
- if (save_duty_resolution != timer -> duty_resolution ) {
264
- if (self -> duty_x == UI_RES_16_BIT ) {
265
- set_duty_u16 (self , self -> duty_u16 );
266
- } else if (self -> duty_x == PWM_RES_10_BIT ) {
267
- set_duty_u10 (self , self -> duty_u10 );
268
- } else if (self -> duty_x == - UI_RES_16_BIT ) {
269
- set_duty_ns (self , self -> duty_ns );
270
- }
271
- }
264
+ // Save the same duty cycle when frequency is changed
265
+ if (self -> duty_x == HIGHEST_PWM_RES ) {
266
+ set_duty_u16 (self , self -> duty_u16 );
267
+ } else if (self -> duty_x == PWRES ) {
268
+ set_duty_u10 (self , self -> duty_u10 );
269
+ } else if (self -> duty_x == - HIGHEST_PWM_RES ) {
270
+ set_duty_ns (self , self -> duty_ns );
272
271
}
273
272
}
274
273
6D47
button>@@ -293,11 +292,18 @@ STATIC int duty_to_ns(machine_pwm_obj_t *self, int duty) {
293
292
#define get_duty_raw (self ) ledc_get_duty(self->mode, self->channel)
294
293
295
294
STATIC uint32_t get_duty_u16 (machine_pwm_obj_t * self ) {
296
- return ledc_get_duty (self -> mode , self -> channel ) << (UI_RES_16_BIT - timers [TIMER_IDX (self -> mode , self -> timer )].duty_resolution );
295
+ int resolution = timers [TIMER_IDX (self -> mode , self -> timer )].duty_resolution ;
296
+ int duty = ledc_get_duty (self -> mode , self -> channel );
297
+ if (resolution <= UI_RES_16_BIT ) {
298
+ duty <<= (UI_RES_16_BIT - resolution );
299
+ } else {
300
+ duty >>= (resolution - UI_RES_16_BIT );
301
+ }
302
+ return duty ;
297
303
}
298
304
299
305
STATIC uint32_t get_duty_u10 (machine_pwm_obj_t * self ) {
300
- return get_duty_u16 (self ) >> ( UI_RES_16_BIT - LEDC_TIMER_10_BIT );
306
+ return get_duty_u16 (self ) >> 6 ; // Scale down from 16 bit to 10 bit resolution
301
307
}
302
308
303
309
STATIC uint32_t get_duty_ns (machine_pwm_obj_t * self ) {
@@ -309,7 +315,12 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
309
315
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("duty_u16 must be from 0 to %d" ), UI_MAX_DUTY );
310
316
}
311
317
ledc_timer_config_t timer = timers [TIMER_IDX (self -> mode , self -> timer )];
312
- int channel_duty = duty >> (UI_RES_16_BIT - timer .duty_resolution );
318
+ int channel_duty ;
319
+ if (timer .duty_resolution <= UI_RES_16_BIT ) {
320
+ channel_duty = duty >> (UI_RES_16_BIT - timer .duty_resolution );
321
+ } else {
322
+ channel_duty = duty << (timer .duty_resolution - UI_RES_16_BIT );
323
+ }
313
324
int max_duty = (1 << timer .duty_resolution ) - 1 ;
314
325
if (channel_duty < 0 ) {
315
326
channel_duty = 0 ;
@@ -333,16 +344,16 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
333
344
}
334
345
*/
335
346
336
- self -> duty_x = UI_RES_16_BIT ;
347
+ self -> duty_x = HIGHEST_PWM_RES ;
337
348
self -> duty_u16 = duty ;
338
349
}
339
350
340
351
STATIC void set_duty_u10 (machine_pwm_obj_t * self , int duty ) {
341
352
if ((duty < 0 ) || (duty > MAX_DUTY_U10 )) {
342
353
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("duty must be from 0 to %u" ), MAX_DUTY_U10 );
343
354
}
344
- set_duty_u16 (self , duty << (UI_RES_16_BIT - LEDC_TIMER_10_BIT ));
345
- self -> duty_x = PWM_RES_10_BIT ;
355
+ set_duty_u16 (self , duty << (HIGHEST_PWM_RES + UI_RES_SHIFT - PWRES ));
356
+ self -> duty_x = PWRES ;
346
357
self -> duty_u10 = duty ;
347
358
}
348
359
@@ -351,7 +362,7 @@ STATIC void set_duty_ns(machine_pwm_obj_t *self, int ns) {
351
362
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("duty_ns must be from 0 to %d ns" ), duty_to_ns (self , UI_MAX_DUTY ));
352
363
}
353
364
set_duty_u16 (self , ns_to_duty (self , ns ));
354
- self -> duty_x = - UI_RES_16_BIT ;
365
+ self -> duty_x = - HIGHEST_PWM_RES ;
355
366
self -> duty_ns = ns ;
356
367
}
357
368
@@ -422,9 +433,9 @@ STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_p
422
433
if (self -> active ) {
423
434
mp_printf (print , ", freq=%u" , ledc_get_freq (self -> mode , self -> timer ));
424
435
425
- if (self -> duty_x == PWM_RES_10_BIT ) {
436
+ if (self -> duty_x == PWRES ) {
426
437
mp_printf (print , ", duty=%d" , get_duty_u10 (self ));
427
- } else if (self -> duty_x == - UI_RES_16_BIT ) {
438
+ } else if (self -> duty_x == - HIGHEST_PWM_RES ) {
428
439
mp_printf (print , ", duty_ns=%d" , get_duty_ns (self ));
429
440
} else {
430
441
mp_printf (print , ", duty_u16=%d" , get_duty_u16 (self ));
@@ -476,7 +487,7 @@ STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
476
487
freq = timers [chans [channel_idx ].timer_idx ].freq_hz ;
477
488
}
478
489
if (freq <= 0 ) {
479
- freq = PWM_FREQ ;
490
+ freq = PWFREQ ;
480
491
}
481
492
}
482
493
if ((freq <= 0 ) || (freq > 40000000 )) {
@@ -533,7 +544,7 @@ STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
533
544
} else if (duty != -1 ) {
534
545
set_duty_u10 (self , duty );
535
546
} else if (self -> duty_x == 0 ) {
536
- set_duty_u10 (self , (1 << PWM_RES_10_BIT ) / 2 ); // 50%
547
+ set_duty_u10 (self , (1 << PWRES ) / 2 ); // 50%
537
548
}
538
549
}
539
550
0 commit comments