/***********************************************************************
 * Copyright (c)  2019, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : um_lptimer.c
 * Description : lpTimer driver source file
 * Author(s)   : wanyi
 * version     : V1.0
 * Modify date : 2020-09-04
 ***********************************************************************/
#include "lptimer.h"
#include  "string.h"

void (*lptimfunc[3])(void) = { 0 };
/************************************************************************
 * function   : lptimer_IRQHandler
 * Description: lptimer interrupt handler
 * input : none
 * output: none   
 * return: none
 ************************************************************************/
void LPTIMER_IRQHandler(void) interrupt 12
{
    
	if(((REG_LPTIM_LPTIF & 0x01) == 0x01)&&((REG_LPTIM_LPTIE & 0x01) == 0x01))		   /* 匹配中断 */
	{
		REG_LPTIM_LPTIF = 0x01;                                                        /* 清中断标志 */
        
        if(lptimfunc[0]!= NULL)
        {
            ((void(*)())(lptimfunc)[0])();                                             /* lptim匹配中断回调函数 */ 
        }
	}
    else if(((REG_LPTIM_LPTIF & 0x02) == 0x02)&&((REG_LPTIM_LPTIE & 0x02) == 0x02))	   /* 溢出中断 */ 
	{
		REG_LPTIM_LPTIF = 0x02;                                                        /* 清中断标志 */    
        
        if(lptimfunc[1]!= NULL)
        {
            ((void(*)())(lptimfunc)[1])();                                             /* lptim溢出中断回调函数 */  
        }
	}
    else if(((REG_LPTIM_LPTIF & 0x04) == 0x04)&&((REG_LPTIM_LPTIE & 0x04) == 0x04))	  /* 外部Trigger触发中断 */ 
	{
		REG_LPTIM_LPTIF = 0x04;	                                                      /* 清中断标志 */    
        
        if(lptimfunc[2]!= NULL)
        {
            ((void(*)())(lptimfunc)[2])();                                            /* lptim外部Trigger触发中断回调函数 */ 
        }   
	}
}
/*******************************************************************
* Function		: lptimer_timer_init
* Description	: lptimer 定时初始化
* Input			: uint8_t clk_src  时钟源选择
*                 uint8_t clk_div  时钟源分频
*                 uint16_t target  定时目标值                   
* Output		: none
* Return		: none
********************************************************************/
void lptimer_timer_init(uint8_t clk_src,uint8_t clk_div,uint16_t target)
{
    PCLK0 |= (1<<6); 									        /* 开启lpTimer时钟使能 */
    PRESET0 |= (1<<6);									        /* lpTimer正常工作 */  
    
    REG_LPTIM_LPTCFG0 &= ~(3<<3);
	REG_LPTIM_LPTCFG0 |= (clk_src<<3);							/* 时钟源设置 0:RCL低速时钟, 1:clk_1hz时钟,  2:系统时钟, 3:外部输入时钟 */ 
 
	REG_LPTIM_LPTCFG0 &= ~(7<<0);									
    REG_LPTIM_LPTCFG0 |= (clk_div<<0);							/* 设置计数时钟分频 */
    
   	REG_LPTIM_LPTCFG1 &= ~(3<<3);									
    REG_LPTIM_LPTCFG1 |= (TIMER_TMODE<<3);                      /* 设置工作模式 */
    
	REG_LPTIM_LPTCFG1 &= ~(1<<2);								
    REG_LPTIM_LPTCFG1 |= (CONTINUOUS_MODE<<2);                  /* 连续计数模式 */ 
	
	REG_LPTIM_LPTTARGETL = (target)%256;						/* 设置定时目标值 */								
    REG_LPTIM_LPTTARGETH = (target)/256; 
}

/*******************************************************************
* Function		: lptimer_pwm_init
* Description	: lptimer PWM初始化
* Input			: uint8_t clk_src  时钟源选择
*                 uint8_t clk_div  时钟源分频
*                 uint16_t target  定时目标值(设置PWM周期)
*                 uint16_t target  比较匹配值(设置占空比)
*                 uint8_t level  1:计数值=比较值时输出上升沿  2:计数值=比较值时输出下降沿
* Output		: none
* Return		: none
********************************************************************/
void lptimer_pwm_init(uint8_t clk_src,uint8_t clk_div,uint16_t target,uint16_t cmp,uint8_t level)
{
    PCLK0 |= (1<<6); 									        /* 开启lpTimer时钟使能 */
    PRESET0 |= (1<<6);									        /* lpTimer正常工作 */  
    
    REG_LPTIM_LPTCFG0 &= ~(3<<3);
	REG_LPTIM_LPTCFG0 |= (clk_src<<3);							/* 时钟源设置 0:RCL低速时钟, 1:clk_1hz时钟,  2:系统时钟, 3:外部输入时钟 */ 
 
	REG_LPTIM_LPTCFG0 &= ~(7<<0);									
    REG_LPTIM_LPTCFG0 |= (clk_div<<0);							/* 设置计数时钟分频 */
    
   	REG_LPTIM_LPTCFG1 &= ~(3<<3);									
    REG_LPTIM_LPTCFG1 |= (TIMER_TMODE<<3);                      /* 设置工作模式 */
    
	REG_LPTIM_LPTCFG1 &= ~(1<<2);								
    REG_LPTIM_LPTCFG1 |= (CONTINUOUS_MODE<<2);                  /* 连续计数模式 */ 
	
	REG_LPTIM_LPTCFG1 &= ~(1<<1);								  
    REG_LPTIM_LPTCFG1 |= (1<<1);                                /* PWM输出模式 */ 
	
	if(level == HIGH)
	{
		REG_LPTIM_LPTCFG1 &= ~(1<<0);							/* 计数值=比较值时输出上升沿 */
	}
	else
	{
		REG_LPTIM_LPTCFG1 |= (1<<0);							/* 计数值=比较值时输出下降沿 */
	}
	
	REG_LPTIM_LPTTARGETL = (target)%256;						/* 设置定时目标值 */								
    REG_LPTIM_LPTTARGETH = (target)/256; 
	
	REG_LPTIM_LPTCMPL = cmp%256;								/* 设置比较匹配值 */
    REG_LPTIM_LPTCMPH = cmp/256;
	
	REG_LPTIM_LPTCFG1 |= (1<<6);                                /* P0_3作为LPOUT */
}

/*******************************************************************
* Function		: lptimer_trigger_init
* Description	: lptimer trigger初始化
* Input			: uint8_t clk_src  时钟源选择
*                 uint8_t clk_div  时钟源分频
*                 uint16_t target  定时目标值
*                 uint8_t trig_edge  trigger触发边沿选择
* Output		: none
* Return		: none
********************************************************************/
void lptimer_trigger_init(uint8_t clk_src,uint8_t clk_div,uint16_t target,uint8_t trig_edge)
{
    PCLK0 |= (1<<6); 									        /* 开启lpTimer时钟使能 */
    PRESET0 |= (1<<6);									        /* lpTimer正常工作 */  
    
    REG_LPTIM_LPTCFG0 &= ~(3<<3);
	REG_LPTIM_LPTCFG0 |= (clk_src<<3);							/* 时钟源设置 0:RCL低速时钟, 1:clk_1hz时钟,  2:系统时钟, 3:外部输入时钟 */ 
 
	REG_LPTIM_LPTCFG0 &= ~(7<<0);									
    REG_LPTIM_LPTCFG0 |= (clk_div<<0);							/* 设置计数时钟分频 */
    
   	REG_LPTIM_LPTCFG1 &= ~(3<<3);									
    REG_LPTIM_LPTCFG1 |= (TRIGGERCOUNT_TMODE<<3);               /* 设置工作模式 */
    
	REG_LPTIM_LPTCFG1 &= ~(1<<2);								
    REG_LPTIM_LPTCFG1 |= (CONTINUOUS_MODE<<2);                  /* 连续计数模式 */ 
	
	REG_LPTIM_LPTCFG1 &= ~(3<<6);								
	REG_LPTIM_LPTCFG1 |= (trig_edge<<6);						/* 设置trigger触发边沿 */	
	
	REG_LPTIM_LPTTARGETL = (target)%256;						/* 设置定时目标值 */								
    REG_LPTIM_LPTTARGETH = (target)/256; 
	
	REG_LPTIM_LPTCFG1 |= (1<<7);								/* P1.1 作为 EXTRIGGER_IO_IEN*/
	
}

/*******************************************************************
* Function		: lptimer_extcount_init
* Description	: lptimer 外部异步脉冲初始化
* Input			: 
*                 uint8_t clk_div  时钟源分频
*                 uint16_t target  定时目标值
*                 
* Output		: none
* Return		: none
********************************************************************/
void lptimer_extcount_init(uint8_t clk_div,uint16_t target)
{
    PCLK0 |= (1<<6); 									        /* 开启lpTimer时钟使能 */
    PRESET0 |= (1<<6);									        /* lpTimer正常工作 */  
    
    REG_LPTIM_LPTCFG0 &= ~(3<<3);
	REG_LPTIM_LPTCFG0 |= (LPTIMER_LPTIN<<3);					/* 时钟源设置 0:RCL低速时钟, 1:clk_1hz时钟,  2:系统时钟, 3:外部输入时钟 */ 
 
	REG_LPTIM_LPTCFG0 &= ~(7<<0);									
    REG_LPTIM_LPTCFG0 |= (clk_div<<0);							/* 设置计数时钟分频 */
    
   	REG_LPTIM_LPTCFG1 &= ~(3<<3);									
    REG_LPTIM_LPTCFG1 |= (EXTCOUNT_TMODE<<3);               	/* 设置工作模式 */
    
	REG_LPTIM_LPTCFG1 &= ~(1<<2);								
    REG_LPTIM_LPTCFG1 |= (CONTINUOUS_MODE<<2);                  /* 连续计数模式 */ 
	
	REG_LPTIM_LPTCFG1 &= ~(1<<5);								
	REG_LPTIM_LPTCFG1 |= (0<<5);								/* LPTIN上升沿计数 */					
	
	REG_LPTIM_LPTTARGETL = (target)%256;						/* 设置定时目标值 */								
    REG_LPTIM_LPTTARGETH = (target)/256; 
	
	REG_LPTIM_LPTCFG1 |= (1<<5);								/* P1.0 作为 LPTIN*/
	
}

/*******************************************************************
* Function		: lptimer_timeout_init
* Description	: lptimer timeout模式初始化
* Input			: uint8_t clk_src  时钟源选择
*                 uint8_t clk_div  时钟源分频
*                 uint16_t target  定时目标值                
* Output		: none
* Return		: none
********************************************************************/
void lptimer_timeout_init(uint8_t clk_src,uint8_t clk_div,uint16_t target)
{
    PCLK0 |= (1<<6); 									        /* 开启lpTimer时钟使能 */
    PRESET0 |= (1<<6);									        /* lpTimer正常工作 */  
    
    REG_LPTIM_LPTCFG0 &= ~(3<<3);
	REG_LPTIM_LPTCFG0 |= (clk_src<<3);							/* 时钟源设置 0:RCL低速时钟, 1:clk_1hz时钟,  2:系统时钟, 3:外部输入时钟 */ 
 
	REG_LPTIM_LPTCFG0 &= ~(7<<0);									
    REG_LPTIM_LPTCFG0 |= (clk_div<<0);							/* 设置计数时钟分频 */
    
   	REG_LPTIM_LPTCFG1 &= ~(3<<3);									
    REG_LPTIM_LPTCFG1 |= (TIMEOUT_TMODE<<3);               		/* 设置工作模式 */
    
	REG_LPTIM_LPTCFG1 &= ~(1<<2);								
    REG_LPTIM_LPTCFG1 |= (CONTINUOUS_MODE<<2);                  /* 连续计数模式 */ 
					
	REG_LPTIM_LPTTARGETL = (target)%256;						/* 设置定时目标值 */								
    REG_LPTIM_LPTTARGETH = (target)/256; 
	
	REG_LPTIM_LPTCFG1 |= (1<<7);								/* P1.1 作为 EXTRIGGER_IO_IEN*/
	
}

/*******************************************************************
* Function		: lptimer_irq_init
* Description	: lptimer 中断初始化
* Input			: irqstate：0  中断失能
*                           1  中断使能
*                 ie: 0 比较匹配中断使能 
*                     1 计数器溢出中断使能
*                     2 外部触发到来中断使能
*                 void (*pfunc)() ：中断回调函数  
* Output		: none
* Return		: none
********************************************************************/
void lptimer_irq_init(uint8_t irqstate,uint8_t ie,void (*pfunc)())
{
    if(irqstate == LPTIMER_IRQ_ENABLE)
    {
        EA = 1;				                                      /* EA总中断开启 */ 
        IEN1 |= (1<<4);                                           /* lptimer中断开启*/  
        
        switch(ie)
        {
            case 0:        
                    REG_LPTIM_LPTIE |= (1<<0);                    /*比较匹配中断使能*/
                    lptimfunc[0] = pfunc;
                    break;
            case 1:
                    REG_LPTIM_LPTIE |= (1<<1);                    /*计数器溢出中断使能*/
                    lptimfunc[1] = pfunc;
                    break;           
            case 2:
                    REG_LPTIM_LPTIE |= (1<<2);                    /*外部触发到来中断使能*/ 
                    lptimfunc[2] = pfunc;
                    break;   
            default:
                    break;
        }
    }
    else
    {
        EA = 0;				                                      /* EA总中断关闭 */     
        IEN1 &= ~(1<<4);                                          /* lptimer中断关闭*/   

        switch(ie)
        {
            case 0:        
                    REG_LPTIM_LPTIE &= ~(1<<2);                    /*外部触发到来中断失能*/ 
                    break;
            case 1:
                    REG_LPTIM_LPTIE &= ~(1<<1);                    /*计数器溢出中断失能*/
                    break;           
            case 2:
                    REG_LPTIM_LPTIE &= ~(1<<0);                    /*比较匹配中断失能*/
                    break;   
            default:
                    break;            
        }        
    }
}


/*******************************************************************
* Function		: lptimer_on
* Description	: lptimer 计数启动
* Input			: none
* Output		: none
* Return		: none
********************************************************************/
void lptimer_on(void)
{
	REG_LPTIM_LPTCTRL |= (1<<0);									/* 打开LPTEN使能位，启动计数器 */  
}
/*******************************************************************
* Function		: lptimer_off
* Description	: lptimer 计数停止
* Input			: none
* Output		: none
* Return		: none
********************************************************************/
void lptimer_off(void)
{
	REG_LPTIM_LPTCTRL &= ~(1<<0);									/* 禁止计数器计数 */  
}

/*******************************************************************
* Function		: get_lptimer_cnt
* Description	: get_lptimer_cnt 获取Lptimer计数值
* Input			: none
* Output		: none
* Return		: Lptimer计数值
********************************************************************/
uint16_t get_lptimer_cnt(void)
{
    return (((uint16_t)REG_LPTIM_LPTCNTH<<8) | REG_LPTIM_LPTCNTL);             
}