esp32/machine_pwm: Support higher PWM freq by auto-scaling timer res.
This commit is contained in:
parent
87623082e3
commit
287b02d98a
@ -59,7 +59,7 @@ STATIC int chan_gpio[LEDC_CHANNEL_MAX];
|
||||
// Config of timer upon which we run all PWM'ed GPIO pins
|
||||
STATIC bool pwm_inited = false;
|
||||
STATIC ledc_timer_config_t timer_cfg = {
|
||||
.bit_num = PWRES,
|
||||
.duty_resolution = PWRES,
|
||||
.freq_hz = PWFREQ,
|
||||
.speed_mode = PWMODE,
|
||||
.timer_num = PWTIMER
|
||||
@ -77,10 +77,28 @@ STATIC void pwm_init(void) {
|
||||
}
|
||||
|
||||
STATIC int set_freq(int newval) {
|
||||
int ores = timer_cfg.duty_resolution;
|
||||
int oval = timer_cfg.freq_hz;
|
||||
|
||||
// Find the highest bit resolution for the requested frequency
|
||||
if (newval <= 0) {
|
||||
newval = 1;
|
||||
}
|
||||
unsigned int res = 0;
|
||||
for (unsigned int i = LEDC_APB_CLK_HZ / newval; i > 1; i >>= 1, ++res) {
|
||||
}
|
||||
if (res == 0) {
|
||||
res = 1;
|
||||
} else if (res > PWRES) {
|
||||
// Limit resolution to PWRES to match units of our duty
|
||||
res = PWRES;
|
||||
}
|
||||
|
||||
// Configure the new resolution and frequency
|
||||
timer_cfg.duty_resolution = res;
|
||||
timer_cfg.freq_hz = newval;
|
||||
if (ledc_timer_config(&timer_cfg) != ESP_OK) {
|
||||
timer_cfg.duty_resolution = ores;
|
||||
timer_cfg.freq_hz = oval;
|
||||
return 0;
|
||||
}
|
||||
@ -138,7 +156,7 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
|
||||
if (chan_gpio[channel] == -1) {
|
||||
ledc_channel_config_t cfg = {
|
||||
.channel = channel,
|
||||
.duty = (1 << PWRES) / 2,
|
||||
.duty = (1 << timer_cfg.duty_resolution) / 2,
|
||||
.gpio_num = self->pin,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.speed_mode = PWMODE,
|
||||
@ -166,6 +184,7 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
|
||||
int dval = args[ARG_duty].u_int;
|
||||
if (dval != -1) {
|
||||
dval &= ((1 << PWRES)-1);
|
||||
dval >>= PWRES - timer_cfg.duty_resolution;
|
||||
ledc_set_duty(PWMODE, channel, dval);
|
||||
ledc_update_duty(PWMODE, channel);
|
||||
}
|
||||
@ -244,12 +263,14 @@ STATIC mp_obj_t esp32_pwm_duty(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
duty = ledc_get_duty(PWMODE, self->channel);
|
||||
duty <<= PWRES - timer_cfg.duty_resolution;
|
||||
return MP_OBJ_NEW_SMALL_INT(duty);
|
||||
}
|
||||
|
||||
// set
|
||||
duty = mp_obj_get_int(args[1]);
|
||||
duty &= ((1 << PWRES)-1);
|
||||
duty >>= PWRES - timer_cfg.duty_resolution;
|
||||
ledc_set_duty(PWMODE, self->channel, duty);
|
||||
ledc_update_duty(PWMODE, self->channel);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user