#include "bsp/bsp_driver.h"
#include "libs/logger.h"

static void _io_init(void) {
	rcu_periph_clock_enable(ENC_A_RCU);
	rcu_periph_clock_enable(ENC_B_RCU);
	rcu_periph_clock_enable(ENC_PWM_RCU);
	rcu_periph_clock_enable(ENC_I_RCU);
#ifdef TIMER2_PB4_PB5_REMAP
	gpio_pin_remap_config(TIMER2_PB4_PB5_REMAP, ENABLE);
#endif
#ifdef TIMER1_PA15_REMAP
	gpio_pin_remap_config(TIMER1_PA15_REMAP, ENABLE);
#endif
	gpio_init(ENC_A_GROUP, ENC_A_MODE, GPIO_OSPEED_50MHZ, ENC_A_PIN);
	gpio_init(ENC_B_GROUP, ENC_B_MODE, GPIO_OSPEED_50MHZ, ENC_B_PIN);
	gpio_init(ENC_PWM_GROUP, ENC_PWM_MODE, GPIO_OSPEED_50MHZ, ENC_PWM_PIN);
	gpio_init(ENC_I_GROUP, ENC_I_MODE, GPIO_OSPEED_50MHZ, ENC_I_PIN);
}

static void _io_init_irq(void) {
	gpio_exti_source_select(ENC_I_EXIT_SRC_GROUP, ENC_I_EXIT_SRC_PIN);
	exti_init(ENC_I_EXTI, EXTI_INTERRUPT, EXTI_TRIG_RISING);
	exti_interrupt_flag_clear(ENC_I_EXTI);
	exti_interrupt_enable(ENC_I_EXTI);

	nvic_irq_enable(ENC_I_IRQ, ENC_I_EXIT_IRQ_PRIORITY, 0U);
}

void enc_intf_init(u32 rate) {
	_io_init();
	enc_intf_pwm_counter();
	enc_intf_quadrature_init(rate);
	_io_init_irq();
}

void enc_intf_quadrature_init(u32 rate) {
	timer_parameter_struct timer_initpara;
	timer_ic_parameter_struct timer_icinitpara;

	u32 timer = ENC_TIMER;

	rcu_periph_clock_enable(ENC_TIMER_RCU);

	timer_deinit(timer);

	/* TIMER configuration */
	timer_struct_para_init(&timer_initpara);
	timer_initpara.prescaler		= 0;//TIM_CLOCK/PWM_TIME_CLK - 1;
	timer_initpara.alignedmode		= TIMER_COUNTER_EDGE;
	timer_initpara.counterdirection  = TIMER_COUNTER_UP;
	timer_initpara.period		   = rate-1;
	timer_initpara.clockdivision	= TIMER_CKDIV_DIV1;
	timer_initpara.repetitioncounter = 0;
	timer_init(timer,&timer_initpara);

    /* initialize TIMER channel input parameter struct */
    timer_channel_input_struct_para_init(&timer_icinitpara);
    /* TIMER2 CH0 input capture configuration */
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = ENC_FILTER_NR;//采样频率120M, 这个必须要加入滤波，否则AB的计数可能不对
    timer_input_capture_config(timer,TIMER_CH_0,&timer_icinitpara);
	
	timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
	timer_input_capture_config(timer,TIMER_CH_1,&timer_icinitpara);

	timer_quadrature_decoder_mode_config(timer ,TIMER_ENCODER_MODE2,TIMER_IC_POLARITY_FALLING, TIMER_IC_POLARITY_RISING);
	
	/* auto-reload preload enable */
	timer_auto_reload_shadow_enable(timer);	

	
	timer_interrupt_flag_clear(timer, TIMER_INT_FLAG_UP);

	//timer_interrupt_enable(timer, TIMER_INT_UP);
	//nvic_irq_enable(ENC_TIMER_IRQ, ENC_TIMER_IRQ_PRIORITY, 0);

	/* TIMER2 counter enable */
	timer_enable(timer);
}

void enc_intf_pwm_counter(void) {
	timer_ic_parameter_struct timer_icinitpara;
	timer_parameter_struct timer_initpara;
	u32 timer = ENC_PWM_TIMER;

	rcu_periph_clock_enable(ENC_PWM_TIMER_RCU);

	timer_deinit(timer);

	/* TIMER configuration */
	timer_struct_para_init(&timer_initpara);
	timer_initpara.prescaler		= TIM_CLOCK/PWM_TIME_CLK - 1;
	timer_initpara.alignedmode		= TIMER_COUNTER_EDGE;
	timer_initpara.counterdirection  = TIMER_COUNTER_UP;
	timer_initpara.period		   = 65535;
	timer_initpara.clockdivision	= TIMER_CKDIV_DIV1;
	timer_initpara.repetitioncounter = 0;
	timer_init(timer,&timer_initpara);

	timer_channel_input_struct_para_init(&timer_icinitpara);
	/* TIMER CH0 PWM input capture configuration */
	timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
	timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
	timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
	timer_icinitpara.icfilter	 = ENC_FILTER_NR;
	timer_input_pwm_capture_config(timer, ENC_PWM_TIMER_CHAN, &timer_icinitpara);

	/* slave mode selection: TIMER */
	timer_input_trigger_source_select(timer, TIMER_SMCFG_TRGSEL_CI0FE0);
	timer_slave_mode_select(timer, TIMER_SLAVE_MODE_RESTART);

	/* select the master slave mode */
	timer_master_slave_mode_config(timer, TIMER_MASTER_SLAVE_MODE_ENABLE);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(timer);
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(timer, ENC_PWM_TIMER_INT_FLG);
    /* channel 0 interrupt enable */
    timer_interrupt_enable(timer, ENC_PWM_TIMER_IRQ_CH);
	nvic_irq_enable(ENC_PWM_TIMER_IRQ, ENC_PWM_IRQ_PRIORITY, 0);
    /* TIMER2 counter enable */
    timer_enable(timer);
}

__weak void ENC_TIMER_Overflow(void) {

}

void ENC_TIMER_IRQHandler(void) {
	if (SET == timer_interrupt_flag_get(ENC_TIMER, TIMER_INT_FLAG_UP)) {
		timer_interrupt_flag_clear(ENC_TIMER, TIMER_INT_FLAG_UP);
		ENC_TIMER_Overflow();
	}
}


__weak void ENC_ABI_IRQHandler(void) {

}

void ABI_I_IRQHandler(void) {
	ENC_ABI_IRQHandler();
}

__weak void ENC_PWM_Duty_Handler(float t, float d) {

}

static float pwm_freq = 0.0f;
void ENC_PWM_IRQHandler(void) {
    if(SET == timer_interrupt_flag_get(ENC_PWM_TIMER, ENC_PWM_TIMER_INT_FLG)){
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(ENC_PWM_TIMER, ENC_PWM_TIMER_INT_FLG);
        /* read channel 0 capture value */
        u32 ic0value = TIMER_CH0CV(ENC_PWM_TIMER)+1;
		u32 ic1value = TIMER_CH1CV(ENC_PWM_TIMER)+1;
		float p_calc = ENC_PWM_Calc_P(ic0value);
		float d_calc = ENC_PWM_Calc_P(ic1value);
		ENC_PWM_Duty_Handler(p_calc, d_calc);
		pwm_freq = (float)PWM_TIME_CLK/((float)ic0value);
    }
}

float enc_get_pwm_freq(void) {
	return pwm_freq;
}
