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

uint8_t uart2_tx_flag = 0;

void (*uart2_recv_callback)(void) = NULL;

/************************************************************************
 * function   : UART2_IRQHandler
 * description: uart2 interrupt handling
 * input 	  : none
 * return     : none
 ************************************************************************/
void UART2_IRQHandler(void)
{
	if(REG_UART2_ISR & 0x20)                              		// Rx int 
	{		
		if(uart2_recv_callback!= NULL)		
		{		
			(*uart2_recv_callback)();		
		}			
		REG_UART2_ISR &= ~(1<<5);	                      		//清除FIFO_NE非空标志位
	}		
#ifdef UART2_TX_INT_MODE		                          		//中断方式
	else if(REG_UART2_ISR & 0x02)                         		// Tx int 发送中断
	{		
		uart2_tx_flag =1;		
		REG_UART2_ISR &= ~(1<<1);	                      		//清除发送完成标志位
	}		
#endif		
	else		
	{		
		REG_UART2_ISR = 0x00;                             		//清除中断状态
	}
	
}
/************************************************************************
 * function   : uart2_init
 * description: uart2_init
 * input 	  : uint32_t sys_clk_hz: system clock frequency
 *		        uint32_t baud_rate: uart baud rare       
 * return     : none
 ************************************************************************/
void uart2_init(uint32_t sys_clk_hz, uint32_t baud_rate)
{
	REG_SCU_PERICLKEN |= (1<<30);								//开UART时钟使能	
	REG_SCU_PERIRESET |= (1<<30);								//UART正常工作
							
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 						//清除IO写保护
	
    REG_SCU_PESEL = (REG_SCU_PESEL&(~(0xF<<4)))|(7<<4);			//PE1复用为UART2_TX
    REG_SCU_PESEL = (REG_SCU_PESEL&(~(0xF<<0)))|(8<<0);			//PE0复用为UART2_RX
    REG_SCU_PADIE1 |= (0x1<<0);                                 //PE0输入使能
    
	REG_SCU_IOCTRLPROTECT = 0xffffffff; 						//开启IO写保护
	while((REG_SCU_IOCTRLPROTECT & 0x01) == 0x01)     		    //读IO控制保护寄存器的写使能状态
	{	
		REG_SCU_IOCTRLPROTECT = 0xffffffff; 				    //开启IO写保护
	}

	uart2_tx_flag = 0;
	
	REG_UART2_CR = 0x00;	  									//归零该寄存
	REG_UART2_CR|= (1 << 2);  									//清除接收FIFO中数据和指针
	REG_UART2_CR&= ~(1 << 2);   								//清空fifo完成后，还原状态（避免fifo一直处在清空状态，无法接收数据）
	REG_UART2_CR|= (1 << 1)|(1 << 3); 							//无奇偶校验 | 发送数据使能

	uart2_set_baud_rate(sys_clk_hz, baud_rate);					//设置波特率
	
	REG_UART2_ISR = 0x00; 								        //中断状态清除
	REG_UART2_IER = 0x00;       
			
}

/************************************************************************
 * function   : uart2_irq_init
 * description: uart2 irq init
 * input      : uint8_t irq_enable: interrupt enable/disable
 *              void (*uart_recv)(): interrupt callback function 
 * return     : none
 ************************************************************************/
void uart2_irq_init(uint8_t irq_enable,void (*uart_recv)()) 
{
	if(irq_enable == UART2_IRQ_ENABLE)                          //中断使能
	{
		NVIC_ClearPendingIRQ(UART2_IRQn);
		NVIC_EnableIRQ(UART2_IRQn);
		
	#ifdef UART2_TX_INT_MODE			  						//发送采用中断方式
		REG_UART2_IER |= (1 << 1);        						//发送中断使能
	#endif							
		REG_UART2_IER |= (1 << 5);        						//接收FIFO非空中断使能
		uart2_recv_callback = uart_recv;					
	}					
	else					
	{					
	#ifdef UART2_TX_INT_MODE		        					//发送采用中断方式
		REG_UART2_IER &= ~(1 << 1);         					//发送中断失能
	#endif						
		REG_UART2_IER &= ~(1 << 5);         					//接收FIFO非空中断失能
		
		uart2_recv_callback = NULL;
	}
}


/************************************************************************
 * function   : uart2_set_baud_rate
 * description: uart2 set baud rate
 * input      : uint32_t sys_clk_hz: system clock frequency
 *              uint32_t baud_rate: Series rate      
 * return	  : none
 ************************************************************************/
void uart2_set_baud_rate(uint32_t sys_clk_hz, uint32_t baud_rate)
{
	uint16_t temp;
	uint8_t MSbyte, LSbyte;

	temp = sys_clk_hz / baud_rate;

	MSbyte = temp>>8;
	LSbyte = temp;
	
	REG_UART2_BRPH = MSbyte;
	REG_UART2_BRPL = LSbyte;
}

/************************************************************************
 * function   : uart2_send_byte
 * description: uart out byte
 * input 	  : uint8_t c: out byte
 * return     : none
 ************************************************************************/
void uart2_send_byte(uint8_t c)	
{
	REG_UART2_TDR = c;         					 				//输出一个字符
										
#ifdef UART2_TX_INT_MODE						 				//中断方式
	uint16_t timeout;									
	timeout = 65535;									
	while(uart2_tx_flag == 0)  					 				//等待数据发送完成
	{									
		if((timeout--)==0)     					 				//超时等待退出
		break;
	}
	uart2_tx_flag = 0;
#else	
	uint16_t timeout;
	timeout = 65535;
	//查询方式
	while((REG_UART2_ISR & 0x02) != 0x02) 						//等待数据发送完成
	{
		if((timeout--)==0)   									//超时等待退出
		{
			break;
		}
	}
	REG_UART2_ISR &= ~(1<<1);			   						//清除发送完成标志位
#endif	

}

/************************************************************************
 * function   : uart2_recv_byte
 * description: uart2 read one byte's data
 * input 	  : none
 * return	  : data from uart
 ************************************************************************/
uint8_t uart2_recv_byte(void)	
{
	return REG_UART2_RDR;
}

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

	for(i = 0; i < length; i++)
	{
		uart2_send_byte(*buff++);
	}
}

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