/***********************************************************************
 * Copyright (c)  2019, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : lptimer.c
 * Description : lpTimer driver source file
 * Author(s)   : canheng
 * version     : V1.0
 * Modify date : 2021-08-13
 ***********************************************************************/
#include  "lptimer1.h"
	
void (*lptimer1func[3])(void) = { 0 };

/************************************************************************
 * function   : LPTIMER1_IRQHandler
 * Description: LPTIMER1_IRQHandler
 * input      : none
 * output     : none   
 * return     : none
 ************************************************************************/

void LPTIMER1_IRQHandler(void)
{
	if(REG_LPTIM1_LPTIF & 0x07)
	{
		if(REG_LPTIM1_LPTIF & VAL_LPTIM_LPTIF_OVIF)			//溢出中断
		{
			if(lptimer1func[0]!= NULL)
			{
				((void(*)())(lptimer1func[0]))();			//lptimer0溢出中断处理回调函数
			}	
			REG_LPTIM1_LPTIF = VAL_LPTIM_LPTIF_OVIF;
		}
		
		if(REG_LPTIM1_LPTIF & VAL_LPTIM_LPTIF_TRIGIF)		//外部触发中断
		{
			if(lptimer1func[1]!= NULL)
			{
				((void(*)())(lptimer1func[1]))();  			//lptimer0外部触发处理回调函数
			}	
			REG_LPTIM1_LPTIF = VAL_LPTIM_LPTIF_TRIGIF;
		}
	
		if(REG_LPTIM1_LPTIF & VAL_LPTIM_LPTIF_COMPIF)		//比较匹配中断
		{
			if(lptimer1func[2]!= NULL)
			{
				((void(*)())(lptimer1func[2]))();			//lptimer0比较匹配中断处理回调函数
			}	
			REG_LPTIM1_LPTIF = VAL_LPTIM_LPTIF_COMPIF;
		}
	}
	else 
	{
		REG_LPTIM1_LPTIF = 0x07;							//清除中断状态 												
	}
}

/*******************************************************************
* Function		: lptim1_count_init
* Description	: lptimer1普通定时器计数初始化设置
* Input			:uint32_t clock_source	时钟源选择
*				 uint32_t clock_div	时钟源分频
*                uint16_t time			定时时间                 
* Output		: none
* Return		: none
********************************************************************/
void lptim1_count_init(uint32_t clock_source, uint32_t clock_div, uint16_t time)
{
	REG_SCU_PERIRESET |= ((uint32_t)0x01<<5);				// lpTimer1正常工作 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<5);				// 开启lpTimer1时钟使能 
	
	REG_LPTIM1_LPTCFG &= ~(0x00001FFF);						// 恢复默认值 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_TMODE_TIME;		// 设置工作模式 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_MODE_COUNT;		// 计数模式 
	REG_LPTIM1_LPTCFG |= clock_div;							// 设置分频值2分频
	REG_LPTIM1_LPTCFG |= clock_source;						// 选择时钟源 
	
	REG_LPTIM1_LPTTARGET = time;							// 设置高低位目标寄存器的值
}

/*******************************************************************
* Function		: lptim1_pwm_init
* Description	: lptimer2 out pwm form PB5
* Input			: uint16_t cmp:  匹配比较值   			
*				  uint16_t target:target  定时目标值     duty cyle（占空比） = (cmp / target) * 100% 
*                 uint32_t clock_div  时钟源分频
*                 uint32_t clock_source  时钟源选择
*                 uint8_t level  1:计数值=比较值时输出上升沿  2:计数值=比较值时输出下降沿
* Output		: none
* Return		: none
********************************************************************/
void lptim1_pwm_init(uint16_t cmp, uint16_t target, uint32_t clock_source, uint32_t clock_div, uint8_t level)
{
	REG_SCU_PERIRESET |= ((uint32_t)0x01<<5);					// lpTimer1正常工作 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<5);					// 开启lpTimer1时钟使能 
		
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 						// 清除IO写保护 					
	REG_SCU_PBSEL = (REG_SCU_PBSEL&(~(0x7<<20)))|(6<<20); 		// PB5选择LPTIM1_OUT
	REG_SCU_IOCTRLPROTECT = 0xFFFFFFFF; 						// IO写保护
		
	REG_LPTIM1_LPTCFG &= ~(0x00001FFF);							// 恢复默认值 
	REG_LPTIM1_LPTCFG |= clock_source;			         		// 选择时钟源 
	REG_LPTIM1_LPTCFG |= clock_div;                      		// 分频系数
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_MODE_COUNT;			// 计数模式: 连续计数模式
	REG_LPTIM1_LPTCMP = cmp;									// 设置高低位比较寄存器的值 
	REG_LPTIM1_LPTTARGET = target;								// 设置高低位目标寄存器的值 
	
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_PWM_PWM;				// 设置工作模式:PWM
	
	if(level == HIGH)
	{
		REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_POLARITY_HIGHT;   // 计数值=比较值时输出上升沿
	}
	else
	{
		REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_POLARITY_LOWER;	// 计数值=比较值时输出下降沿
	}
}
/*******************************************************************
* Function		: lptim1_trigger_init
* Description	: LPTIM1  Trigger脉冲触发计数初始化设置
* Input			: pfunc:timer irq  lptimer1  外部触发中断处理回调函数
*                 uint32_t clock_source 	 时钟源选择
*				  uint32_t clock_div  		 时钟源分频
*                 uint16_t target  			 定时目标值
* Output		: none
* Return		: none
********************************************************************/
void lptim1_trigger_init(uint32_t clock_source, uint32_t clock_div, uint16_t target)
{
	REG_SCU_PERIRESET |= ((uint32_t)0x01<<5);				// lpTimer1正常工作 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<5);				// 开启lpTimer1时钟使能 
	
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 					// 清除IO写保护 
	REG_SCU_PDSEL = (REG_SCU_PDSEL&(~(0x7<<4)))|(3<<4);  	// PD1选择LPTIM1_EXT 
	REG_SCU_IOCTRLPROTECT = 0xFFFFFFFF; 					// IO写保护 
	
	REG_LPTIM1_LPTCFG &= ~(0x00001FFF);						// 恢复默认值 
	REG_LPTIM1_LPTCFG |= clock_source;				     	// 选择时钟源 
	REG_LPTIM1_LPTCFG |= clock_div;                      	// 设置时钟分频
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_MODE_COUNT;		// 计数模式 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_EDGESEL_RISE;		// 输入边沿选择 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_TMODE_TRIGGER;	// Trigger脉冲触发计数模式 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_TRIGCFG_FALL;		// 外部输入信号下降沿trigger 
	REG_LPTIM1_LPTTARGET = target;							// 设置高低位目标寄存器的值 
}
/*******************************************************************
* Function		: lptim1_extcount_init
* Description	: lptimer1 外部异步脉冲初始化设置
* Input			: uint16_t target:target  定时目标值
*				  uint32_t clock_source  时钟源选择
*				  uint32_t clock_div  时钟源分频
* Output		: none
* Return		: none
********************************************************************/
void lptim1_extcount_init(uint32_t clock_source, uint32_t clock_div, uint16_t target)
{
	REG_SCU_PERIRESET |= ((uint32_t)0x01<<5);				// lpTimer1正常工作 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<5);				// 开启lpTimer1时钟使能
	
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 					// 清除IO写保护 
	REG_SCU_PBSEL = (REG_SCU_PBSEL&(~(0x7<<8)))|(5<<8);  	// PB2选择LPTIM1_IN                         	
	REG_SCU_IOCTRLPROTECT = 0xFFFFFFFF; 					// IO写保护 
	
	REG_LPTIM1_LPTCFG &= ~(0x00001FFF);						// 恢复默认值 
	REG_LPTIM1_LPTCFG |= clock_source;				     	// 选择时钟源 
	REG_LPTIM1_LPTCFG |= clock_div;                     	// 分频系数
	REG_LPTIM1_LPTTARGET = target;							// 设置高低位目标寄存器的值 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_TMODE_EXT;	   	// 选择外部异步脉冲模式 
 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_EDGESEL_RISE;  	// LPTIN 的上升沿计数 
	
}
/*******************************************************************
* Function		: lptim1_time_out_init
* Description	: lptim1_time_out初始化
* Input			: uint16_t target:target  	定时目标值
*				  uint32_t clock_source  	时钟源选择
*				  uint32_t clock_div  		时钟源分频
* Output		: none
* Return		: none
********************************************************************/
void lptim1_time_out_init(uint32_t clock_source, uint32_t clock_div, uint16_t target)
{
	REG_SCU_PERIRESET |= ((uint32_t)0x01<<5);				// lpTimer1正常工作 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<5);				// 开启lpTimer1时钟使能 
	
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 					// 清除IO写保护
	REG_SCU_PDSEL = (REG_SCU_PDSEL&(~(0x7<<4)))|(3<<4);   	// PD1选择LPTIM1_EXT	

	if(clock_source == VAL_LPTIM_LPTCFG_CLKSEL_LPTIN)
	{
		REG_SCU_PBSEL = (REG_SCU_PBSEL&(~(0x7<<8)))|(5<<8); // PB2选择LPTIM1_IN         					
	}				
	
	REG_SCU_IOCTRLPROTECT = 0xFFFFFFFF; 					// IO写保护 
	
	REG_LPTIM1_LPTCFG &= ~(0x00001FFF);						// 恢复默认值 
	REG_LPTIM1_LPTCFG |= clock_source;				     	// 时钟源选择 
	REG_LPTIM1_LPTCFG |= clock_div;                    		// 设置时钟分频
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_MODE_COUNT;		// 计数模式 
	REG_LPTIM1_LPTTARGET = target;							// 设置高低位目标寄存器的值 
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_TMODE_TIMEOUT;	// 模式选择 	
	REG_LPTIM1_LPTCFG |= VAL_LPTIM_LPTCFG_TRIGCFG_FALL;		// 外部触发边沿选择			
}

/*******************************************************************
* Function		: lptim1_irq_init
* Description	: lptim1_irq_init  中断初始化设置
* Input			: none
* Output		: none
* Return		: none
********************************************************************/
void lptim1_irq_init(uint32_t irq_enable, uint32_t irq_type, void (*pfunc)()) 
{
	if(irq_enable == VAL_LPTIM_IRQ_ENABLE)
	{
		NVIC_ClearPendingIRQ(LPTIMER1_IRQn);
		NVIC_EnableIRQ(LPTIMER1_IRQn);
		
		if(irq_type == VAL_LPTIM_LPTIE_OVIE)         		//计数器溢出中断使能
		{
			REG_LPTIM1_LPTIE |= VAL_LPTIM_LPTIE_OVIE;
			lptimer1func[0] = pfunc;
		}
		if(irq_type == VAL_LPTIM_LPTIE_TRIGIE)  			//外部触发到来中断使能
		{
			REG_LPTIM1_LPTIE |= VAL_LPTIM_LPTIE_TRIGIE;
			lptimer1func[1] = pfunc;
		}
		if(irq_type == VAL_LPTIM_LPTIE_COMPIE)  			//比较匹配中断使能
		{
			REG_LPTIM1_LPTIE |= VAL_LPTIM_LPTIE_COMPIE;
			lptimer1func[2] = pfunc;
		}
	}
	else
	{		
		if(irq_type == VAL_LPTIM_LPTIE_OVIE) 
		{
			REG_LPTIM1_LPTIE &= ~(VAL_LPTIM_LPTIE_OVIE);	//计数器溢出中断不使能
			lptimer1func[0] = NULL;                         
		}                                                   
		if(irq_type == VAL_LPTIM_LPTIE_TRIGIE)              
		{                                                   
			REG_LPTIM1_LPTIE &= ~(VAL_LPTIM_LPTIE_TRIGIE);  //外部触发到来中断不使能
			lptimer1func[1] = NULL;                         
		}                                                   
		if(irq_type == VAL_LPTIM_LPTIE_COMPIE)              
		{                                                   
			REG_LPTIM1_LPTIE &= ~(VAL_LPTIM_LPTIE_COMPIE);  //比较匹配中断不使能
			lptimer1func[2] = NULL;
		}
	}
}

/*******************************************************************
* Function		: lptim1_start
* Description	: enable lptim1 count
* Input			: none
* Output		: none
* Return		: none
********************************************************************/

void lptim1_start(void)
{
	REG_LPTIM1_LPTCTRL |= VAL_LPTIM_LPTCTRL_LPTEN_ENABLE;		// 打开LPTEN使能位，启动计数器 
}

/*******************************************************************
* Function		: lptimer_stop
* Description	: disable lptimer count
* Input			: none
* Output		: none
* Return		: none
********************************************************************/
void lptim1_stop(void)
{
	REG_LPTIM1_LPTCTRL &= ~VAL_LPTIM_LPTCTRL_LPTEN_ENABLE;		// 关闭LPTEN使能位，关闭计数器 
}

// 获取lpTim1的当前计数值
uint16_t lptim1_get_count(void)
{
	return (uint16_t)REG_LPTIM1_LPTCNT;  // 
}
