35
35
#include "driver/ledc.h"
36
36
#include "esp_err.h"
37
37
38
- #define DBG (...)
39
- // #define DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, "\n");
38
+ #define DBG_LEVEL -1 // See py/mpprint.h
40
39
41
40
// Total number of channels
42
41
#define PWM_CHANNEL_MAX (LEDC_SPEED_MODE_MAX * LEDC_CHANNEL_MAX)
@@ -74,26 +73,26 @@ STATIC ledc_timer_config_t timers[PWM_TIMER_MAX];
74
73
75
74
// 10-bit resolution (compatible with esp8266 PWM)
76
75
#define PWRES (LEDC_TIMER_10_BIT)
77
- // maximum duty value on 10-bit resolution
76
+ // Maximum duty value on 10-bit resolution
78
77
#define MAX_DUTY_U10 ((1 << PWRES) - 1)
79
78
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/ledc.html#supported-range-of-frequency-and-duty-resolutions
80
79
// duty() uses 10-bit resolution or less
81
80
// duty_u16() and duty_ns() use 16-bit resolution or less
82
81
83
- // possible highest resolution in device
82
+ // Possible highest resolution in device
84
83
#if CONFIG_IDF_TARGET_ESP32
85
- #define HIGHEST_PWM_RES (LEDC_TIMER_16_BIT) // 20 in fact, but 16 is used
84
+ #define HIGHEST_PWM_RES (LEDC_TIMER_16_BIT) // 20 bit in fact, but 16 bit is used
86
85
#else
87
86
#define HIGHEST_PWM_RES (LEDC_TIMER_14_BIT)
88
87
#endif
89
- // duty resolution of user interface in `duty_u16()` and `duty_u16` parameter in constructor/initializer
88
+ // Duty resolution of user interface in `duty_u16()` and `duty_u16` parameter in constructor/initializer
90
89
#define UI_RES_16_BIT (16)
91
- // maximum duty value on highest resolution
90
+ // Maximum duty value on highest user interface resolution
92
91
#define UI_MAX_DUTY ((1 << UI_RES_16_BIT) - 1)
93
- // how much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT
92
+ // How much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT
94
93
#define UI_RES_SHIFT (16 - HIGHEST_PWM_RES) // 0 for ESP32, 2 for S2, S3, C3
95
94
96
- // If the PWM frequency is less than EMPIRIC_FREQ, then LEDC_REF_CLK_HZ(1 MHz) is used, else LEDC_APB_CLK_HZ(80 MHz) is used
95
+ // 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
97
96
#define EMPIRIC_FREQ (10) // Hz
98
97
99
98
// Config of timer upon which we run all PWM'ed GPIO pins
@@ -108,9 +107,9 @@ typedef struct _machine_pwm_obj_t {
108
107
int channel ;
109
108
int timer ;
110
109
int duty_x ; // PWRES if duty(), HIGHEST_PWM_RES if duty_u16(), -HIGHEST_PWM_RES if duty_ns()
111
- int duty_u10 ;
112
- int duty_u16 ;
113
- int duty_ns ;
110
+ int duty_u10 ; // stored values from previous duty setters
111
+ int duty_u16 ; // - / -
112
+ int duty_ns ; // - / -
114
113
} machine_pwm_obj_t ;
115
114
116
115
STATIC void pwm_init (void ) {
@@ -128,12 +127,12 @@ STATIC void pwm_init(void) {
128
127
timers [i ].freq_hz = -1 ;
129
128
timers [i ].speed_mode = TIMER_IDX_TO_MODE (i );
130
129
timers [i ].timer_num = TIMER_IDX_TO_TIMER (i );
131
- timers [i ].clk_cfg = LEDC_AUTO_CLK ;
130
+ timers [i ].clk_cfg = LEDC_AUTO_CLK ; // will reinstall later according to the EMPIRIC_FREQ
132
131
}
133
132
}
134
133
135
134
STATIC void configure_channel (machine_pwm_obj_t * self ) {
136
- DBG ("configure_channel" )
135
+ DBG (5 , "configure_channel" )
137
136
ledc_channel_config_t cfg = {
138
137
.channel = self -> channel ,
139
138
.duty = (1 << (timers [TIMER_IDX (self -> mode , self -> timer )].duty_resolution )) / 2 ,
@@ -155,7 +154,7 @@ STATIC void set_freq(unsigned int freq, ledc_timer_config_t *timer, machine_pwm_
155
154
// Even if the timer frequency is already set,
156
155
// the set_duty_x() is required to reconfigure the channel duty anyway
157
156
if (freq != timer -> freq_hz ) {
158
- DBG ("set_freq(%d)" , freq )
157
+ DBG (3 , "set_freq(%d)" , freq )
159
158
160
159
// Find the highest bit resolution for the requested frequency
161
160
unsigned int i = LEDC_APB_CLK_HZ ; // 80 MHz
@@ -201,10 +200,10 @@ STATIC void set_freq(unsigned int freq, ledc_timer_config_t *timer, machine_pwm_
201
200
202
201
// Set frequency
203
202
esp_err_t err = ledc_timer_config (timer );
204
- DBG ("ledc_timer_config" )
203
+ DBG (4 , "ledc_timer_config" )
205
204
if (err != ESP_OK ) {
206
205
if (err == ESP_FAIL ) {
207
- DBG (" (timer timer->speed_mode %d, timer->timer_num %d, timer->clk_cfg %d, timer->freq_hz %d, timer->duty_resolution %d) " , timer -> speed_mode , timer -> timer_num , timer -> clk_cfg , timer -> freq_hz , timer -> duty_resolution );
206
+ DBG (1 , " (timer timer->speed_mode %d, timer->timer_num %d, timer->clk_cfg %d, timer->freq_hz %d, timer->duty_resolution %d) " , timer -> speed_mode , timer -> timer_num , timer -> clk_cfg , timer -> freq_hz , timer -> duty_resolution );
208
207
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("unreachable frequency %d" ), freq );
209
208
} else {
210
209
check_esp_err (err );
@@ -213,7 +212,7 @@ STATIC void set_freq(unsigned int freq, ledc_timer_config_t *timer, machine_pwm_
213
212
// Reset the timer if low speed
214
213
if (self -> mode == LEDC_LOW_SPEED_MODE ) {
215
214
check_esp_err (ledc_timer_rst (self -> mode , self -> timer ));
216
- DBG ("ledc_timer_rst LEDC_LOW_SPEED_MODE" )
215
+ DBG (4 , "ledc_timer_rst LEDC_LOW_SPEED_MODE" )
217
216
}
218
217
}
219
218
@@ -236,14 +235,14 @@ STATIC int ns_to_duty(machine_pwm_obj_t *self, int ns) {
236
235
} else if (duty > UI_MAX_DUTY ) {
237
236
duty = UI_MAX_DUTY ;
238
237
}
239
- // DBG(" ns_to_duty(UI_MAX_DUTY=%d freq_hz=%d duty=%d=%f <- ns=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)ns * UI_MAX_DUTY * timer.freq_hz / 1000000000.0, ns);
238
+ // DBG(3, " ns_to_duty(UI_MAX_DUTY=%d freq_hz=%d duty=%d=%f <- ns=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)ns * UI_MAX_DUTY * timer.freq_hz / 1000000000.0, ns);
240
239
return duty ;
241
240
}
242
241
243
242
STATIC int duty_to_ns (machine_pwm_obj_t * self , int duty ) {
244
243
ledc_timer_config_t timer = timers [TIMER_IDX (self -> mode , self -> timer )];
245
244
int64_t ns = ((int64_t )duty * 1000000000LL + (int64_t )timer .freq_hz * UI_MAX_DUTY / 2 ) / ((int64_t )timer .freq_hz * UI_MAX_DUTY );
246
- // DBG(" duty_to_ns(UI_MAX_DUTY=%d freq_hz=%d duty=%d -> ns=%f=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)duty * 1000000000.0 / ((float)timer.freq_hz * UI_MAX_DUTY), ns);
245
+ // DBG(3, " duty_to_ns(UI_MAX_DUTY=%d freq_hz=%d duty=%d -> ns=%f=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)duty * 1000000000.0 / ((float)timer.freq_hz * UI_MAX_DUTY), ns);
247
246
return ns ;
248
247
}
249
248
@@ -262,7 +261,7 @@ STATIC uint32_t get_duty_ns(machine_pwm_obj_t *self) {
262
261
}
263
262
264
263
STATIC void set_duty_u16 (machine_pwm_obj_t * self , int duty ) {
265
- DBG ("set_duty_u16(%d)" , duty )
264
+ DBG (5 , "set_duty_u16(%d)" , duty )
266
265
if ((duty < 0 ) || (duty > UI_MAX_DUTY )) {
267
266
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("duty_u16 must be from 0 to %d" ), UI_MAX_DUTY );
268
267
}
@@ -283,7 +282,7 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
283
282
if (duty != get_duty_u16(self)) {
284
283
ets_delay_us(100);
285
284
if (duty != get_duty_u16(self)) {
286
- DBG(" (set_duty_u16(%u) get_duty_u16()=%u duty_resolution=%d) ", duty, get_duty_u16(self), timers[TIMER_IDX(self->mode, self->timer)].duty_resolution);
285
+ DBG(2, " (set_duty_u16(%u) get_duty_u16()=%u duty_resolution=%d) ", duty, get_duty_u16(self), timers[TIMER_IDX(self->mode, self->timer)].duty_resolution);
287
286
}
288
287
}
289
288
*/
@@ -293,7 +292,7 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
293
292
}
294
293
295
294
STATIC void set_duty_u10 (machine_pwm_obj_t * self , int duty ) {
296
- DBG ("set_duty(%d)" , duty )
295
+ DBG (5 , "set_duty(%d)" , duty )
297
296
if ((duty < 0 ) || (duty > MAX_DUTY_U10 )) {
298
297
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("duty must be from 0 to %u" ), MAX_DUTY_U10 );
299
298
}
@@ -303,7 +302,7 @@ STATIC void set_duty_u10(machine_pwm_obj_t *self, int duty) {
303
302
}
304
303
305
304
STATIC void set_duty_ns (machine_pwm_obj_t * self , int ns ) {
306
- DBG ("set_duty_ns(%d)" , ns )
305
+ DBG (5 , "set_duty_ns(%d)" , ns )
307
306
if ((ns < 0 ) || (ns > duty_to_ns (self , UI_MAX_DUTY ))) {
308
307
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 ));
309
308
}
@@ -394,9 +393,10 @@ STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_p
394
393
mp_printf (print , ")" );
395
394
}
396
395
396
+ // This called from pwm.init() method
397
397
STATIC void mp_machine_pwm_init_helper (machine_pwm_obj_t * self ,
398
398
size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
399
- DBG ("mp_machine_pwm_init_helper" )
399
+ DBG (5 , "mp_machine_pwm_init_helper" )
400
400
enum { ARG_freq , ARG_duty , ARG_duty_u16 , ARG_duty_ns };
401
401
static const mp_arg_t allowed_args [] = {
402
402
{ MP_QSTR_freq , MP_ARG_INT , {.u_int = -1 } },
@@ -494,9 +494,10 @@ STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
494
494
}
495
495
}
496
496
497
+ // This called from PWM() constructor
497
498
STATIC mp_obj_t mp_machine_pwm_make_new (const mp_obj_type_t * type ,
498
499
size_t n_args , size_t n_kw , const mp_obj_t * args ) {
499
- DBG ("mp_machine_pwm_make_new" )
500
+ DBG (5 , "mp_machine_pwm_make_new" )
500
501
mp_arg_check_num (n_args , n_kw , 1 , 2 , true);
501
502
gpio_num_t pin_id = machine_pin_get_id (args [0 ]);
502
503
@@ -524,6 +525,7 @@ STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type,
524
525
return MP_OBJ_FROM_PTR (self );
525
526
}
526
527
528
+ // Deinit channel and timer if the timer is unused
527
529
STATIC void pwm_deinit (int channel_idx ) {
528
530
// Valid channel?
529
531
if ((channel_idx >= 0 ) && (channel_idx < PWM_CHANNEL_MAX )) {
@@ -562,6 +564,7 @@ STATIC void pwm_deinit(int channel_idx) {
562
564
}
563
565
}
564
566
567
+ // This called from pwm.deinit() method
565
568
STATIC void mp_machine_pwm_deinit (machine_pwm_obj_t * self ) {
566
569
int channel_idx = CHANNEL_IDX (self -> mode , self -> channel );
567
570
pwm_deinit (channel_idx );
@@ -572,6 +575,7 @@ STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
572
575
self -> duty_x = 0 ;
573
576
}
574
577
578
+ // This called from Ctrl-D soft reboot
575
579
void machine_pwms_deinit (void ) {
576
580
if (pwm_inited ) {
577
581
for (int channel_idx = 0 ; channel_idx < PWM_CHANNEL_MAX ; ++ channel_idx ) {
@@ -581,6 +585,8 @@ void machine_pwms_deinit(void) {
581
585
}
582
586
}
583
587
588
+ // Set's and get's methods of PWM class
589
+
584
590
STATIC mp_obj_t mp_machine_pwm_freq_get (machine_pwm_obj_t * self ) {
585
591
return MP_OBJ_NEW_SMALL_INT (ledc_get_freq (self -> mode , self -> timer ));
586
592
}
@@ -620,7 +626,7 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
620
626
if (!current_in_use ) {
621
627
// Free the old timer
622
628
check_esp_err (ledc_timer_rst (self -> mode , self -> timer ));
623
- DBG ("ledc_timer_rst(%d, %d) Free" , self -> mode , self -> timer )
629
+ DBG (4 , "ledc_timer_rst(%d, %d) Free" , self -> mode , self -> timer )
624
630
// Flag it unused
625
631
timers [current_timer_idx ].freq_hz = -1 ;
626
632
}
0 commit comments