#define PWM_COUNTER_OVERFLOW 2000U // To get ~50kHz

// TODO: Implement for 32-bit timers

void pwm_init(TIM_TypeDef *TIM, uint8_t channel){
    // Enable timer and auto-reload
    register_set(&(TIM->CR1), TIM_CR1_CEN | TIM_CR1_ARPE, 0x3FU);

    // Set channel as PWM mode 1 and enable output
    switch(channel){
        case 1U:
            register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE));
            register_set_bits(&(TIM->CCER), TIM_CCER_CC1E);
            break;
        case 2U:
            register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE));
            register_set_bits(&(TIM->CCER), TIM_CCER_CC2E);
            break;
        case 3U:
            register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE));
            register_set_bits(&(TIM->CCER), TIM_CCER_CC3E);
            break;
        case 4U:
            register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE));
            register_set_bits(&(TIM->CCER), TIM_CCER_CC4E);
            break;
        default:
            break;
    }

    // Set max counter value
    register_set(&(TIM->ARR), PWM_COUNTER_OVERFLOW, 0xFFFFU);

    // Update registers and clear counter
    TIM->EGR |= TIM_EGR_UG;
}

void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage){
    uint16_t comp_value = (((uint16_t) percentage * PWM_COUNTER_OVERFLOW) / 100U);
    switch(channel){
        case 1U:
            register_set(&(TIM->CCR1), comp_value, 0xFFFFU);
            break;
        case 2U:
            register_set(&(TIM->CCR2), comp_value, 0xFFFFU);
            break;
        case 3U:
            register_set(&(TIM->CCR3), comp_value, 0xFFFFU);
            break;
        case 4U:
            register_set(&(TIM->CCR4), comp_value, 0xFFFFU);
            break;
        default:
            break;
    }
}
