/******************** (C) COPYRIGHT 2020 SONiX *******************************
* COMPANY:  SONiX
* DATE:     2021/06
* AUTHOR:   SA1
* IC:       
* DESCRIPTION:  UART1 related functions. This file provides a set of functions
*               used in UART mode 1.
*____________________________________________________________________________
* REVISION  Date        User  Description
* 1.0       2020/06/30  SA1   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 stUART1_Hardware;

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

/**
 * This function is used to initialize the UART1 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 UART1_Init(uint8_t bUartBaudRate, uint8_t* bRxBufAddress, uint8_t bLength)
{
	_SET_UART1_TX_OUTPUT_
	_SET_UART1_RX_INPUT_
	/* Notice: Enable UART1 TX/RX module first. */
	S0CON2 |= TEN1;
	S1CON  |= REN1;
	
	/* S1CON: UART MODE Setting */
	S1CON |= mskUART_MODE1;
		
	if (bUartBaudRate == eBAUD_RATE_TIMER1)
	{
		/* Baud rate generator selection (mode1, 3) (0 : Timer1 overflow period) */
		S0CON2 &= ~BD1; 
	}
	else
	{
		/* Baud rate generator selection (mode1, 3) (1 : Controlled by S0REL) */
		S0CON2 |= BD1;  
		S1RELH = 0x03;
		SMODCAL |= SMOD1;
		
		switch(bUartBaudRate) {
			case eBAUD_RATE_4800:
				S1RELL = BD_4800 & 0x00FF;
				SMODCAL &= ~SMOD1;
				break;
							
			case eBAUD_RATE_9600:
				S1RELL = BD_9600 & 0x00FF;
				SMODCAL &= ~SMOD1;
				break;
			
			case eBAUD_RATE_19200:
				S1RELL = BD_19200 & 0x00FF;
				break;
			
			case eBAUD_RATE_38400:
				S1RELL = BD_38400 & 0x00FF;
				break;
			
			case eBAUD_RATE_56000:
				S1RELL = BD_56000 & 0x00FF;
				break;
			
			case eBAUD_RATE_115200:
				S1RELL = BD_115200 & 0x00FF;
				break;
			
			case eBAUD_RATE_128000:
				S1RELL = BD_128000 & 0x00FF;
				break;
			
			case eBAUD_RATE_250000:
				S1RELL = BD_250000 & 0x00FF;
				break;
			
			default:
				break;
		}
	}

	/* Init UART status. */
	if(bRxBufAddress !=0)
	{
		stUART1_Hardware.fRx_Done = 0;
		stUART1_Hardware.bptrRx_StartAdress = bRxBufAddress;
		stUART1_Hardware.bptrRx_EndAdress = bRxBufAddress + (bLength-1);	
		stUART1_Hardware.bptrRx_Buf = stUART1_Hardware.bptrRx_StartAdress;	
	}
	
	/* Clear Interrupt flags. */ 
	S1CON &= ~RI1;
	S1CON &= ~TI1;
}


/**
 * 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 UART1_TransmitData(uint8_t *bptrData, uint8_t bLength)
{
	while(bLength--)
	{
		/* Write bytes to S1BUF and Polling transmit. */
		S1BUF = *(bptrData++);
		while(!(S1CON & TI1));
		S1CON &= ~TI1;
	}
	_SET_UART1_TX_INPUT_
}

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

/**
 * Received interrupt service routine.
 *
 * @param None
 * @return None
 */
void ISR_UART1_RX() interrupt ISRUart1rx
{
	*(stUART1_Hardware.bptrRx_Buf++) = S0BUF;
	if(stUART1_Hardware.bptrRx_Buf > stUART1_Hardware.bptrRx_EndAdress)
	{
		stUART1_Hardware.bptrRx_Buf = stUART1_Hardware.bptrRx_StartAdress;
		stUART1_Hardware.fRx_Done = 1;
	}
	/* Clear UART Interrupt flag of reception. */
	S1CON &= ~RI1;
}


