@@ -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,7 +125,7 @@ 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
130
// Continue to check if a channel with the same freq is in used.
131
131
}
@@ -134,25 +134,16 @@ STATIC int found_timer(int freq) {
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 curr_channel
138
+ STATIC bool is_timer_in_use (int curr_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 != curr_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
/******************************************************************************/
@@ -204,13 +195,13 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
204
195
int timer ;
205
196
int freq = args [ARG_freq ].u_int ;
206
197
207
- //Check if freq wasn't passed as an argument
198
+ // Check if freq wasn't passed as an argument
208
199
if (freq == -1 ) {
209
200
// Check if already set, otherwise use the defaut freq
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 );
204
+ timer = found_timer (freq , false );
214
205
215
206
if (timer == -1 ) {
216
207
mp_raise_ValueError (MP_ERROR_TEXT ("out of PWM timers" ));
@@ -289,10 +280,15 @@ STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
289
280
// Valid channel?
290
281
if ((chan >= 0 ) && (chan < LEDC_CHANNEL_MAX )) {
291
282
// Clean up timer if necessary
292
- cleanup_timer (chan , chan_timer [self -> channel ]);
283
+ if (!is_timer_in_use (chan , chan_timer [chan ])) {
284
+ ledc_timer_rst (PWMODE , chan_timer [chan ]);
285
+ // Flag it unused
286
+ timers [chan_timer [chan ]].freq_hz = -1 ;
287
+ }
293
288
294
289
// Mark it unused, and tell the hardware to stop routing
295
290
chan_gpio [chan ] = -1 ;
291
+ chan_timer [chan ] = -1 ;
296
292
ledc_stop (PWMODE , chan , 0 );
297
293
self -> active = 0 ;
298
294
self -> channel = -1 ;
@@ -311,24 +307,52 @@ STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args) {
311
307
312
308
// set
313
309
int tval = mp_obj_get_int (args [1 ]);
314
- cleanup_timer (self -> channel , chan_timer [self -> channel ]);
315
310
316
- // Check if a timer already use the new freq, or grab a new one
317
- int new_timer = found_timer (tval );
311
+ if (tval == timers [chan_timer [self -> channel ]].freq_hz ) {
312
+ return mp_const_none ;
313
+ }
318
314
319
- if (new_timer == -1 ) {
320
- mp_raise_ValueError (MP_ERROR_TEXT ("out of PWM timers" ));
315
+ int current_timer = chan_timer [self -> channel ];
316
+ int new_timer = -1 ;
317
+ bool current_in_use = is_timer_in_use (self -> channel , current_timer );
318
+
319
+ // Check if an already running with the same freq is running
320
+ new_timer = found_timer (tval , true);
321
+
322
+ // If no existing timer was found, and the current one is in use, then find a new one
323
+ if (new_timer == -1 && current_in_use ) {
324
+ // Have to found a new timer
325
+ new_timer = found_timer (tval , false);
326
+
327
+ if (new_timer == -1 ) {
328
+ mp_raise_ValueError (MP_ERROR_TEXT ("out of PWM timers" ));
329
+ }
321
330
}
322
331
323
- chan_timer [self -> channel ] = new_timer ;
332
+ if (new_timer != -1 && new_timer != current_timer ) {
333
+ // Bind the channel to the new timer
334
+ chan_timer [self -> channel ] = new_timer ;
335
+
336
+ if (ledc_bind_channel_timer (PWMODE , self -> channel , new_timer ) != ESP_OK ) {
337
+ mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("Failed to bind timer to channel" ));
338
+ }
339
+
340
+ if (!current_in_use ) {
341
+ // Free the old timer
342
+ ledc_timer_rst (PWMODE , current_timer );
343
+
344
+ // Flag it unused
345
+ timers [current_timer ].freq_hz = -1 ;
346
+ }
324
347
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" ));
348
+ current_timer = new_timer ;
327
349
}
328
350
329
- if (!set_freq (tval , & timers [new_timer ])) {
351
+ // Set the freq
352
+ if (!set_freq (tval , & timers [current_timer ])) {
330
353
mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("bad frequency %d" ), tval );
331
354
}
355
+
332
356
return mp_const_none ;
333
357
}
334
358
0 commit comments