/******************** (C) COPYRIGHT 2020 SONiX *******************************
* COMPANY:  SONiX
* DATE:     2022/04/11
* AUTHOR:   SA1
* IC:       
* DESCRIPTION:  UART0 related functions. This file provides a set of functions
*               used in UART mode 1.
*____________________________________________________________________________
* REVISION  Date        User    Description
* 1.0       2022/04/11  SONiX   First release
*
*____________________________________________________________________________
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS TIME TO MARKET.
* SONiX SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL 
* DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE
* AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN 
* IN CONNECTION WITH THEIR PRODUCTS.
*****************************************************************************/

/*_____ I N C L U D E S ____________________________________________________*/
#include "uart.h"

/*_____ D E F I N I T I O N S ______________________________________________*/

/*_____ D E C L A R A T I O N S ____________________________________________*/
UART_Hardware_st stUART0_Hardware;

/*_____ F U N C T I O N S __________________________________________________*/

/**
 * @Brief	This function is used to initialize the UART0 function and set the UART
 * 				mode and baud rate in mode 1. 
 *
 * @param bUartBaudRate The baud rate selection. Mode1 supports an asynchronous
 *                      8-bit UART with variable baud rate. The baud rate clock 
 *                      source is from baud rate generator or from Timer 1. Here
 *                      is the selections below. \n
 *                      - eBAUD_RATE_TIMER1
 *                      - eBAUD_RATE_4800
 *                      - eBAUD_RATE_9600
 *                      - eBAUD_RATE_19200
 *                      - eBAUD_RATE_38400
 *                      - eBAUD_RATE_56000
 *                      - eBAUD_RATE_57600
 *                      - eBAUD_RATE_115200
 *                      - eBAUD_RATE_128000
 *                      - eBAUD_RATE_250000
 *  
 * @note If you set baud rate clock source from Timer1, you need to configure timer1
 *       before initializing UART.
 *
 */
void UART0_Init(uint8_t bUartBaudRate, uint8_t* bRxBufAddress, uint8_t bLength)
{
	_SET_UART0_TX_OUTPUT_
	_SET_UART0_RX_INPUT_

	/* Notice: Enable UART0 TX/RX module first. */
	S0CON  |= REN0;
	S0CON2 |= TEN0;

	/* S0CON: UART MODE Setting */
	S0CON |= mskUART_MODE1;
		
	if (bUartBaudRate == eBAUD_RATE_TIMER1)
	{
		/* Baud rate generator selection (mode1, 3) (0 : Timer1 overflow period) */
		S0CON2  &= ~BD0; 
		TMOD |= (mskT1CT|mskT1_Mode2);           
		PCON |= SMOD0;             
		TCON0|= mskT1Fhosc_1;      
		
		TL1 = TBD_250000;
		TH1 = TBD_250000;
		
		TCON |= mskTR1;
	}
	else
	{
		/* Baud rate generator selection (mode1, 3) (1 : Controlled by S0REL) */
		S0CON2 |= BD0;  
		S0RELH = 0x03;
		PCON |= SMOD0;
		
		switch(bUartBaudRate) {
			case eBAUD_RATE_4800:
				S0RELL = BD_4800 & 0x00FF;
				PCON &= ~SMOD0;
				break;
							
			case eBAUD_RATE_9600:
				S0RELL = BD_9600 & 0x00FF;
				PCON &= ~SMOD0;
				break;
			
			case eBAUD_RATE_19200:
				S0RELL = BD_19200 & 0x00FF;
				PCON &= ~SMOD0;			
				break;
			
			case eBAUD_RATE_38400:
				S0RELL = BD_38400 & 0x00FF;
				break;
			
			case eBAUD_RATE_56000:
				S0RELL = BD_56000 & 0x00FF;
				break;
			
			case eBAUD_RATE_115200:
				S0RELL = BD_115200 & 0x00FF;
				break;
			
			case eBAUD_RATE_128000:
				S0RELL = BD_128000 & 0x00FF;
				break;
			
			case eBAUD_RATE_250000:
				S0RELL = BD_250000 & 0x00FF;
				break;
			
			case eBAUD_RATE_500000:
				S0RELL = BD_500000 & 0x00FF;
				break;
			
			default:
				break;
		}
	}

	/* Init UART status. */
	if(bRxBufAddress !=0)
	{
		stUART0_Hardware.fRx_Done = 0;
		stUART0_Hardware.bptrRx_StartAdress = bRxBufAddress;
		stUART0_Hardware.bptrRx_EndAdress = bRxBufAddress + (bLength-1);	
		stUART0_Hardware.bptrRx_Buf = stUART0_Hardware.bptrRx_StartAdress;
	}
	
	/* Clear Interrupt flags. */ 
	S0CON &= ~RI0;
	S0CON &= ~TI0;
	
	/* Enable UART Interrupt. */
	UART0_RX_ISR_EN();
}


/**
 * @Brief	Transmit an amount of data via UART. The data to be sent is stored in the transmission
 * 				FIFO that is implemented by software.
 * @param pData Points to a data array to be sent.
 * @param bLength The length of the data to be sent.
 * @return None
 */
void UART0_TransmitData(uint8_t* bptrData, uint8_t bLength)
{
	while(bLength--)
	{
		/* Write the first byte to S0BUF and start to transmit. */
		S0BUF = *(bptrData++);
		while(!(S0CON & TI0));
		S0CON &= ~TI0;
	}
}

/**
 * @Brief		Check UART received done or not
 * @param 	bLength, bptrData address
 * @return 	True or Flase
 */
bit UART0_ReceivedDone(void)
{
	if(stUART0_Hardware.fRx_Done)
	{
		stUART0_Hardware.fRx_Done = 0;		
		return 1;
	}
	else
	{
		return 0;
	}
}


/**
 * Received interrupt service routine.
 *
 * @param None
 * @return None
 */
void ISR_UART0_RX() interrupt ISRUart0RX
{
	*(stUART0_Hardware.bptrRx_Buf++) = S0BUF;
	if(stUART0_Hardware.bptrRx_Buf > stUART0_Hardware.bptrRx_EndAdress)
	{
		stUART0_Hardware.bptrRx_Buf = stUART0_Hardware.bptrRx_StartAdress;
		stUART0_Hardware.fRx_Done = 1;
	}
	/* Clear UART Interrupt flag of reception. */
	S0CON &= ~RI0;
}

