#include "gw3323_tmr.h"

/**
  * @brief  Initializes the timer base peripheral according to the specified
  *         parameters in the tmr_base_init_typedef.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  tmr_base_init_struct: pointer to a tmr_base_init_typedef structure that
  *         contains the configuration information for the specified TMR peripheral.
  * @retval None
  */
void tmr_base_init(tmr_typedef *tmrx, tmr_base_init_typedef *tmr_base_init_struct)
{
    //---------- uart controller register ----------//
    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
        tmrx->con &= ~(uint32_t)TMR_CON1_INCSRC;
        tmrx->con |= (uint32_t)tmr_base_init_struct->clock_source;

        tmrx->con &= ~(uint32_t)TMR_CON1_INCSEL;
        tmrx->con |= (uint32_t)tmr_base_init_struct->increase_clock;
    } else if (tmrx == TMR3 || tmrx == TMR4 || tmrx == TMR5) {
        tmrx->con &= ~(uint32_t)TMR_CON2_INCSRC;
        tmrx->con |= (uint32_t)tmr_base_init_struct->clock_source;

        tmrx->con &= ~(uint32_t)TMR_CON2_INCSEL;
        tmrx->con |= (uint32_t)tmr_base_init_struct->increase_clock;

        if (tmr_base_init_struct->pwm_mode == TMR_PWM_MODE_0) {
            tmrx->con |= (uint32_t)TMR_CON2_PWM0EN;
            tmrx->duty0 = (uint32_t)(tmr_base_init_struct->pwm_duty);
        } else if (tmr_base_init_struct->pwm_mode == TMR_PWM_MODE_1) {
            tmrx->con |= (uint32_t)TMR_CON2_PWM1EN;
            tmrx->duty1 = (uint32_t)(tmr_base_init_struct->pwm_duty);
        } else if (tmr_base_init_struct->pwm_mode == TMR_PWM_MODE_2) {
            tmrx->con |= (uint32_t)TMR_CON2_PWM2EN;
            tmrx->duty2 = (uint32_t)(tmr_base_init_struct->pwm_duty);
        }
    }
    tmrx->pr = (uint32_t)(tmr_base_init_struct->period);
}

/**
  * @brief  Set the TMR counter register value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  cnt: specifies the counter register new value.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_set_counter(tmr_typedef *tmrx, uint32_t cnt)
{
    tmrx->cnt = cnt;
}

/**
  * @brief  Set the TMR period register value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  period: specifies the period register new value.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_set_period(tmr_typedef *tmrx, uint32_t period)
{
    tmrx->pr = period;
}

/**
  * @brief  Get the TMR counter register value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @retval specifies the counter register value.
  */
AT(.com_text.tmr)
uint32_t tmr_get_counter(tmr_typedef *tmrx)
{
    return (uint32_t)(tmrx->cnt);
}

/**
  * @brief  Get the TMR period register value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @retval specifies the period register value.
  */
AT(.com_text.tmr)
uint32_t tmr_get_period(tmr_typedef *tmrx)
{
    return (uint32_t)(tmrx->pr);
}

/**
  * @brief  Enable or disable the specified TMR peripheral.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  state: state of the TMRx peripheral.
            This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_cmd(tmr_typedef *tmrx, FUNCTIONAL_STATE state)
{
    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
        if (state != DISABLE) {
            tmrx->con |= (uint32_t)TMR_CON1_TMREN;
        } else {
            tmrx->con &= (uint32_t)~((uint32_t)TMR_CON1_TMREN);
        }
    } else if (tmrx == TMR3 || tmrx == TMR4 || tmrx == TMR5) {
        if (state != DISABLE) {
            tmrx->con |= (uint32_t)TMR_CON2_TMREN;
        } else {
            tmrx->con &= (uint32_t)~((uint32_t)TMR_CON2_TMREN);
        }
    }
}

/**
  * @brief  Set the TMR pwm0 comparison value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  duty: specifies the duty register new value.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_set_pwm0_duty(tmr_typedef *tmrx, uint32_t duty)
{
    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
        return;
    }
    tmrx->duty0 = (uint32_t)(duty & 0xffff);
}

/**
  * @brief  Set the TMR pwm1 comparison value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  duty: specifies the duty register new value.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_set_pwm1_duty(tmr_typedef *tmrx, uint32_t duty)
{
    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
        return;
    }
    tmrx->duty1 = (uint32_t)(duty & 0xffff);
}

/**
  * @brief  Set the TMR pwm2 comparison value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  duty: specifies the duty register new value.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_set_pwm2_duty(tmr_typedef *tmrx, uint32_t duty)
{
    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
        return;
    }
    tmrx->duty2 = (uint32_t)(duty & 0xffff);
}

/**
  * @brief  Configure input capture for TMR.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  edge_select: Captured edge selection.
  *         this parameter can be one of the following values:
  *             @arg TMR_CAP_NULL: no capture.
  *             @arg TMR_CAP_RISING: capture rising edge.
  *             @arg TMR_CAP_FALLING: capture falling edge.
  *             @arg TMR_CAP_EDGE: capture bilateral edge.
  * @param  state: state of the TMRx capture.
            This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_capture_config(tmr_typedef *tmrx, TMR_CAP_EDGE_TYPEDEF edge_select, FUNCTIONAL_STATE state)
{
    if (state == ENABLE) {
        tmrx->con &= ~((uint32_t)TMR_CON2_CPTEDSEL);
        tmrx->con |= (uint32_t)edge_select;

        tmrx->con |= (uint32_t)TMR_CON2_CPTEN;
    } else if (state == DISABLE) {
        tmrx->con &= ~((uint32_t)TMR_CON2_CPTEDSEL);
        tmrx->con &= ~((uint32_t)TMR_CON2_CPTEN);
    }
}

/**
  * @brief  Get the TMR capture register value.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @retval specifies the capture register value.
  */
AT(.com_text.tmr)
uint32_t tmr_get_capture(tmr_typedef *tmrx)
{
    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
        return ~((uint32_t)0);
    }
    return (uint32_t)(tmrx->cpt_val);
}

/**
  * @brief  Enable or disable the specified TMRx interrupt.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  isr: Function to be executed for service interruption.
  * @param  pr: Priority of service interruption.
  * @param  tmr_ie_bit: specifies the TRMx interrupt sources to be enable or disable.
  *         this parameter can be one of the following values:
  *             @arg TMR_IT_UPDATE1: TMR(1..2) overflow interrupt enable bit.
  *             @arg TMR_IT_CAP: TMR(3..5) capture interrupt enable bit.
  *             @arg TMR_IT_UPDATE2: TMR(3..5) overflow interrupt enable bit.
  * @param  state: the state of the TMRx peripheral.
  *         this parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void tmr_pic_config(tmr_typedef *tmrx, isr_t isr, int pr, uint16_t tmr_ie_bit, FUNCTIONAL_STATE state)
{
    u8 irq_vector;

    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
        if ((tmr_ie_bit & TMR_IT_CAP) != RESET) {
            return;
        }
    }

    if (tmrx == TMR1) {
        irq_vector = IRQ_TMR1_VECTOR;
    } else if (tmrx == TMR2) {
        irq_vector = IRQ_TMR2_VECTOR;
    } else if (tmrx == TMR3) {
        irq_vector = IRQ_TMR3_VECTOR;
    } else if (tmrx == TMR4) {
        irq_vector = IRQ_TMR4_VECTOR;
    } else if (tmrx == TMR5) {
        irq_vector = IRQ_TMR5_VECTOR;
    } else {
        return;
    }

    if (state != DISABLE) {
        tmrx->con |= (uint32_t)tmr_ie_bit;
        sys_irq_init(irq_vector, pr, isr);
    } else {
        tmrx->con &= ~(uint32_t)tmr_ie_bit;
    }
}

/**
  * @brief  Get the TMR interrupt pending.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  tmr_flag: specifies the flag to clear.
  *         this parameter can be one of the following values:
  *             @arg TMR_FLAG_UPDATE1: TMR(1..2) overflow interrupt.
  *             @arg TMR_FLAG_CAP: TMR(3..5) capture interrupt.
  *             @arg TMR_FLAG_UPDATE2: TMR(3..5) overflow interrupt.
  * @retval The state of tmr_flag (SET or RESET).
  */
AT(.com_text.tmr)
FLAG_STATE tmr_get_flag(tmr_typedef *tmrx, uint32_t tmr_flag)
{
    if ((tmrx->con & tmr_flag) != RESET) {
        return SET;
    } else {
        return RESET;
    }
}

/**
  * @brief  Clear the TMR interrupt pending.
  * @param  tmrx: where x can be (1..5) to select the TMR peripheral.
  * @param  tmr_flag: specifies the flag to clear.
  *         this parameter can be one of the following values:
  *             @arg TMR_FLAG_UPDATE1: TMR(1..2) overflow interrupt.
  *             @arg TMR_FLAG_CAP: TMR(3..5) capture interrupt.
  *             @arg TMR_FLAG_UPDATE2: TMR(3..5) overflow interrupt.
  * @retval None
  */
AT(.com_text.tmr)
void tmr_clear_flag(tmr_typedef *tmrx, uint32_t tmr_flag)
{
    tmrx->cpnd |= (uint32_t)(tmr_flag);
}
