/***********************************************************************
 * Copyright (c)  2017 - 2022, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : gtimer1.c
 * Description : gtimer1 driver source file
 * Author(s)   : Sissi
 * version     : V1.0
 * Modify date : 2022-08-08
 ***********************************************************************/
#include "gtimer.h"
	
void (*gtimer1_callback[4])(void) = { 0 };

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

/************************************************************************
 * function   : gtimer1_caen 
 * Description: gtimer1使能受cen_all控制
 * input      : none
 * output     : none
 * return     : none
 ************************************************************************/
void btimer1_caen(void)
{
	REG_GTIM1_CR |= (1<<3);
}

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

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

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

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

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

/************************************************************************
 * Function   	: gtimer1_bke_init
 * Description	: gtimer1 硬件刹车初始化
 * Input 		: uint32_t bke_src	刹车源设置
 *            	  uint32_t bke_pol	刹车信号触发极性
 * Output 		: none
 * Return		: none
 ************************************************************************/
void gtimer1_bke_init(uint32_t bke_src,uint32_t bke_pol)
{
	REG_SCU_PERIRESET |= GTIMER1_RESET;						//gtimer1正常工作
	REG_SCU_PERICLKEN |= GTIMER1_CLKEN;						//开gtimer1时钟使能	
	
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 					//清除IO写保护
	
	REG_SCU_PESEL = (REG_SCU_PESEL&(~(0xF<<12)))|(0x5<<12); //PE3复用为GTIMER1_BK 刹车源 
	
	REG_SCU_IOCTRLPROTECT = 0xffffffff; 					//开启IO写保护
	
	REG_GTIM1_CR = (REG_GTIM1_CR & ~(0xFF<<21)) | bke_src;	//刹车源选择
	
	REG_GTIM1_CR = (REG_GTIM1_CR & ~(1<<11)) | bke_pol;     //刹车信号触发极性
	
	REG_GTIM1_CR &= ~VAL_GTIM_PWMN_IDLE; 					//PWM输出负向电平IDLE状态为低电平
	REG_GTIM1_CR &= ~VAL_GTIM_PWMP_IDLE; 					//PWM输出正向电平IDLE状态为低电平
	
	REG_GTIM1_CR &= ~VAL_GTIM_PWMN_B_S;    					//PWM刹车触发后，PWM互补电平状态设置位为低电平
	REG_GTIM1_CR &= ~VAL_GTIM_PWMS_B_S;     				//PWM刹车触发后，PWM正向电平状态设置位为低电平
	
	REG_GTIM1_CR |= VAL_GTIM_BKE;           				//刹车功能使能	
}

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

/************************************************************************
 * Function   	: gtimer1_start
 * Description	: 启动gtimer1计数
 * Input 		: none
 * Output 		: none
 * Return		: none
 ************************************************************************/	
void gtimer1_start(void)
{
	REG_GTIM1_CR |= VAL_GTIM_CEN;							//启动计数器
}

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

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

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