Repository: raspberrypi/pico-sdk
File: src/rp2_common/hardware_pwm/include/hardware/pwm.h (C/C++)

Code before:
 *
 * \param c PWM configuration struct to modify
 * \param phase_correct true to set phase correct modulation, false to set trailing edge
 *
 * Setting phase control to true means that instead of wrapping back to zero when the wrap point is reached,
 * the PWM starts counting back down. The output frequency is halved when phase-correct mode is enabled.
 */
static inline void pwm_config_set_phase_correct(pwm_config *c, bool phase_correct) {
    c->csr = (c->csr & ~PWM_CH0_CSR_PH_CORRECT_BITS)
        | (bool_to_bit(phase_correct) << PWM_CH0_CSR_PH_CORRECT_LSB);
}

/** \brief Set PWM clock divider in a PWM configuration
 *  \ingroup hardware_pwm
 *
 * \param c PWM configuration struct to modify
 * \param div Value to divide counting rate by. Must be greater than or equal to 1.
 *
 * If the divide mode is free-running, the PWM counter runs at clk_sys / div.
 * Otherwise, the divider reduces the rate of events seen on the B pin input (level or edge)
 * before passing them on to the PWM counter.
 */
static inline void pwm_config_set_clkdiv(pwm_config *c, float div) {
    valid_params_if(HARDWARE_PWM, div >= 1.f && div < 256.f);
#if PICO_PWM_CLKDIV_ROUND_NEAREST
    div += 0.5f / (1 << PWM_CH0_DIV_INT_LSB); // round to the nearest fraction
#endif
    c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB));
}

/** \brief Set PWM clock divider in a PWM configuration using an 8:4 fractional value
 *  \ingroup hardware_pwm
 *
 * \param c PWM configuration struct to modify
 * \param div_int 8 bit integer part of the clock divider. Must be greater than or equal to 1.
 * \param div_frac4 4 bit fractional part of the clock divider
 *
 * If the divide mode is free-running, the PWM counter runs at clk_sys / div.
 * Otherwise, the divider reduces the rate of events seen on the B pin input (level or edge)
 * before passing them on to the PWM counter.
 */
static inline void pwm_config_set_clkdiv_int_frac4(pwm_config *c, uint32_t div_int, uint8_t div_frac4) {
    static_assert(PWM_CH0_DIV_INT_MSB - PWM_CH0_DIV_INT_LSB == 7, "");
    valid_params_if(HARDWARE_PWM, div_int >= 1 && div_int < 256);
    static_assert(PWM_CH0_DIV_FRAC_MSB - PWM_CH0_DIV_FRAC_LSB == 3, "");
    valid_params_if(HARDWARE_PWM, div_frac4 < 16);
    c->div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
}

// backwards compatibility
static inline void pwm_config_set_clkdiv_int_frac(pwm_config *c, uint8_t div_int, uint8_t div_frac4) {

Review comment (suggestion):
Sorry - why are we using PWM_CH0_DIV_INT_LSB here rather than PWM_CH0_DIV_FRAC_MSB+1 - PWM_CH0_DIV_FRAC_LSB. Isn't it coincidence that it's the right value? It confuses me because there are 8 bits for the pwm int.

Code after:
 *
 * \param c PWM configuration struct to modify
 * \param phase_correct true to set phase correct modulation, false to set trailing edge
 *
 * Setting phase control to true means that instead of wrapping back to zero when the wrap point is reached,
 * the PWM starts counting back down. The output frequency is halved when phase-correct mode is enabled.
 */
static inline void pwm_config_set_phase_correct(pwm_config *c, bool phase_correct) {
    c->csr = (c->csr & ~PWM_CH0_CSR_PH_CORRECT_BITS)
        | (bool_to_bit(phase_correct) << PWM_CH0_CSR_PH_CORRECT_LSB);
}

/** \brief Set PWM clock divider in a PWM configuration
 *  \ingroup hardware_pwm
 *
 * \param c PWM configuration struct to modify
 * \param div Value to divide counting rate by. Must be greater than or equal to 1.
 *
 * If the divide mode is free-running, the PWM counter runs at clk_sys / div.
 * Otherwise, the divider reduces the rate of events seen on the B pin input (level or edge)
 * before passing them on to the PWM counter.
 */
static inline void pwm_config_set_clkdiv(pwm_config *c, float div) {
    valid_params_if(HARDWARE_PWM, div >= 1.f && div < 256.f);
    const int frac_bit_count = REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC);
#if PICO_PWM_CLKDIV_ROUND_NEAREST
    div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
#endif
    c->div = (uint32_t)(div * (float)(1u << frac_bit_count));
}

/** \brief Set PWM clock divider in a PWM configuration using an 8:4 fractional value
 *  \ingroup hardware_pwm
 *
 * \param c PWM configuration struct to modify
 * \param div_int 8 bit integer part of the clock divider. Must be greater than or equal to 1.
 * \param div_frac4 4 bit fractional part of the clock divider
 *
 * If the divide mode is free-running, the PWM counter runs at clk_sys / div.
 * Otherwise, the divider reduces the rate of events seen on the B pin input (level or edge)
 * before passing them on to the PWM counter.
 */
static inline void pwm_config_set_clkdiv_int_frac4(pwm_config *c, uint32_t div_int, uint8_t div_frac4) {
    static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_INT) == 8, "");
    valid_params_if(HARDWARE_PWM, div_int >= 1 && div_int < 256);
    static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC) == 4, "");
    valid_params_if(HARDWARE_PWM, div_frac4 < 16);
    c->div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
}

// backwards compatibility