Skip to content

Commit 4bf8c33

Browse files
author
Antoine Aubert
committed
esp32/machine_pwm: re-use existing timer if possible.
In order to smooth the pwm transition. If the timer is only use by one channel. Just set the frequency.
1 parent daeccc1 commit 4bf8c33

File tree

1 file changed

+51
-25
lines changed

1 file changed

+51
-25
lines changed

ports/esp32/machine_pwm.c

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ STATIC int set_freq(int newval, ledc_timer_config_t *timer) {
116116
return 1;
117117
}
118118

119-
STATIC int found_timer(int freq) {
119+
STATIC int found_timer(int freq, bool same_freq_only) {
120120
int free_timer_found = -1;
121121
int timer;
122122
// Find a free PWM Timer using the same freq
@@ -125,7 +125,7 @@ STATIC int found_timer(int freq) {
125125
// A timer already use the same freq. Use it now.
126126
return timer;
127127
}
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)) {
129129
free_timer_found = timer;
130130
// Continue to check if a channel with the same freq is in used.
131131
}
@@ -134,25 +134,18 @@ STATIC int found_timer(int freq) {
134134
return free_timer_found;
135135
}
136136

137-
// If the timer is no longer used, clean it
138-
STATIC void cleanup_timer(int prev_channel, int timer) {
137+
// return if the timer is in use in addition to curr_channel
138+
STATIC bool is_timer_in_use(int curr_channel, int timer) {
139139
bool used = false;
140140
int i;
141141
for (i = 0; i < LEDC_CHANNEL_MAX; ++i) {
142-
if (i != prev_channel && chan_timer[i] == timer) {
142+
if (i != curr_channel && chan_timer[i] == timer) {
143143
used = true;
144144
break;
145145
}
146146
}
147147

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-
}
148+
return used;
156149
}
157150

158151
/******************************************************************************/
@@ -204,13 +197,13 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
204197
int timer;
205198
int freq = args[ARG_freq].u_int;
206199

207-
//Check if freq wasn't passed as an argument
200+
// Check if freq wasn't passed as an argument
208201
if (freq == -1) {
209202
// Check if already set, otherwise use the defaut freq
210203
freq = chan_timer[self->channel] != -1 ? timers[chan_timer[self->channel]].freq_hz : PWFREQ;
211204
}
212205

213-
timer = found_timer(freq);
206+
timer = found_timer(freq, false);
214207

215208
if (timer == -1) {
216209
mp_raise_ValueError(MP_ERROR_TEXT("out of PWM timers"));
@@ -289,7 +282,12 @@ STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
289282
// Valid channel?
290283
if ((chan >= 0) && (chan < LEDC_CHANNEL_MAX)) {
291284
// Clean up timer if necessary
292-
cleanup_timer(chan, chan_timer[self->channel]);
285+
if (!is_timer_in_use(chan, chan_timer[chan])) {
286+
ledc_timer_rst(PWMODE, chan_timer[chan]);
287+
// Flag it unused
288+
timers[chan_timer[chan]].freq_hz = -1;
289+
chan_timer[chan] = -1;
290+
}
293291

294292
// Mark it unused, and tell the hardware to stop routing
295293
chan_gpio[chan] = -1;
@@ -311,24 +309,52 @@ STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args) {
311309

312310
// set
313311
int tval = mp_obj_get_int(args[1]);
314-
cleanup_timer(self->channel, chan_timer[self->channel]);
315312

316-
// Check if a timer already use the new freq, or grab a new one
317-
int new_timer = found_timer(tval);
313+
if (tval == timers[chan_timer[self->channel]].freq_hz) {
314+
return mp_const_none;
315+
}
316+
317+
int current_timer = chan_timer[self->channel];
318+
int new_timer = -1;
319+
bool current_in_use = is_timer_in_use(self->channel, current_timer);
318320

319-
if (new_timer == -1) {
320-
mp_raise_ValueError(MP_ERROR_TEXT("out of PWM timers"));
321+
// Check if an already running with the same freq is running
322+
new_timer = found_timer(tval, true);
323+
324+
// If no existing timer was found, and the current one is in use, then find a new one
325+
if (new_timer == -1 && current_in_use) {
326+
// Have to found a new timer
327+
new_timer = found_timer(tval, false);
328+
329+
if (new_timer == -1) {
330+
mp_raise_ValueError(MP_ERROR_TEXT("out of PWM timers"));
331+
}
321332
}
322333

323-
chan_timer[self->channel] = new_timer;
334+
if (new_timer != -1 && new_timer != current_timer) {
335+
// Bind the channel to the new timer
336+
chan_timer[self->channel] = new_timer;
337+
338+
if (ledc_bind_channel_timer(PWMODE, self->channel, new_timer) != ESP_OK) {
339+
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Failed to bind timer to channel"));
340+
}
341+
342+
if (!current_in_use) {
343+
// Free the old timer
344+
ledc_timer_rst(PWMODE, current_timer);
324345

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+
// Flag it unused
347+
timers[current_timer].freq_hz = -1;
348+
}
349+
350+
current_timer = new_timer;
327351
}
328352

329-
if (!set_freq(tval, &timers[new_timer])) {
353+
// Set the freq
354+
if (!set_freq(tval, &timers[current_timer])) {
330355
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("bad frequency %d"), tval);
331356
}
357+
332358
return mp_const_none;
333359
}
334360

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy