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

void (*lpuartfunc[2])(void) = { 0 };

volatile uint8_t lputx_flag;
volatile uint8_t lpurx_flag;

/************************************************************************
 * function   : LPUART_IRQHandler
 * description: lpuart interrupt handling
 * input 	  : none
 * return	  : none
 ************************************************************************/
void LPUART_IRQHandler(void)
{

	if((REG_LPUART_LPUIF & 0x01) == 0x01)      						// 接收完成中断		
	{		
		if(lpuartfunc[0]!= NULL)		
		{		
			((void(*)())(lpuartfunc[0]))();  						//lpuart的接收处理回调函数
		
		}		
		REG_LPUART_LPUIF = 0x01;									//清除接收完成中断标志位		
	}		
	else if((REG_LPUART_LPUIF & 0x08)== 0x08)  						//发送完成中断
	{		
		if(lpuartfunc[1]!= NULL)		
		{		
			((void(*)())(lpuartfunc[1]))();  						//lpuart的发送处理回调函数
		}			
		REG_LPUART_LPUIF = 0x08;									//清除发送完成中断标志位
				
	}		
	else		
	{		
		REG_LPUART_LPUIF = 0x0F; 									//清除中断状态
		REG_LPUART_LPUSTA = 0x3D;	
	}

}


/************************************************************************
 * function   : lpuart_set_baud_rate
 * description: lpuart_set_baud_rate
 * input      : uint32_t baud_rate: Series rate  		 
 * return     : none
 ************************************************************************/
void lpuart_set_baud_rate(uint32_t baud_rate)
{
	switch(baud_rate)                                   //波特率选择     
	{
		case 300: 
					REG_LPUART_LPUBAUD = 0x05;
					REG_LPUART_MCTL = 0x842;
					break;
		case 600: 
					REG_LPUART_LPUBAUD = 0x04;
					REG_LPUART_MCTL = 0x6D6;
					break;		   
		case 1200: 
					REG_LPUART_LPUBAUD = 0x03;
					REG_LPUART_MCTL = 0x412;
					break;
		case 2400: 
					REG_LPUART_LPUBAUD = 0x02;
					REG_LPUART_MCTL = 0x6DB;
					break;
		case 4800: 
					REG_LPUART_LPUBAUD = 0x01;
					REG_LPUART_MCTL = 0xEFB;
					break;
		case 9600: 
					REG_LPUART_LPUBAUD = 0x00;
					REG_LPUART_MCTL = 0x952;
					break;
		default:
			        break;
	}

}

/************************************************************************
 * function   : lpuart_init
 * description: lpuart initial for baud_rate
 * input      : uint32_t baud_rate: Series rate 	
 * return	  : none
 ************************************************************************/
void lpuart_init(uint32_t baud_rate)
{	
	REG_SCU_PERICLKEN |= (1<<1);													//	开LPUART时钟使能
	REG_SCU_PERIRESET |= (1<<1);													//	LPUART正常工作	
		

	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 											//	清除IO写保护
	REG_SCU_PFSEL = (REG_SCU_PFSEL&(~(0xF<<16)))|(0x1<<16);							//	PF4复用为LPUART_TX  
	REG_SCU_PFSEL = (REG_SCU_PFSEL&(~(0xF<<12)))|(0x1<<12);							//	PF3复用为LPUART_RX 
	REG_SCU_PADIE1 |= (0x1<<11);                                    				//  PF3 输入使能	
	REG_SCU_IOCTRLPROTECT = 0xFFFFFFFF;												//	开启IO写保护
	
	lpuart_set_baud_rate(baud_rate);												//	波特率设置
		
	REG_LPUART_LPUEN = 0x03;														//	发送使能，接收使能
	while((REG_LPUART_LPUEN & 0x03) != 0x03); 										//	等待设置成功

	REG_LPUART_LPUSTA = 0x3D;														//	清除状态标志寄存器
	REG_LPUART_LPUIF = 0x0F;														//	清除中断标志
    
}

/************************************************************************
 * function   : lpuart_irq_init
 * description: lpuart irq init
 * input      : uint8_t irq_enable: interrupt enable/disable
 *              void (*lpuart_recv)(): interrupt callback function  
 *				void (*lpuart_send)(): interrupt callback function  	 
 * return	  : none
 ************************************************************************/
void lpuart_irq_init(uint8_t irq_enable,void (*lpuart_recv)(),void (*lpuart_send)()) 
{
	if(irq_enable == LPUART_IRQ_ENABLE)
	{
		NVIC_ClearPendingIRQ(LPUART_IRQn);
		NVIC_EnableIRQ(LPUART_IRQn);
		
#ifdef LPUART_Tx_INT_MODE												    //发送采用中断方式
		REG_LPUART_LPUCON |= (1<<11);										//发送完成中断使能								
#else																										
		REG_LPUART_LPUCON |= (5<<0);										//接收中断使能，1byte数据接收完成触发中断	
#endif	
		
		lpuartfunc[0] = lpuart_recv;
		lpuartfunc[1] = lpuart_send;
	}
	else
	{
#ifdef LPUART_Tx_INT_MODE												    //发送采用中断方式
		REG_LPUART_LPUCON &=~ (1<<11);										//发送完成中断失能						
#else																										
		REG_LPUART_LPUCON &= ~(5<<0);										//接收中断失能
#endif	
		lpuartfunc[0] = NULL;
		lpuartfunc[1] = NULL;
		
		NVIC_ClearPendingIRQ(LPUART_IRQn);                                  //清除中断                
		NVIC_DisableIRQ(LPUART_IRQn);                                       //中断禁止
	}
}


/************************************************************************
 * function   : lpuart_recv_byte
 * description: lpuart read one byte's data
 * input : none       
 * return: data from uart
 ************************************************************************/
uint8_t lpuart_recv_byte(void)	
{
	return REG_LPUART_LPURXD;
}

/************************************************************************
 * function   : lpuart_rec_bytes 
 * description: lpuart receive bytes by polling mode
 * input      : uint8_t* buff: receive buffer
 *              uint32_t length: buffer length    
 * return     : none
 ************************************************************************/
void lpuart_rec_bytes(uint8_t *buff, uint32_t length)
{
	while(length--)
	{
		while(!( REG_UART0_ISR & 0x20 ));										//wait rx not empty
		*buff++ = lpuart_recv_byte();	
	}	
		
}

/************************************************************************
 * function   : lpuart_send_byte
 * description: lpuart out byte
 * input      : char c: out byte      
 * return     ：none
 ************************************************************************/
void lpuart_send_byte(char c)
{
	REG_LPUART_LPUTXD = c;
#ifdef LPUART_Tx_INT_MODE														//中断方式
	while(!lputx_flag);
	lputx_flag = 0;
#else																			//查询方式
	while((REG_LPUART_LPUSTA & 0xC0) != 0xC0);  								//等待数据发送完成,查询发送完成标志为1，且发送buffer为空
	REG_LPUART_LPUIF = 0x0C;													//清除发送完成中断标志和发送buffer空中断标志
#endif	
}

/************************************************************************
 * function   : lpuart_send_bytes
 * description: lpuart_send_bytes
 * input      : uint8_t* buff: out buffer
 *              uint32_t length: buffer length
 * return: none
 ************************************************************************/
void lpuart_send_bytes(uint8_t *buff, uint32_t length)
{
	uint32_t i;

	for(i = 0; i < length; i++)
	{
		lpuart_send_byte(*buff++);
	}
}
/************************************************************************
 * function   : lpuart_match_init
 * description: lpuart_match_init
 * input : none
 * return: none
 ************************************************************************/
void lpuart_match_init(void)
{
	REG_LPUART_LPUCON = (7<<0);													//接受数据匹配,接受中断使能
									
	REG_LPUART_COMPARE = 0x4A;													//设置需要匹配的数据
									
	REG_LPUART_WKCKE = 0;														//匹配中断唤醒配置  0:接受数据匹配 1：接受数据和奇偶校验匹配
	
}

