/***********************************************************************
 * Copyright (c)  2017 - 2022, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : gtimer2.c
 * Description : gtimer2 driver source file
 * Author(s)   : Sissi
 * version     : V1.0
 * Modify date : 2022-08-08
 ***********************************************************************/
#include "gtimer.h"

void (*gtimer2_callback[4])(void) = { 0 };

/************************************************************************
 * Function   	: GTIMER2_IRQHandler
 * Description	: gtimer2中断处理函数
 * Input 		: none
 * Output 		: none
 * Return		: none
 ************************************************************************/
void GTIMER2_IRQHandler(void)
{
	if((REG_GTIM2_SR & VAL_GTIM_UIF) && (REG_GTIM2_IER & VAL_GTIM_UIE))				//UE中断
	{
		if(gtimer2_callback[0] != NULL)
		{
			gtimer2_callback[0]();	
			REG_GTIM2_SR = VAL_GTIM_UIF;											//清除UE中断标志
		}		
	}	
	else if((REG_GTIM2_SR & VAL_GTIM_CCIF) && (!(REG_GTIM2_CCMR & VAL_GTIM_CCS)) && (REG_GTIM2_IER & VAL_GTIM_CCIE))	
	{                                                                               //比较中断
		if(gtimer2_callback[1] != NULL)
		{
			gtimer2_callback[1]();	
			REG_GTIM2_SR = VAL_GTIM_CCIF;											//清除比较中断标志
		}	
	}
	else if((REG_GTIM2_SR & VAL_GTIM_CCIF) && ((REG_GTIM2_CCMR & VAL_GTIM_CCS)) && (REG_GTIM2_IER & VAL_GTIM_CCIE))		
	{                                                                               //捕捉中断
		if(gtimer2_callback[2] != NULL)
		{
			gtimer2_callback[2]();	
			REG_GTIM2_SR = VAL_GTIM_CCIF;											//清除捕捉中断标志
		}	
	}	
	else if((REG_GTIM2_SR & VAL_GTIM_BKEF) && (REG_GTIM2_IER & VAL_GTIM_BKE_IE))	//刹车中断
	{
		if(gtimer2_callback[3] != NULL)
		{
			gtimer2_callback[3]();	
			REG_GTIM2_SR = VAL_GTIM_BKEF;											//清除刹车中断标志
		}	
	}
	else
	{
		REG_GTIM2_SR = VAL_GTIM_SRCLEAR;											//清除所有中断状态
	}	
}

/************************************************************************
 * function   : gtimer2_caen 
 * Description: gtimer2_使能受cen_all控制
 * input      : none
 * output     : none
 * return     : none
 ************************************************************************/
void gtimer2_caen(void)
{
	REG_GTIM2_CR |= (1<<3);
}

/************************************************************************
 * function   : gtimer2_cen_all
 * Description: gtimer2使能Atimer,Btimer,Gtimer,LPtimer cen = 1
 * input      : none
 * output     : none
 * return     : none
 ************************************************************************/
void gtimer2_cen_all(void)
{
	REG_GTIM2_CR |= (1<<12);
}

/************************************************************************
 * Function   	: gtimer2_count_init
 * Description	: gtimer2定时器初始化
 * Input 		: uint8_t  clk_src 	 计数时钟源选择
 *            	  uint16_t arr 		 重载值设置
 *			  	  uint16_t psc 		 预分频值设置
 * Output 		: none
 * Return		: none
 ************************************************************************/
void gtimer2_count_init(uint8_t clk_src,uint16_t arr,uint16_t psc)
{
	REG_SCU_PERIRESET |= GTIMER2_RESET;											//gtimer2正常工作
	REG_SCU_PERICLKEN |= GTIMER2_CLKEN;											//开gtimer2时钟使能	
	
	REG_GTIM2_CCMR = (REG_GTIM2_CCMR & ~(3<<4)) | clk_src;	//选择计数时钟源
	
	REG_GTIM2_ARR = arr;														//重载值
	REG_GTIM2_PSC = psc;														//f(CNT) = f(CLK) / (psc + 1);
	REG_GTIM2_EGR = VAL_EGR;													//产生UE事件，将PSC的值立即载入shadow寄存器
	REG_GTIM2_SR  = VAL_GTIM_SRCLEAR;											//清除所有中断
	
	REG_GTIM2_CR |= VAL_GTIM_EDGE_ALIGN;										//边沿对齐模式	
	REG_GTIM2_CR |= VAL_GTIM_EDGE_DIR_UP; 									    //向上计数
}

/************************************************************************
 * Function   	: gtimer2_pwm_init
 * Description	: gtimer2 PWM输出初始化
 * Input 		: uint8_t  clk_src 	计数时钟源选择
 *            	  uint16_t arr 		重载值设置
 *				  uint16_t arr 		比较值设置
 *			  	  uint16_t psc 		预分频值设置
 * Output 		: none
 * Return		: none
 ************************************************************************/
void gtimer2_pwm_init(uint8_t clk_src,uint16_t arr,uint16_t ccr,uint16_t psc)
{
	REG_SCU_PERIRESET |= GTIMER2_RESET;							//gtimer2正常工作
	REG_SCU_PERICLKEN |= GTIMER2_CLKEN;							//开gtimer2时钟使能	
	
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 						//清除IO写保护
	
	REG_SCU_PGSEL = (REG_SCU_PGSEL&(~(0xF<<24)))|(0x8<<24);		//PG6复用为GTIM2_CH
	REG_SCU_PGSEL = (REG_SCU_PGSEL&(~(0xF<<20)))|(0xA<<20);		//PG5复用为GTIM2_CHN
	
	REG_SCU_IOCTRLPROTECT = 0xffffffff; 						//开启IO写保护
	
	REG_GTIM2_CCMR = (REG_GTIM2_CCMR & ~(3<<4)) | clk_src;		//选择计数时钟源
	
	REG_GTIM2_ARR = arr|((arr)<<16);							//重载值
	REG_GTIM2_CCR = ccr|((ccr)<<16);							//比较值
	REG_GTIM2_PSC = psc;										//f(CNT) = f(CLK) / (psc + 1);
	REG_GTIM2_EGR = VAL_EGR;								    //产生UE事件，将PSC的值立即载入shadow寄存器
	REG_GTIM2_SR  = VAL_GTIM_SRCLEAR;							//清除所有中断
	
	REG_GTIM2_CR |= VAL_GTIM_PWM_DEAD_ENABLE;								//避免死区功能使能,使能此位才能输出互补的PWM波
	REG_GTIM2_CR |= VAL_GTIM_PWM_INV_ENABLE;		     					//互补PWM和原PWM反相位
	
	REG_GTIM2_CR  = (REG_GTIM2_CR&(~(0x3<<4)))|VAL_GTIM_EDGE_ALIGN;			//边沿对齐模式	
	REG_GTIM2_CR  = (REG_GTIM2_CR&(~(0x1<<2)))|VAL_GTIM_EDGE_DIR_UP;	    //向上计数

	REG_GTIM2_CCMR = (REG_GTIM2_CCMR&(~(0x1<<0)))|VAL_GTIM_CCS_OUTPUT;		//CC通道配置为输出
	
	REG_GTIM2_CCER = (REG_GTIM2_CCER&(~(0x1<<1)))|VAL_GTIM_CCP_HIGH;	    //CNT<CCR时输出高电平
	REG_GTIM2_CCER = (REG_GTIM2_CCER&(~(0x1<<0)))|VAL_GTIM_CCE_ENABLE;		//比较输出使能	
}

/************************************************************************
 * Function   	: gtimer2_capture_init
 * Description	: gtimer2输入捕获初始化
 * Input 		: uint8_t  clk_src 	   计数时钟源选择
 *            	  uint16_t arr 		   重载值设置
 *			  	  uint16_t psc 		   预分频值设置
 *                uint8_t  cap_div     捕捉源分频设置
 * Output 		: none
 * Return		: none
 ************************************************************************/
void gtimer2_capture_init(uint8_t clk_src,uint16_t arr,uint16_t psc,uint8_t cap_div) 
{
	REG_SCU_PERIRESET |= GTIMER2_RESET;										//gtimer2正常工作
	REG_SCU_PERICLKEN |= GTIMER2_CLKEN;										//开gtimer2时钟使能	
		
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 									//清除IO写保护
		
	REG_SCU_PGSEL = (REG_SCU_PGSEL&(~(0xF<<0)))|(0x9<<0);			        //PG0复用为GTIM2_CH
			
	REG_SCU_IOCTRLPROTECT = 0xffffffff; 									//开启IO写保护
	
	REG_GTIM2_CCMR |= VAL_GTIM_CAPSSEL_GTIMERx_CH;							//选择捕捉源
	REG_GTIM2_CCMR = (REG_GTIM2_CCMR & ~(3<<13)) | cap_div;					//捕捉源预分频
	REG_GTIM2_CCMR |= VAL_GTIM_CAPEDGE_UP;									//捕捉源上升沿触发
		
	REG_GTIM2_CCMR = (REG_GTIM2_CCMR & ~(3<<4)) | clk_src;					//选择计数时钟源
	REG_GTIM2_ARR = arr;													//重载值
	REG_GTIM2_PSC = psc;													//f(CNT) = f(CLK) / (psc + 1);
	REG_GTIM2_EGR = VAL_EGR;												//产生UE事件，将PSC的值立即载入shadow寄存器
	REG_GTIM2_SR  = VAL_GTIM_SRCLEAR;										//清除所有中断
		
	REG_GTIM2_CCMR = (REG_GTIM2_CCMR&(~(0x1<<0)))|VAL_GTIM_CCS_INPUT;		//CC通道配置为输出
	
	REG_GTIM2_CCER = (REG_GTIM2_CCER&(~(0x1<<0)))|VAL_GTIM_CCE_ENABLE;;		//捕捉使能	
}

/************************************************************************
 * Function   	: gtimer2_bke_init
 * Description	: gtimer2 硬件刹车初始化
 * Input 		: uint32_t bke_src	刹车源设置
 *            	  uint32_t bke_pol	刹车信号触发极性
 * Output 	    : none
 * Return		: none
 ************************************************************************/
void gtimer2_bke_init(uint32_t bke_src,uint32_t bke_pol)
{
	REG_SCU_PERIRESET |= GTIMER2_RESET;									//gtimer2正常工作
	REG_SCU_PERICLKEN |= GTIMER2_CLKEN;									//开gtimer2时钟使能	
	
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 								//清除IO写保护
	
	REG_SCU_PESEL = (REG_SCU_PESEL&(~(0xF<<16)))|(0x5<<16);		        //PE4复用为GTIMER2_BK 

	REG_SCU_IOCTRLPROTECT = 0xffffffff; 								//开启IO写保护
	
	REG_GTIM2_CR = (REG_GTIM2_CR & ~(0xFF<<21)) | bke_src;				//刹车源选择
	
	REG_GTIM2_CR = (REG_GTIM2_CR & ~(1<<11)) | bke_pol;     			//刹车信号触发极性
	
	REG_GTIM2_CR &= ~VAL_GTIM_PWMN_IDLE; 								//PWM输出负向电平IDLE状态为低电平
	REG_GTIM2_CR &= ~VAL_GTIM_PWMP_IDLE; 								//PWM输出正向电平IDLE状态为低电平
	
	REG_GTIM2_CR &= ~VAL_GTIM_PWMN_B_S;    								//PWM刹车触发后，PWM互补电平状态设置位为低电平
	REG_GTIM2_CR &= ~VAL_GTIM_PWMS_B_S;     							//PWM刹车触发后，PWM正向电平状态设置位为低电平
	
	REG_GTIM2_CR |= VAL_GTIM_BKE;           							//刹车功能使能	
}

/************************************************************************
 * Function   	: gtimer2_irq_init
 * Description	: gtimer2中断初始化
 * Input 	    : uint8_t irq_enable	  中断使能开关 1：使能 0：禁止
				  uint8_t gtimer_irq_type 中断类型选择
 *            	  void (*pfunc)()		  中断回调函数
 * Output 		: none
 * Return		: none
 ************************************************************************/	
void gtimer2_irq_init(uint8_t irq_enable,uint8_t gtimer_irq_type,void (*pfunc)())
{
	REG_GTIM2_SR = VAL_GTIM_SRCLEAR;							//清除所有中断状态
	
	if(irq_enable == GTIM_IRQ_ENABLE)
	{
		switch(gtimer_irq_type)
		{
			case GTIM_UE_IRQ:
					gtimer2_callback[0] = pfunc;
					REG_GTIM2_IER |= VAL_GTIM_UIE;				//使能UPDATE中断
					break;
			case GTIM_COMP_IRQ:
					gtimer2_callback[1] = pfunc;
					REG_GTIM2_IER |= VAL_GTIM_CCIE;				//使能比较中断
					break;
			case GTIM_CAP_IRQ:
					gtimer2_callback[2] = pfunc;
					REG_GTIM2_IER |= VAL_GTIM_CCIE;				//使能捕捉中断
					break;
			case GTIM_BKE_IRQ:
					gtimer2_callback[3] = pfunc;
					REG_GTIM2_IER |= VAL_GTIM_BKE_IE;			//使能刹车中断
					break;					
			default:
					break;	
		}
		NVIC_ClearPendingIRQ(GTIMER2_IRQn);
		NVIC_EnableIRQ(GTIMER2_IRQn);
	}
	else
	{
		switch(gtimer_irq_type)
		{
			case GTIM_UE_IRQ:
					gtimer2_callback[0] = NULL;
					REG_GTIM2_IER &= ~VAL_GTIM_UIE;				//禁止UPDATE中断
					break;
			case GTIM_COMP_IRQ:
					gtimer2_callback[1] = NULL;
					REG_GTIM2_IER &= ~VAL_GTIM_CCIE;			//禁止比较中断
					break;
			case GTIM_CAP_IRQ:
					gtimer2_callback[2] = NULL;
					REG_GTIM2_IER &= ~VAL_GTIM_CCIE;			//禁止捕捉中断
					break;
			case GTIM_BKE_IRQ:
					gtimer2_callback[3] = NULL;
					REG_GTIM2_IER &= ~VAL_GTIM_BKE_IE;			//禁止刹车中断
					break;		
			default:
					break;	
		}	
	}		
}

/************************************************************************
 * Function   	: gtimer2_start
 * Description	: 启动gtimer2计数
 * Input 		: none
 * Output 		: none
 * Return		: none
 ************************************************************************/	
void gtimer2_start(void)
{
	REG_GTIM2_CR |= VAL_GTIM_CEN;							//启动计数器
}

/************************************************************************
 * Function   	: gtimer2_stop
 * Description	: 关闭gtimer2计数
 * Input 		: none
 * Output 		: none
 * Return		: none
 ************************************************************************/
void gtimer2_stop(void)
{
	REG_GTIM2_CR &= ~VAL_GTIM_CEN;							//关闭计数器
}

/************************************************************************
 * Function   	: gtimer2_moe_set
 * Description	: gtimer2通道输出使能开关
 * Input 		: uint8_t moe_enable	1:使能输出 0：关闭输出
 * Output 		: none
 * Return		: none
 ************************************************************************/
void gtimer2_moe_set(uint8_t moe_enable)
{
	if(moe_enable == GTIM_MOE_ENABLE)
	{
		REG_GTIM2_CR |= VAL_GTIM_MOE_ENABLE;				//使能输出
	}
	else
	{	
		REG_GTIM2_CR &= ~VAL_GTIM_MOE_ENABLE;				//关闭输出
	}
}

/************************************************************************
 * Function   	: gtimer2_soft_bke_set
 * Description	: gtimer2软件触发刹车使能开关
 * Input 		: uint8_t soft_bk_enable	1:使能软件触发刹车 0：关闭软件触发刹车
 * Output 		: none
 * Return		: none
 ************************************************************************/
void gtimer2_soft_bke_set(uint8_t soft_bk_enable)
{
	if(soft_bk_enable == GTIM_SOFT_BK_ENABLE)
	{
		REG_GTIM2_CR |= VAL_GTIM_SOFT_BK;       			//软件触发刹车功能
	}
	else
	{	
		REG_GTIM2_CR &= ~VAL_GTIM_SOFT_BK;       			//关闭软件触发刹车功能
		REG_GTIM2_SR = VAL_GTIM_BKEF;						//清除刹车中断标志
	}
}
