/** * @brief Disables a PWM channel. * @pre The PWM unit must have been activated using @p pwmStart(). * @post The channel is disabled and its output line returned to the * idle state. * @note Depending on the hardware implementation this function has * effect starting on the next cycle (recommended implementation) * or immediately (fallback implementation). * * @param[in] pwmp pointer to a @p PWMDriver object * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) * * @notapi */ void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { uint8_t i = timer_index(pwmp); config_channel(regs_table[i].tccra, 7 - 2*channel, 6 - 2*channel, PWM_OUTPUT_DISABLED); *regs_table[i].timsk &= ~(1 << (channel + 1)); }
/** * @brief Enables a PWM channel. * @pre The PWM unit must have been activated using @p pwmStart(). * @post The channel is active using the specified configuration. * @note Depending on the hardware implementation this function has * effect starting on the next cycle (recommended implementation) * or immediately (fallback implementation). * * @param[in] pwmp pointer to a @p PWMDriver object * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) * @param[in] width PWM pulse width as clock pulses number * * @notapi */ void pwm_lld_enable_channel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width) { uint16_t val = width; if (val > MAX_PWM_VALUE) val = MAX_PWM_VALUE; #if AVR_PWM_USE_TIM2 || defined(__DOXYGEN__) if (pwmp == &PWMD2) { config_channel(&TCCR2A, 7 - 2*channel, 6 - 2*channel, pwmp->config->channels[channel].mode); TIMSK2 |= (1 << (channel + 1)); /* Timer 2 is 8 bit */ if (val > 0xFF) val = 0xFF; if (pwmp->config->channels[channel].callback) { switch (channel) { case 0: OCR2A = val; break; case 1: OCR2B = val; break; } } return; } #endif uint8_t i = timer_index(pwmp); config_channel(regs_table[i].tccra, 7 - 2*channel, 6 - 2*channel, pwmp->config->channels[channel].mode); volatile uint8_t *ocrh, *ocrl; switch (channel) { case 1: ocrh = regs_table[i].ocrbh; ocrl = regs_table[i].ocrbl; break; case 2: ocrh = regs_table[i].ocrch; ocrl = regs_table[i].ocrcl; break; default: ocrh = regs_table[i].ocrah; ocrl = regs_table[i].ocral; } *ocrh = val >> 8; *ocrl = val & 0xFF; *regs_table[i].tifr |= (1 << (channel + 1)); if (pwmp->config->channels[channel].callback) *regs_table[i].timsk |= (1 << (channel + 1)); }
/** * @brief Configures and activates the PWM peripheral. * * @param[in] pwmp pointer to the @p PWMDriver object * * @notapi */ void pwm_lld_start(PWMDriver *pwmp) { if (pwmp->state == PWM_STOP) { #if AVR_PWM_USE_TIM2 || defined(__DOXYGEN__) if (pwmp == &PWMD2) { TCCR2B &= ~((1 << CS22) | (1 << CS21)); TCCR2B |= (1 << CS20); if (pwmp->config->callback != NULL) TIMSK2 |= (1 << TOIE2); return; } #endif /* TODO: support other prescaler options */ uint8_t i = timer_index(pwmp); *regs_table[i].tccrb &= ~(1 << CS11); *regs_table[i].tccrb |= (1 << CS12) | (1 << CS10); *regs_table[i].timsk = (1 << TOIE1); } }
/** * @brief Disables a channel de-activation edge notification. * @pre The PWM unit must have been activated using @p pwmStart(). * @pre The channel must have been activated using @p pwmEnableChannel(). * @note If the notification is already disabled then the call has no effect. * * @param[in] pwmp pointer to a @p PWMDriver object * @param[in] channel PWM channel identifier (0...channels-1) * * @notapi */ void pwm_lld_disable_channel_notification(PWMDriver *pwmp, pwmchannel_t channel) { uint8_t i = timer_index(pwmp); *regs_table[i].timsk &= ~(1 << (channel + 1)); }
/** * @brief Disables the periodic activation edge notification. * @pre The PWM unit must have been activated using @p pwmStart(). * @note If the notification is already disabled then the call has no effect. * * @param[in] pwmp pointer to a @p PWMDriver object * * @notapi */ void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) { uint8_t i = timer_index(pwmp); *regs_table[i].timsk &= ~(1 << TOIE1); }
/** * @brief Deactivates the PWM peripheral. * * @param[in] pwmp pointer to the @p PWMDriver object * * @notapi */ void pwm_lld_stop(PWMDriver *pwmp) { uint8_t i = timer_index(pwmp); *regs_table[i].tccrb &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); *regs_table[i].timsk = 0; }