void pwm_channel_set_period_and_duty_cycle( unsigned id, u32 period, u32 duty ) { // Fix invalid parameters if ( duty > period ) duty = period; #if ASYNCHRONOUS_UPDATE // If the channel is not active... if ( ( AVR32_PWM.sr & ( 1 << id ) ) == 0 ) { // ...write directly to the registers AVR32_PWM.channel[id].cprd = period; AVR32_PWM.channel[id].cdty = duty; } else { // ...otherwise we cannot write CPRD directly, but have to update them // through the update register. // You can't change both period and duty cycle in one cycle; you have to // update one, wait for the end of the output waveform and then update the // other. This means you always get one cycle of junk between one update // and the other. // We can only choose whether to output one cycle at the old frequency // and the new duty cycle or at the old duty cycle and the new frequency. // In either case we must ensure that duty <= period for the junk cycle. // So one solution is, if the period decreases, update the duty cycle first // or if the period increases, update the period first. if ( period < AVR32_PWM.channel[id].cprd ) { pwm_channel_set_duty_cycle( id, duty ); pwm_channel_set_period( id, period ); } else { pwm_channel_set_period( id, period ); pwm_channel_set_duty_cycle( id, duty ); } } #else // No nasty interrupts: just disable, configure and re-enable. // In practice, it seems you don't even need to disable the channel // like the User's Guide tells you to, so we don't bother. { //int was_enabled = AVR32_PWM.sr & (1 << id); //if (was_enabled) AVR32_PWM.dis = 1 << id; AVR32_PWM.channel[id].cprd = period; AVR32_PWM.channel[id].cdty = duty; //if (was_enabled) AVR32_PWM.ena = 1 << id; } #endif }
void pwm_channel_configure2(void volatile *channel, pwm_channel_clock_t const clock, pwm_channel_alignment_t const alignment, pwm_channel_polarity_t const polarity, pwm_channel_update_mode_t const update_mode, uint32_t const period, uint32_t const duty_cycle) { pwm_channel_configure(channel, clock, alignment, polarity, update_mode); pwm_channel_set_period(channel, period); pwm_channel_set_duty_cycle(channel, duty_cycle); }