diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC82X/pwmout_api.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC82X/pwmout_api.c index 38ef6b9f8f..db4b4d6dd3 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC82X/pwmout_api.c +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC82X/pwmout_api.c @@ -91,6 +91,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) pwm->CTRL &= ~(0x7F << 5); pwm->CTRL |= (((SystemCoreClock/1000000 - 1) & 0x7F) << 5); + // Set event number pwm->OUT[sct_n].SET = (1 << ((sct_n * 2) + 0)); pwm->OUT[sct_n].CLR = (1 << ((sct_n * 2) + 1)); @@ -99,10 +100,6 @@ void pwmout_init(pwmout_t* obj, PinName pin) pwm->EVENT[(sct_n * 2) + 1].CTRL = (1 << 12) | ((sct_n * 2) + 1); pwm->EVENT[(sct_n * 2) + 1].STATE = 0xFFFFFFFF; - // unhalt the counter: - // - clearing bit 2 of the CTRL register - pwm->CTRL &= ~(1 << 2); - // default to 20ms: standard for servos, and fine for e.g. brightness control pwmout_period_ms(obj, 20); pwmout_write (obj, 0); @@ -120,16 +117,27 @@ void pwmout_write(pwmout_t* obj, float value) if (value < 0.0f) { value = 0.0; } else if (value > 1.0f) { - value = 1.0; + value = 1.0f; + } + uint32_t t_on = (uint32_t)((float)(obj->pwm->MATCHREL[obj->pwm_ch * 2] + 1) * value); + if (t_on > 0) { + if (value != 1.0f) { + obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] = t_on - 1; + obj->pwm->CTRL &= ~(1 << 2); + } else { + obj->pwm->CTRL |= (1 << 2) | (1 << 3); + obj->pwm->OUTPUT |= (1 << obj->pwm_ch); + } + } else { + obj->pwm->CTRL |= (1 << 2) | (1 << 3); + obj->pwm->OUTPUT &= ~(1 << obj->pwm_ch); } - uint32_t t_on = (uint32_t)((float)(obj->pwm->MATCHREL[obj->pwm_ch * 2]) * value); - obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] = t_on; } float pwmout_read(pwmout_t* obj) { - uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 0]; - uint32_t t_on = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1]; + uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 0] + 1; + uint32_t t_on = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] + 1; float v = (float)t_on/(float)t_off; return (v > 1.0f) ? (1.0f) : (v); } @@ -147,11 +155,17 @@ void pwmout_period_ms(pwmout_t* obj, int ms) // Set the PWM period, keeping the duty cycle the same. void pwmout_period_us(pwmout_t* obj, int us) { - uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 0]; - uint32_t t_on = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1]; + uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 0] + 1; + uint32_t t_on = obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] + 1; float v = (float)t_on/(float)t_off; - obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 0] = (uint32_t)us; - obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] = (uint32_t)((float)us * (float)v); + obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 0] = (uint32_t)us - 1; + if (us > 0) { + obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] = (uint32_t)((float)us * (float)v) - 1; + obj->pwm->CTRL &= ~(1 << 2); + } else { + obj->pwm->CTRL |= (1 << 2) | (1 << 3); + obj->pwm->OUTPUT &= ~(1 << obj->pwm_ch); + } } void pwmout_pulsewidth(pwmout_t* obj, float seconds) @@ -166,7 +180,13 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) void pwmout_pulsewidth_us(pwmout_t* obj, int us) { - obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] = (uint32_t)us; + if (us > 0) { + obj->pwm->MATCHREL[(obj->pwm_ch * 2) + 1] = (uint32_t)us - 1; + obj->pwm->CTRL &= ~(1 << 2); + } else { + obj->pwm->CTRL |= (1 << 2) | (1 << 3); + obj->pwm->OUTPUT &= ~(1 << obj->pwm_ch); + } } #endif