@@ -116,7 +116,7 @@ STATIC int set_freq(int newval, ledc_timer_config_t *timer) {
116
116
return 1 ;
117
117
}
118
118
119
- STATIC int found_timer (int freq ) {
119
+ STATIC int found_timer (int freq , bool same_freq_only ) {
120
120
int free_timer_found = -1 ;
121
121
int timer ;
122
122
// Find a free PWM Timer using the same freq
@@ -125,34 +125,25 @@ STATIC int found_timer(int freq) {
125
125
// A timer already use the same freq. Use it now.
126
126
return timer ;
127
127
}
128
- if ((free_timer_found == -1 ) && (timers [timer ].freq_hz == -1 )) {
128
+ if (! same_freq_only && (free_timer_found == -1 ) && (timers [timer ].freq_hz == -1 )) {
129
129
free_timer_found = timer ;
130
- // Continue to check if a channel with the same freq is in used .
130
+ // Continue to check if a channel with the same freq is in use .
131
131
}
132
132
}
133
133
134
134
return free_timer_found ;
135
135
}
136
136
137
- // If the timer is no longer used, clean it
138
- STATIC void cleanup_timer (int prev_channel , int timer ) {
139
- bool used = false;
137
+ // Return true if the timer is in use in addition to current channel
138
+ STATIC bool is_timer_in_use (int current_channel , int timer ) {
140
139
int i ;
141
140
for (i = 0 ; i < LEDC_CHANNEL_MAX ; ++ i ) {
142
- if (i != prev_channel && chan_timer [i ] == timer ) {
143
- used = true;
144
- break ;
141
+ if (i != current_channel && chan_timer [i ] == timer ) {
142
+ return true;
145
143
}
146
144
}
147
145
148
- // If timer is not used, clean it
149
- if (!used ) {
150
- ledc_timer_pause (PWMODE , timer );
151
-
152
- // Flag it unused
153
- timers [timer ].freq_hz = -1 ;
154
- chan_timer [prev_channel ] = -1 ;
155
- }
146
+ return false;
156
147
}
157
148
158
149
/******************************************************************************/
@@ -210,8 +201,7 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
210
201
freq = chan_timer [self -> channel ] != -1 ? timers [chan_timer [self -> channel ]].freq_hz : PWFREQ ;
211
202
}
212
203
213
- timer = found_timer (freq );
214
-
204
+ timer = found_timer (freq , false);
215
205
if (timer == -1 ) {
216
206
mp_raise_ValueError (MP_ERROR_TEXT ("out of PWM timers" ));
217
207
}
@@ -289,10 +279,15 @@ STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
289
279
// Valid channel?
290
280
if ((chan >= 0 ) && (chan < LEDC_CHANNEL_MAX )) {
291
281
// Clean up timer if necessary
292
- cleanup_timer (chan , chan_timer [self -> channel ]);
282
+ if (!is_timer_in_use (chan , chan_timer [chan ])) {
283
+ ledc_timer_rst (PWMODE , chan_timer [chan ]);
284
+ // Flag it unused
285
+ timers [chan_timer [chan ]].freq_hz = -1 ;
286
+ }
293
287
294
288
// Mark it unused, and tell the hardware to stop routing
295
289
chan_gpio [chan ] = -1 ;
290
+ chan_timer [chan ] = -1 ;
296
291
ledc_stop (PWMODE , chan , 0 );
297
292
self -> active = 0 ;
298
293
self -> channel = -1 ;
@@ -311,22 +306,48 @@ STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args) {
311
306
312
307
// set
313
308
int tval = mp_obj_get_int (args [1 ]);
314
- cleanup_timer (self -> channel , chan_timer [self -> channel ]);
315
309
316
- // Check if a timer already use the new freq, or grab a new one
317
- int new_timer = found_timer (tval );
310
+ if (tval == timers [chan_timer [self -> channel ]].freq_hz ) {
311
+ return mp_const_none ;
312
+ }
313
+
314
+ int current_timer = chan_timer [self -> channel ];
315
+ int new_timer = -1 ;
316
+ bool current_in_use = is_timer_in_use (self -> channel , current_timer );
318
317
319
- if (new_timer == -1 ) {
320
- mp_raise_ValueError (MP_ERROR_TEXT ("out of PWM timers" ));
318
+ // Check if an already running timer with the same freq is running
319
+ new_timer = found_timer (tval , true);
320
+
321
+ // If no existing timer was found, and the current one is in use, then find a new one
322
+ if (new_timer == -1 && current_in_use ) {
323
+ // Have to find a new timer
324
+ new_timer = found_timer (tval , false);
325
+
326
+ if (new_timer == -1 ) {
327
+ mp_raise_ValueError (MP_ERROR_TEXT ("out of PWM timers" ));
328
+ }
321
329
}
322
330
323
- chan_timer [self -> channel ] = new_timer ;
331
+ if (new_timer != -1 && new_timer != current_timer ) {
332
+ // Bind the channel to the new timer
333
+ chan_timer [self -> channel ] = new_timer ;
334
+
335
+ if (ledc_bind_channel_timer (PWMODE , self -> channel , new_timer ) != ESP_OK ) {
336
+ mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("Failed to bind timer to channel" ));
337
+ }
338
+
339
+ if (!current_in_use ) {
340
+ // Free the old timer
341
+ ledc_timer_rst (PWMODE , current_timer );
342
+ // Flag it unused
343
+ timers [current_timer ].freq_hz = -1 ;
344
+ }
324
345
325
- if (ledc_bind_channel_timer (PWMODE , self -> channel , new_timer ) != ESP_OK ) {
326
- mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("Failed to bind timer to channel" ));
346
+ current_timer = new_timer ;
327
347
}
328
348
329
- if (!set_freq (tval , & timers [new_timer ])) {
349
+ // Set the freq
350
+ if (!set_freq (tval , & timers [current_timer ])) {
330
351
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("bad frequency %d" ), tval );
331
352
}
332
353
return mp_const_none ;
0 commit comments