/***********************************************************************
 * Copyright (c)  2017 - 2020, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : uart1.c
 * Description : uart1 driver source file
 * Author(s)   : Kian
 * version     : V1.0
 * Modify date : 2020.12.30
 ***********************************************************************/
#include  "uart1.h"

extern uint8_t uart1_tx_flag ;
void (*uart1_recv_callback)(void) = NULL;

/************************************************************************
 * function   : UART_IRQHandler
 * Description: uart interrupt handling
 * input : none
 * return: none
 ************************************************************************/
void UART1_IRQHandler(void)
{
	if( (REG_UART1_IIR & 0x0f)==0x04 )   
	{		
		if(uart1_recv_callback!= NULL)
		{
			(*uart1_recv_callback)(); 		//uart1的接收处理回调函数
		}	
	//	清除中断状态(读FIFO相关状态位硬件会自动清)
	}
}

/************************************************************************
 * function   : uart_init
 * Description: uart initial for  baud_rate
 * input : 
 *         UINT32 baud_rate: Series rate
 * return: none
 ************************************************************************/
void uart1_init(uint32_t sys_clk_hz,uint32_t baud_rate)
{
	REG_SCU_PERICLKEN |= (1<<10);		//开UART时钟使能	
	REG_SCU_PERIRESET |= (1<<10);		//UART正常工作
	
	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; //清除IO写保护
	
	REG_SCU_PCSEL = (REG_SCU_PCSEL&(~(7<<4)))|(2<<4);		  //PC1复用为UART1_TX
	REG_SCU_PCSEL = (REG_SCU_PCSEL&(~(7<<8)))|(2<<8);		  //PC2复用为UART1_RX	

	REG_SCU_IOCTRLPROTECT = 0xffffffff; //开启IO写保护
	while((REG_SCU_IOCTRLPROTECT & 0x01) == 0x01)      //读IO控制保护寄存器的写使能状态
	{	
		REG_SCU_IOCTRLPROTECT = 0xffffffff; //开启IO写保护
	}
	
	REG_UART1_MCR = 0x00;     	//流控制不使能  
	uart1_set_baud_rate(sys_clk_hz, baud_rate);		//设置波特率
	REG_UART1_FCR = 0x01;  		//接收FIFO 1字节触发非空中断，发送FIFO空中断,使能FIFO
    REG_UART1_LCR = 0x03;		//无校验位，1位停止位，8bits数据，
	
}

/************************************************************************
 * function   : uart1_irq_init
 * Description: uart1 irq init
 * input : 
 *         uint8_t irq_enable: interrupt enable/disable
		   void (*uart_recv)(): interrupt callback function 
 * return: none
 ************************************************************************/

void uart1_irq_init(uint8_t irq_enable, void (*uart_recv)())  
{
	if(irq_enable == UART1_IRQ_ENABLE)
	{
		REG_UART1_IER |= 0x01;		//开启接收FIFO非空中断
		uart1_recv_callback = uart_recv;
	
		NVIC_ClearPendingIRQ(UART1_IRQn);
		NVIC_EnableIRQ(UART1_IRQn);
	}
	else
	{
		REG_UART1_IER &= ~0x01;		//关闭接收FIFO非空中断
		uart1_recv_callback =NULL;
	}
		
}
/************************************************************************
 * function   : uart_set_baud_rate
 * Description: uart set baud rate
 * input : 
 *         uint32_t clk_hz: cpu frequency
 *         uint32_t baud_rate: Series rate
 * return: none
 ************************************************************************/
void uart1_set_baud_rate(uint32_t clk_hz, uint32_t baud_rate)
{
	uint32_t integer,fraction;
	uint8_t MSbyte, LSbyte;	
	
	integer = (clk_hz)/(16*baud_rate);						//波特率整数部分
	fraction = ((((clk_hz)%(baud_rate*16))+ (baud_rate/2))/baud_rate);					//波特率小数部分
	
	MSbyte = integer>>8;
	LSbyte = integer;
	
	REG_UART1_DLF = fraction&0x3f;
	REG_UART1_LCR |= 0x80;      //需要动态调整波特率
	REG_UART1_DLH = MSbyte;
	REG_UART1_DLL = LSbyte;
	REG_UART1_LCR &= ~0x80;      //需要动态调整波特率
}


/************************************************************************
 * function   : outbyte
 * Description: uart out byte
 * input : 
 *         char c: out byte
 * return: none
 ************************************************************************/

void uart1_send_byte(uint8_t c)	
{
//	1.输出一个字符
	uint16_t timeout;
	timeout = 65535;
	
	REG_UART1_THR = c;
	
	 while((REG_UART1_LSR & 0x40) != 0x40)		//等待数据发送完成
	{
		if((timeout--)==0)   //超时等待退出
		{
			break;
		}
	}
}

/************************************************************************
 * function   : uart1_recv_byte
 * Description: uart1 read one byte's data
 * input : none
 *         
 * return: data from uart
 ************************************************************************/
uint8_t uart1_recv_byte(void)	
{
	return REG_UART1_RBR;
}

/************************************************************************
 * function   : uart_send_bytes
 * Description: uart send bytes
 * input : 
 *         uint8_t* buff: out buffer
 *         uint32_t length: buffer length
 * return: none
 ************************************************************************/
void uart1_send_bytes(uint8_t *buff, uint32_t length)
{
	uint32_t i;

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

/************************************************************************
 * function   : uart1_rec_bytes 
 * Description: uart1 receive bytes by polling mode
 * input : 
 *         uint8_t* buff: receive buffer
 *         uint32_t length: buffer length
 * return: none
 ************************************************************************/
void uart1_rec_bytes(uint8_t *buff, uint32_t length)
{
	while(length--)
	{
		while((REG_UART1_IIR & 0x0f) !=0x04);	//wait rx not empty	
		*buff++ = REG_UART1_RBR;	
	}	
		
}


