Fix for issue #7707 PwmOut inverted

since obj->sequence = &obj->pulse
and most significant bit of sequence denotes the polarity, we should set it.
pull/8035/head
MateuszM 2018-08-13 17:39:27 +02:00 committed by adbridge
parent e93472c2c3
commit 38652c8a61
1 changed files with 24 additions and 11 deletions

View File

@ -57,6 +57,9 @@
#define MAX_PWM_PERIOD_MS (MAX_PWM_PERIOD_US / 1000) #define MAX_PWM_PERIOD_MS (MAX_PWM_PERIOD_US / 1000)
#define MAX_PWM_PERIOD_S ((float) MAX_PWM_PERIOD_US / 1000000.0f) #define MAX_PWM_PERIOD_S ((float) MAX_PWM_PERIOD_US / 1000000.0f)
/* Sequence bit that denotes the polarity of the pwm waveform. */
#define SEQ_POLARITY_BIT (0x8000)
/* Allocate PWM instances. */ /* Allocate PWM instances. */
static nrf_drv_pwm_t nordic_nrf5_pwm_instance[] = { static nrf_drv_pwm_t nordic_nrf5_pwm_instance[] = {
#if PWM0_ENABLED #if PWM0_ENABLED
@ -140,7 +143,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
/* Get hardware instance from pinmap. */ /* Get hardware instance from pinmap. */
int instance = pin_instance_pwm(pin); int instance = pin_instance_pwm(pin);
MBED_ASSERT(instance < (int)(sizeof(nordic_nrf5_pwm_instance) / sizeof(nrf_drv_pwm_t))); MBED_ASSERT(instance < (int) (sizeof(nordic_nrf5_pwm_instance) / sizeof(nrf_drv_pwm_t)));
/* Populate PWM object with default values. */ /* Populate PWM object with default values. */
obj->instance = instance; obj->instance = instance;
@ -153,6 +156,9 @@ void pwmout_init(pwmout_t *obj, PinName pin)
obj->sequence.repeats = 0; obj->sequence.repeats = 0;
obj->sequence.end_delay = 0; obj->sequence.end_delay = 0;
/* Set active low logic. */
obj->pulse |= SEQ_POLARITY_BIT;
/* Initialize PWM instance. */ /* Initialize PWM instance. */
nordic_pwm_init(obj); nordic_pwm_init(obj);
} }
@ -184,17 +190,20 @@ void pwmout_write(pwmout_t *obj, float percent)
/* Find counts based on period. */ /* Find counts based on period. */
uint16_t pulse = obj->period * percent; uint16_t pulse = obj->period * percent;
/* Clear sequence, but keep the polarity bit */
obj->pulse &= SEQ_POLARITY_BIT;
/* Ensure we don't overcount. */ /* Ensure we don't overcount. */
obj->pulse = (pulse > MAX_PWM_COUNTERTOP) ? MAX_PWM_COUNTERTOP : pulse; obj->pulse |= (pulse > MAX_PWM_COUNTERTOP) ? MAX_PWM_COUNTERTOP : pulse;
/* Store actual percentage passed as parameter to avoid floating point rounding errors. */ /* Store actual percentage passed as parameter to avoid floating point rounding errors. */
obj->percent = percent; obj->percent = percent;
/* Set new duty-cycle. */ /* Set new duty-cycle. */
ret_code_t result = nrf_drv_pwm_simple_playback(&nordic_nrf5_pwm_instance[obj->instance], ret_code_t result = nrf_drv_pwm_simple_playback(&nordic_nrf5_pwm_instance[obj->instance],
&obj->sequence, &obj->sequence,
1, 1,
NRF_DRV_PWM_FLAG_LOOP); NRF_DRV_PWM_FLAG_LOOP);
MBED_ASSERT(result == NRF_SUCCESS); MBED_ASSERT(result == NRF_SUCCESS);
} }
@ -266,10 +275,11 @@ void pwmout_period_us(pwmout_t *obj, int period)
} }
/* Scale new count based on stored duty-cycle and new period. */ /* Scale new count based on stored duty-cycle and new period. */
uint32_t pulse = (period * obj->pulse) / obj->period; uint32_t pulse = (period * (obj->pulse & ~SEQ_POLARITY_BIT)) / obj->period;
/* Store new values in object. */ /* Store new values in object. */
obj->pulse = pulse; obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= pulse;
obj->period = period; obj->period = period;
obj->percent = (float) pulse / (float) period; obj->percent = (float) pulse / (float) period;
@ -287,8 +297,9 @@ void pwmout_pulsewidth(pwmout_t *obj, float pulse)
DEBUG_PRINTF("pwmout_pulsewidt: %f\r\n", pulse); DEBUG_PRINTF("pwmout_pulsewidt: %f\r\n", pulse);
/* Cap pulsewidth to period before setting it. */ /* Cap pulsewidth to period before setting it. */
if ((pulse * 1000000) > (float) obj->pulse) { if ((pulse * 1000000) > (float) (obj->pulse & ~SEQ_POLARITY_BIT)) {
obj->pulse = obj->period; obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= obj->period;
pwmout_pulsewidth_us(obj, obj->pulse); pwmout_pulsewidth_us(obj, obj->pulse);
} else { } else {
pwmout_pulsewidth_us(obj, pulse * 1000000); pwmout_pulsewidth_us(obj, pulse * 1000000);
@ -306,7 +317,8 @@ void pwmout_pulsewidth_ms(pwmout_t *obj, int pulse)
/* Cap pulsewidth to period before setting it. */ /* Cap pulsewidth to period before setting it. */
if ((pulse * 1000) > (int) obj->period) { if ((pulse * 1000) > (int) obj->period) {
obj->pulse = obj->period; obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= obj->period;
pwmout_pulsewidth_us(obj, obj->pulse); pwmout_pulsewidth_us(obj, obj->pulse);
} else { } else {
pwmout_pulsewidth_us(obj, pulse * 1000); pwmout_pulsewidth_us(obj, pulse * 1000);
@ -328,7 +340,8 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int pulse)
} }
/* Store new values in object. */ /* Store new values in object. */
obj->pulse = pulse; obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= pulse;
obj->percent = (float) pulse / (float) obj->period; obj->percent = (float) pulse / (float) obj->period;
/* Restart instance with new values. */ /* Restart instance with new values. */