Block when setting duty_cycle until the new value is taken

This commit is contained in:
Scott Shawcroft 2021-07-27 12:37:35 -07:00
parent 080e5233b4
commit e87e1d8175
No known key found for this signature in database
GPG Key ID: 0DFD512649C052DA
2 changed files with 12 additions and 25 deletions

View File

@ -38,27 +38,12 @@
#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
#include "src/common/pico_time/include/pico/time.h"
static uint8_t refcount = 0;
volatile alarm_id_t cur_alarm = 0;
void turn_off(uint8_t slice) {
// Set the current counter value near the top so that the output is low. The
// - 2 gives us a little wiggle room for enabling and disabling the slice.
// The top + 1 ensure we don't end up lower than the cc (and therefore high.)
uint32_t top = MAX(pwm_hw->slice[slice].cc + 1, pwm_hw->slice[slice].top - 2);
// Disable interrupts so this happens as fast as possible.
common_hal_mcu_disable_interrupts();
pwm_hw->slice[slice].ctr = top;
// Enable for at least one cycle so that the new counter value takes effect.
pwm_hw->slice[slice].csr = PWM_CH0_CSR_EN_BITS;
pwm_hw->slice[slice].csr = 0;
common_hal_mcu_enable_interrupts();
}
void pulse_finish(pulseio_pulseout_obj_t *self) {
self->pulse_index++;
// Turn pwm pin off by setting duty cyle to 1.
common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, 1);
// Turn pwm pin off by setting duty cyle to 0.
common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, 0);
if (self->pulse_index >= self->pulse_length) {
return;
}
@ -91,15 +76,12 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
uint16_t duty_cycle) {
pwmout_result_t result = common_hal_pwmio_pwmout_construct(
&self->carrier, pin, duty_cycle, frequency, false);
&self->carrier, pin, 0, frequency, false);
// This will raise an exception and not return if needed.
common_hal_pwmio_pwmout_raise_error(result);
self->current_duty_cycle = duty_cycle;
pwm_set_enabled(self->carrier.slice, false);
turn_off(self->carrier.slice);
common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, 1);
self->pin = self->carrier.pin->number;
self->slice = self->carrier.slice;
self->min_pulse = (1000000 / self->carrier.actual_frequency);
@ -123,7 +105,6 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t *self, uint16_t *pu
self->pulse_length = length;
common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, self->current_duty_cycle);
pwm_set_enabled(self->slice, true);
uint64_t delay = self->pulse_buffer[0];
if (delay < self->min_pulse) {
delay = self->min_pulse;
@ -140,7 +121,4 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t *self, uint16_t *pu
// signal.
RUN_BACKGROUND_TASKS;
}
// Ensure pin is left low
turn_off(self->slice);
pwm_set_enabled(self->slice,false);
}

View File

@ -26,6 +26,7 @@
#include <stdint.h>
#include "lib/utils/interrupt_char.h"
#include "py/runtime.h"
#include "common-hal/pwmio/PWMOut.h"
#include "shared-bindings/pwmio/PWMOut.h"
@ -235,6 +236,14 @@ extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uin
}
// compare_count is the CC register value, which should be TOP+1 for 100% duty cycle.
pwm_set_chan_level(self->slice, self->channel, compare_count);
// Wait for wrap so that we know our new cc value has been applied. Clear
// the internal interrupt and then wait for it to be set. Worst case, we
// wait a full cycle.
pwm_hw->intr = 1 << self->channel;
while ((pwm_hw->en & (1 << self->channel)) != 0 &&
(pwm_hw->intr & (1 << self->channel)) == 0 &&
!mp_hal_is_interrupted()) {
}
}
uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t *self) {