

/**
 ******************************************************************************
 *
 * @file        MG32x02z_USBD_COM_API.c
 * @brief       The USBD COM Code's c file.
 *
 * @par         Project
 *              MG32x02z
 * @version     V1.00
 * @date        2023/04/07
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 * 
 ******************************************************************************* 
 * @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */
 
/* Includes ------------------------------------------------------------------*/ 
#include "MG32x02z.h"
#include "MG32x02z_GPIO_DRV.h"
#include "MG32x02z_CSC_Init.h"
#include "MG32x02z_USBD_API.h"
#include "MG32x02z_USBD_Descriptor_API.h"
#include "MG32x02z_USBD_EasyCOM_API.h"


#if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
    #include "MG32x02z_URT_DRV.h"
#endif

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//CSC wizard
#define COM_SYS_FREQ                       CONF_CK_APB_FREQ              /*!< System clock source frequency.*/

//USB module 
#define COM_STATUS_EP                      USB_EP3                       /*!< COM STATUS Endpoint.*/
#define COM_DATAUPSTREAM_EP                USB_EP4                       /*!< COM upstream data Endpoint.*/
#define COM_DATADOWNSTREAM_EP              USB_EP4                       /*!< COM downstream data Endpoint.*/


#define COM_DATAUPSTREAM_DATASIZE          EP4_IN_PACKET_SIZE            /*!< COM upstream MAX. data size.*/
                                                                                                                                               
#define COM_DATAUPSTREAM_BUFFER_SIZE       EP4_IN_PACKET_SIZE            /*!< MAX size for COM upstream software buffer.*/
#define COM_DATADOWNSTREAM_BUFFER_SIZE     EP4_OUT_PACKET_SIZE           /*!< MAX size for COM downstream software buffer.*/


#if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
//URT module
#define COM_URT                            URT0
#define COM_URT_IRQn                       URT0_IRQn
#define COM_URT_IRQHandler                 URT0_IRQHandler

//GPIO module
#define COM_URT_TX_PINX                    PINB(8)
#define COM_URT_TX_AFS                     3

#define COM_URT_RX_PINX                    PINB(9)
#define COM_URT_RX_AFS                     3

#endif

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

static uint32_t         COM_USB_ErrorCode;

#if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART

                                                                          
static uint8_t          COM_USB_pOutUpstreamBuf;              /*!< Read pointer of UpstreamBuf ( USB upstream buffer).*/
static uint8_t          COM_USB_pInUpstreamBuf;               /*!< Write pointer of UpstreamBuf ( USB upstream buffer).*/
static uint8_t  __IO    COM_USB_UpstreamBufCnt;               /*!< UpstreamBuf (USB upstream buffer) total data conut.*/



static URT_Data_TypeDef COM_URT_DataDef;                      /*!< URT character format control .*/
static uint32_t         COM_URT_BaudRate;                     /*!< URT baud-rate.*/

static uint8_t          *COM_URT_TxBuf;                       /*!< Easy COM URT transmit data buffer pointer.*/
static uint32_t         COM_URT_pTxTransferCount;             /*!< URT transmit data byte.*/
#endif


COM_TypeDef COM;                                              /*!< Control parameter of COM.*/

static uint8_t COM_USB_OUTUpstreamBuf[EP4_OUT_PACKET_SIZE];   /*!< USB OUT upstream buffer .*/
static uint8_t COM_USB_INUpstreamBuf[EP4_IN_PACKET_SIZE];     /*!< USB IN upstream buffer  .*/
static uint8_t COM_USB_DownstramBuf[EP4_OUT_PACKET_SIZE];     /*!< USB down stream buffer  .*/


/* Private function prototypes -----------------------------------------------*/
#if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
void URT0_IRQHandler(void);
#endif

static void API_USBD_COM_SetUARTState(void);
static uint32_t URTn_BaudRate_Config(uint32_t BRClockSourceFreq, uint32_t BaudRate);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/                                     
/* External variables --------------------------------------------------------*/


/**
 *******************************************************************************
 * @brief    COM relationship hardware and software initial.
 * @details    
 * @param    	
 * @return      
 *******************************************************************************
 */
void API_COM_Init(void)
{
    PIN_InitTypeDef COM_Pin_Init;
    
    //==========================================================
    //1. COM Line Coding parameter intial
    //2. COM software control parameter initial.
    
    COM.LineCoding.BaudRate.W        = 9600;
    COM.LineCoding.StopBit           = COM_STOPBIT_1_0;
    COM.LineCoding.Parity            = COM_PARITY_None;
    COM.LineCoding.DataBit           = 8;
    
    COM.COM_USB_DataDownstream_Busy      = 0;
    COM.COM_USB_DataUpstream_Busy        = 0;
    COM.COM_USB_StatusUpstream_Busy      = 0;
    COM.COM_USB_DataDownstream_Size      = 0;
    COM.COM_USB_DataUpstream_OverrunFlag = 0;
    COM.Status                           = 0;
    
    COM_USB_ErrorCode                    = 0;
    
    //=========================================================
    //Buffer Control Initial
    #if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
        COM_USB_pOutUpstreamBuf = 0;
        COM_USB_pInUpstreamBuf  = 0;
        COM_USB_UpstreamBufCnt  = 0;
    #endif
    //==========================================================
    //UART State bitmap
    #if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART

        COM.COM_Status_EP_SRAM[0] = 0xA1;                              
        COM.COM_Status_EP_SRAM[1] = PSTN_SERIAL_STATE;                 
        COM.COM_Status_EP_SRAM[2] = 0x00;                              
        COM.COM_Status_EP_SRAM[3] = 0x00;                              
        COM.COM_Status_EP_SRAM[4] = 0x00;
        COM.COM_Status_EP_SRAM[5] = 0x00;
        COM.COM_Status_EP_SRAM[6] = 0x02;
        COM.COM_Status_EP_SRAM[7] = 0x00;
        COM.COM_Status_EP_SRAM[8] = COM.Status ;                              /*!< UART State bitmap [ D7  : D0]                         */
        COM.COM_Status_EP_SRAM[9] = 0x00;                                     /*!<                   [ D15 : D8] : RESERVED (future use) */
        
    #endif
    //==========================================================
    //Bridge :  COM to UART
    #if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
       /* RX / TX pin configure*/
       COM_Pin_Init.PINX_Mode				= PINX_Mode_PushPull_O;           /*!< Pin mode is push pull mode.*/
       COM_Pin_Init.PINX_PUResistant        = PINX_PUResistant_Enable;        /*!< Enable internal pull-up resistance.*/
       COM_Pin_Init.PINX_Speed              = PINX_Speed_Low;                 
       COM_Pin_Init.PINX_OUTDrive           = PINX_OUTDrive_Level0;           /*!< Pin output drive strength is "Drive strength-full".*/
       COM_Pin_Init.PINX_FilterDivider      = PINX_FilterDivider_Bypass;      /*!< Disable Pin input filter.*/
       COM_Pin_Init.PINX_Inverse            = PINX_Inverse_Disable;           /*!< Disable Pin input inverse.*/
       COM_Pin_Init.PINX_Alternate_Function = COM_URT_TX_AFS;                 /*!< The pin alternate function is URT0_TX.*/ 
       GPIO_PinMode_Config(COM_URT_TX_PINX,&COM_Pin_Init);
       
       COM_Pin_Init.PINX_Mode				= PINX_Mode_Digital_I;            /*!< Pin mode is digital input.*/
       COM_Pin_Init.PINX_Alternate_Function = COM_URT_RX_AFS;                 /*!< The pin alternate function is URT0_RX.*/
       GPIO_PinMode_Config(COM_URT_RX_PINX,&COM_Pin_Init);
       /*
         Character Format Default Configure.
         *. Data bit         : 8 bit
         *. Data order       : LSB
         *. Parity bit       : None
         *. Stop bit         : 1 bit
         *. Data bit inverse : Disable.         
       */
       COM_URT_DataDef.URT_TX_DataLength = URT_DataLength_8;                  /*!< URT TX data length is 8 bit.*/
       COM_URT_DataDef.URT_RX_DataLength = URT_DataLength_8;                  /*!< URT RX data length is 8 bit.*/
       COM_URT_DataDef.URT_TX_DataOrder  = URT_DataTyped_LSB;                 /*!< URT TX data order is LSB.*/
       COM_URT_DataDef.URT_RX_DataOrder  = URT_DataTyped_LSB;                 /*!< URT RX data order is LSB.*/
       COM_URT_DataDef.URT_TX_Parity     = URT_Parity_No;                     /*!< URT TX no parity bit.*/
       COM_URT_DataDef.URT_RX_Parity     = URT_Parity_No;                     /*!< URT RX no parity bit.*/
       COM_URT_DataDef.URT_TX_StopBits   = URT_StopBits_1_0;                  /*!< URT TX stop bit is 1 bit.*/
       COM_URT_DataDef.URT_RX_StopBits   = URT_StopBits_1_0;                  /*!< URT RX stop bit is 1 bit.*/
       COM_URT_DataDef.URT_TX_DataInverse= DISABLE;                           /*!< URT TX data bit no inverse.*/
       COM_URT_DataDef.URT_RX_DataInverse= DISABLE;                           /*!< URT RX data bit no inverse.*/
       URT_DataCharacter_Config(COM_URT,&COM_URT_DataDef); 
       
       /*Baud-Rate configure*/
       COM_URT_BaudRate = 9600;
       
       URT_TXClockSource_Select(COM_URT, URT_TXClock_Internal);	              /*!< TX clock source from Baud-Rate Generator.*/
       URT_RXClockSource_Select(COM_URT, URT_RXClock_Internal);	              /*!< RX clock source from Baud-Rate Generator.*/
       URTn_BaudRate_Config(COM_SYS_FREQ,COM_URT_BaudRate);                   /*!< Baud-Rate Generator Configure.*/
       
       
       /*Mode configure*/
       URT_Mode_Select(COM_URT, URT_URT_mode);                                /*!< URT module mode is UART mode.*/
       URT_DataLine_Select(COM_URT, URT_DataLine_2);                          /*!< URT data line is 2 line.*/
       URT_TX_Cmd(COM_URT, ENABLE);	                                          /*!< URT TX function enable.*/
       URT_RX_Cmd(COM_URT, ENABLE);                                           /*!< URT RX function enable.*/
       
       /*Buffer configure*/
       URT_RXShadowBufferThreshold_Select(COM_URT, URT_RXTH_4BYTE);           
       URT_IdlehandleMode_Select(COM_URT, URT_IDLEMode_No);
       URT_TXGuardTime_Select(COM_URT, 0);
       URT_ClearRXData(COM_URT);
       URT_ClearTXData(COM_URT);
       
       /*Set Bus Status Detect Control*/
       //Idle detect config.
       URT_TimeoutMode_Select(COM_URT,URT_TMOMDS_URT);
       URT_TimeoutTimerClockSource_Select(COM_URT,URT_TMOCLK_BitTime);        /*Timeout timer clock source from RX bit time,*/
       URT_IdleDetect_Select(COM_URT,10);                                     /*Becase timeout timer clock source from RX bit time
                                                                               , the value unit is bit time.
                                                                               RX Idle Status : no detect next byte over 10 bit time*/
       URT_TimeroutTimer_Cmd(COM_URT,ENABLE);                                 
       URT_IdlehandleMode_Select(COM_URT, URT_IDLEMode_Load);                 /*When detecting RX bus idle and RX data register is empty
                                                                                load RX shadow buffer into RX data register.*/
                                                                               
       /*Interrupt configure*/
       URT_IT_Config(COM_URT,(URT_IT_TC|URT_IT_TX),DISABLE);                   
       URT_IT_Config(COM_URT,(URT_IT_RX|URT_IT_ERR|URT_IT_FE|URT_IT_PE|URT_IT_ROVR),ENABLE);                               
       URT_ITEA_Cmd(COM_URT, ENABLE);
       NVIC_EnableIRQ(COM_URT_IRQn);
       
       /*Enable URT*/
       URT_Cmd(COM_URT, ENABLE);

    #endif
}
/**
 *******************************************************************************
 * @brief     Receive line coding command and handle relationship setting. 	
 * @details    
 * @param[in] sLineCodingBuf : Set line coding command buffer.
 * @return      
 *******************************************************************************
 */
uint32_t API_COM_SetLineCoding(uint8_t* sLineCodingBuf)
{
    uint32_t  COM_SetLineCodingBRTmp;
    uint8_t   COM_SetLineCodingTmp;
    
    //=========================================================
    //Decode set LineCoding parameter.
    COM.LineCoding.BaudRate.B[0] = sLineCodingBuf[0];                        /*!< Baud-Rate [3:0] */
    COM.LineCoding.BaudRate.B[1] = sLineCodingBuf[1];
    COM.LineCoding.BaudRate.B[2] = sLineCodingBuf[2];
    COM.LineCoding.BaudRate.B[3] = sLineCodingBuf[3];
    COM.LineCoding.StopBit       = sLineCodingBuf[4];                        /*!< Stop bit        */
    COM.LineCoding.Parity        = sLineCodingBuf[5];                        /*!< Parity bit      */
    COM.LineCoding.DataBit       = sLineCodingBuf[6];                        /*!< Data bit        */
    COM.LineCoding.Flag          = SET;                                          
    
    //=========================================================
    //COM Relationship Control Parameter Default Initial.
    COM.COM_USB_DataDownstream_Busy      = 0;
    COM.COM_USB_DataUpstream_Busy        = 0;
    COM.COM_USB_StatusUpstream_Busy      = 0;
    COM.COM_USB_DataDownstream_Size      = 0;
    COM.COM_USB_DataUpstream_OverrunFlag = 0;
    
    //=========================================================
    //Buffer Control Initial 
    #if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
        COM_USB_pOutUpstreamBuf = 0;
        COM_USB_pInUpstreamBuf  = 0;
        COM_USB_UpstreamBufCnt  = 0;
    #endif
    
    //==========================================================
    //Bridge :  COM to UART
    //  - UART Initial
    #if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
        //-----------------------------------------------------------
        //Data Bit Initial.
        if(COM.LineCoding.DataBit == 7)
        {
            COM_SetLineCodingTmp   =  URT_DataLength_7;
        }
        else
        {
            COM_SetLineCodingTmp   =  URT_DataLength_8;
            COM.LineCoding.DataBit    = 8;
        }
        COM_URT_DataDef.URT_TX_DataLength = (URT_DataLength_TypeDef)COM_SetLineCodingTmp;
        COM_URT_DataDef.URT_RX_DataLength = (URT_DataLength_TypeDef)COM_SetLineCodingTmp;
        
        //-----------------------------------------------------------
        //Data Terminal Rate Initial.
        COM_SetLineCodingBRTmp  =  COM_URT_BaudRate;
        
        COM_URT_BaudRate        =  COM.LineCoding.BaudRate.W;
        
        //-----------------------------------------------------------
        //Stop Bit Initial
        if( COM.LineCoding.StopBit == COM_STOPBIT_1_0)
        {
            COM_SetLineCodingTmp   =  URT_StopBits_1_0;  
        }
        else if(COM.LineCoding.StopBit == COM_STOPBIT_1_5)
        {
            COM_SetLineCodingTmp   =  URT_StopBits_1_5;   
        }
        else
        {
            COM_SetLineCodingTmp   =  URT_StopBits_2_0;   
        }
        COM_URT_DataDef.URT_TX_StopBits   = (URT_STOP_TypeDef)COM_SetLineCodingTmp;
        COM_URT_DataDef.URT_RX_StopBits   = (URT_STOP_TypeDef)COM_SetLineCodingTmp;
        
        //----------------------------------------------------------
        //Parity Bit Initial.
        if( COM.LineCoding.Parity == COM_PARITY_Odd)
        {
            COM_SetLineCodingTmp    =  URT_Parity_Odd;
        }
        else if( COM.LineCoding.Parity == COM_PARITY_Even)
        {
            COM_SetLineCodingTmp    =  URT_Parity_Even;
        }
        else if( COM.LineCoding.Parity == COM_PARITY_Mark)
        {
            COM_SetLineCodingTmp    =  URT_Parity_All_H;
        }
        else if( COM.LineCoding.Parity == COM_PARITY_Space)
        {
            COM_SetLineCodingTmp    =  URT_Parity_All_L;
        }
        else
        {
            COM_SetLineCodingTmp    =  URT_Parity_No;
        }
        COM_URT_DataDef.URT_TX_Parity     = (URT_Parity_TypeDef)COM_SetLineCodingTmp;
        COM_URT_DataDef.URT_RX_Parity     = (URT_Parity_TypeDef)COM_SetLineCodingTmp;
        
        
        if(URTn_BaudRate_Config(COM_SYS_FREQ,COM_URT_BaudRate)== COM_FAILURE)
        {
            COM_URT_BaudRate = COM_SetLineCodingBRTmp;
            return(COM_FAILURE);
        }
        URT_DataCharacter_Config(COM_URT,&COM_URT_DataDef);
        URT_ClearRXData(COM_URT);
        URT_ClearTXData(COM_URT);

        return( COM_SUCCESS);
    #endif
}
/**
 *******************************************************************************
 * @brief     Write line coding state to gLineCodingBuf 
 * @details    
 * @param[in] gLineCodingBuf : LineCoding command buffer.
 * @return      
 *******************************************************************************
 */
void API_COM_GetLineCoding(uint8_t* gLineCodingBuf)
{
    gLineCodingBuf[0] = COM.LineCoding.BaudRate.B[0];
    gLineCodingBuf[1] = COM.LineCoding.BaudRate.B[1];
    gLineCodingBuf[2] = COM.LineCoding.BaudRate.B[2];
    gLineCodingBuf[3] = COM.LineCoding.BaudRate.B[3];
    gLineCodingBuf[4] = COM.LineCoding.StopBit;
    gLineCodingBuf[5] = COM.LineCoding.Parity;
    gLineCodingBuf[6] = COM.LineCoding.DataBit;
   
}
/**
 *******************************************************************************
 * @brief     Decode set control line state command.  
 * @details  
 * @param[in] sControlLineStateBuf : Control line state command buffer.
 * @return      
 *******************************************************************************
 */ 
void API_COM_SetControlLineState(uint8_t* sControlLineStateBuf)
{
    COM.LineState.ControlSignalBitmp.B[0] = sControlLineStateBuf[2];
    COM.LineState.ControlSignalBitmp.B[1] = sControlLineStateBuf[3];
    COM.LineState.Flag                    = SET;
}
/**
 *******************************************************************************
 * @brief    Decode send break command.
 * @details 
 * @param    	
 * @return         	
 *******************************************************************************
 */ 
void API_COM_SendBreak(uint8_t* SendBreakBuf)
{
    COM.SendBreak.DurationTime.B[0] = SendBreakBuf[2];
    COM.SendBreak.DurationTime.B[1] = SendBreakBuf[3];
    COM.SendBreak.Flag              = SET;
}

/**
 *******************************************************************************
 * @brief    Receive USB COM downstream data to buffer. 	
 * @details
 * @param    	
 * @return      
 * @note     Release COM downstream Endpoint after TX end.   	
 *******************************************************************************
 */ 
void API_COM_ReceiveDownstreamData(void)
{
    COM.COM_USB_DataDownstream_Size = USB_GetEndpointRXData(COM_DATADOWNSTREAM_EP,&COM_USB_DownstramBuf[0],DISABLE);
    
    if( COM.COM_USB_DataDownstream_Size !=0)
    {
        COM.COM_USB_DataDownstream_Busy = 1;
    }
}

/**
 *******************************************************************************
 * @brief   USB COM main function.   	
 * @details 
 * @param    	
 * @return         	
 *******************************************************************************
 */  
void API_USBD_COM_main(void)
{
    uint8_t USBD_COM_mainTmp ;
    uint8_t USBD_COM_mainRXTmp;
    
    //==========================================================
    // The USB device has not enumeration success yet.
    if( (Ep0.USBStatus & USB_STATUS_EMULATION_MASK) == 0)
    {
        return;
    }
    
    //==========================================================
    //Bridge :  COM to UART
    #if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART   
        //--------------------------------------------------------------
        //Set URT RX Data to USB Host.

        if( COM.COM_USB_DataUpstream_Busy == 0 && COM_USB_UpstreamBufCnt != 0)
        {
            USBD_COM_mainTmp   = 0;
            USBD_COM_mainRXTmp = COM_USB_UpstreamBufCnt;
            
            do{
                
                COM_USB_OUTUpstreamBuf[USBD_COM_mainTmp] = COM_USB_INUpstreamBuf[COM_USB_pOutUpstreamBuf];
                
                if( COM_USB_pOutUpstreamBuf < (COM_DATAUPSTREAM_BUFFER_SIZE - 1))
                {
                    COM_USB_pOutUpstreamBuf = COM_USB_pOutUpstreamBuf + 1;
                }
                else
                {
                    COM_USB_pOutUpstreamBuf = 0;
                }
                
                USBD_COM_mainTmp    = USBD_COM_mainTmp   + 1;
                USBD_COM_mainRXTmp  = USBD_COM_mainRXTmp - 1;
                
                if( USBD_COM_mainTmp == COM_DATAUPSTREAM_DATASIZE)
                {
                    break;
                }
            }while( USBD_COM_mainRXTmp !=0); 
        
            COM_URT->INT.W         = COM_URT->INT.W & ((uint32_t)(~URT_IT_RX));
            COM_USB_UpstreamBufCnt = COM_USB_UpstreamBufCnt - USBD_COM_mainTmp;
            COM_URT->INT.W         = COM_URT->INT.W | URT_IT_RX;
            
            COM.COM_USB_DataUpstream_Busy = 1;
            USB_SetEndpointTXData( COM_DATAUPSTREAM_EP, &COM_USB_OUTUpstreamBuf[0] , USBD_COM_mainTmp);
            
        } 
        //-------------------------------------------------------
        //Send URT TX Data.
        if( COM.COM_USB_DataDownstream_Busy == 1)
        {
            COM.COM_USB_DataDownstream_Busy = 0;
            
            COM_URT_TxBuf            = &COM_USB_DownstramBuf[0];
            COM_URT_pTxTransferCount = COM.COM_USB_DataDownstream_Size;
            URT_IT_Config(COM_URT,URT_IT_TX,ENABLE);
        }
        //-------------------------------------------------------
        //Set URT status to USB Host.
        #if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART
            API_USBD_COM_SetUARTState();
        #endif
    #endif
    //===========================================================
    if( COM.LineState.Flag == 1)
    {
        // To do......
        COM.LineState.Flag = 0;
    }        
    if( COM.SendBreak.Flag == 1)
    {
        // To do......
        COM.SendBreak.Flag = 0;
    }        
}

/**
 * @name Bridge device (UART)
 *   		
 */         
///@{

#if API_COM_BRIDGE_DEVICE == API_COM_BRIDGE_DEVICE_UART

/**
 *******************************************************************************
 * @fn        Calculated URT module baud-rate setting value. 
 * @details 
 * @param[in] BRClockSourceFreq : URT Baud-rate generator clock source frequency.
 * @param[in] BaudRate : Expected baud-rate.
 * @param    	
 * @return    Calculated whether success.     	
 *******************************************************************************
 */  
static uint32_t URTn_BaudRate_Config(uint32_t BRClockSourceFreq, uint32_t BaudRate)
{
    uint32_t TRXOverSamplingSampleNumber = 8;
    uint32_t Tmp;
	
    uint8_t BST_SOL,OVSMP,REM;    
    
    
    //==========================================
    //Baudrate
    Tmp = BRClockSourceFreq / BaudRate;
    if(Tmp<8)
    {
        return(COM_FAILURE);
    }
	//================TX and RX oversampling value===================
	BST_SOL = 0;
	for(OVSMP=8;OVSMP<32;OVSMP++)
	{
		REM = Tmp % OVSMP;
		if(REM==0)
		{
            if( (Tmp / OVSMP)<4096)
            {
			    TRXOverSamplingSampleNumber = OVSMP;
			    break;
            }
		}
		else
		{
			if((OVSMP-REM)>BST_SOL || (OVSMP-REM)==BST_SOL)
			{
				BST_SOL = OVSMP - REM;
				TRXOverSamplingSampleNumber = OVSMP;
			}
		}
	}
    
	COM_URT->CLK.W = COM_URT->CLK.W & (~(URT_CLK_TX_CKS_mask_w| URT_CLK_RX_CKS_mask_w | URT_CLK_CK_SEL_mask_w));
	Tmp = Tmp / (TRXOverSamplingSampleNumber);
    if(Tmp>4096)
    {
        return(COM_FAILURE);
    }
    COM_URT->RLR.H[0] = (uint16_t)(Tmp - 1);
     
    
    TRXOverSamplingSampleNumber = TRXOverSamplingSampleNumber - 1;
    COM_URT->CR1.B[3] = (uint8_t)TRXOverSamplingSampleNumber;
    COM_URT->CR1.B[1] = (uint8_t)TRXOverSamplingSampleNumber;
    
    COM_URT->CLK.W = COM_URT->CLK.W | (URT_CLK_BR_MDS_combined_w | URT_CLK_BR_EN_enable_w);

    return(COM_SUCCESS);
}

/**
 *******************************************************************************
 * @fn       URT interrupt handler.
 * @details 
 * @param    	
 * @return         	
 *******************************************************************************
 */ 
void COM_URT_IRQHandler(void)
{
    uint32_t COM_URT_IRQHandlerFlag;
    uint32_t COM_URT_IRQHandlerTmp,COM_URT_IRQHandlerTmp2;
    ctype    COM_URT_IRQHandlerTXBuf;
    ctype    COM_URT_IRQHandlerRXBuf;          
    
                         
    COM_URT_IRQHandlerFlag = (URT_GetITAllFlagStatus(COM_URT) & URT_GetITStatus(COM_URT));
    
    /*Receive interrupt*/
    if((COM_URT_IRQHandlerFlag & URT_IT_RX))
    {
        COM_URT_IRQHandlerTmp     = URT_GetRXDataRegLevel(COM_URT);       /*Read data byte number when data shadodw buffer last transfer to 
                                                                            URTx_RDAT register */
        COM_URT_IRQHandlerRXBuf.W = URT_GetRXData(COM_URT);               /*Read received data*/  
        URT_ClearRxHoldFlag(COM_URT);                                     /*When Idle mode select Load (Force to load shadow buffer) and 
                                                                            idle load event occurs RHF (receive hold flag) will be to set, so
                                                                            has to clear the event flag.    
                                                                          */
        
        COM_URT_IRQHandlerTmp      = COM_URT->CR4.MBIT.RNUM;
        COM_URT_IRQHandlerRXBuf.W  = COM_URT->RDAT.W;

        if( COM_URT_IRQHandlerTmp > (COM_DATAUPSTREAM_BUFFER_SIZE - COM_USB_UpstreamBufCnt))
        {
            COM_URT_IRQHandlerTmp = (COM_DATAUPSTREAM_BUFFER_SIZE - COM_USB_UpstreamBufCnt);
            COM.COM_USB_DataUpstream_OverrunFlag = 1;
        }
        
        for(COM_URT_IRQHandlerTmp2=0;COM_URT_IRQHandlerTmp2<COM_URT_IRQHandlerTmp;COM_URT_IRQHandlerTmp2++)
        {
            COM_USB_INUpstreamBuf[ COM_USB_pInUpstreamBuf] = COM_URT_IRQHandlerRXBuf.B[COM_URT_IRQHandlerTmp2];
            
            COM_USB_UpstreamBufCnt = COM_USB_UpstreamBufCnt + 1;   
            
            if( COM_USB_pInUpstreamBuf < (COM_DATAUPSTREAM_BUFFER_SIZE - 1))
            {
                COM_USB_pInUpstreamBuf = COM_USB_pInUpstreamBuf + 1;
            }
            else
            {
                COM_USB_pInUpstreamBuf = 0;
            }
        }
    }
    /*Error event interrupt.*/
    if((COM_URT_IRQHandlerFlag & URT_IT_ERR))
    {
        URT_ClearITFlag(COM_URT,URT_IT_ERR);
        
        if((COM_URT_IRQHandlerFlag & URT_IT_PE))
        {
            URT_ClearITFlag(COM_URT,URT_IT_PE);
            
            COM_USB_ErrorCode = COM_USB_ErrorCode | URT_IT_PE;
        }
        if((COM_URT_IRQHandlerFlag & URT_IT_FE))
        {
            URT_ClearITFlag(COM_URT,URT_IT_FE);
            
            COM_USB_ErrorCode = COM_USB_ErrorCode | URT_IT_FE;
        }
        if((COM_URT_IRQHandlerFlag & URT_IT_ROVR))
        {
            URT_ClearITFlag(COM_URT,URT_IT_ROVR);
            
            COM_USB_ErrorCode = COM_USB_ErrorCode | URT_IT_ROVR;
        }
        // Clear Receive Hold Flag. (If no clearing the flag RX can't receive new data.
        URT_ClearRxHoldFlag(COM_URT);
        
    }
    /*Transmit interrupt.*/
    if((COM_URT_IRQHandlerFlag & URT_IT_TX))
    {
        COM_URT_IRQHandlerTmp = 0;
        
        while( COM_URT_pTxTransferCount!=0 && COM_URT_IRQHandlerTmp < 4)
        {
            COM_URT_IRQHandlerTXBuf.B[COM_URT_IRQHandlerTmp] = *COM_URT_TxBuf;
            
            COM_URT_pTxTransferCount = COM_URT_pTxTransferCount - 1;
            COM_URT_TxBuf            = COM_URT_TxBuf + 1;
            COM_URT_IRQHandlerTmp    = COM_URT_IRQHandlerTmp + 1;
        }
        
        URT_SetTXData( COM_URT, (uint8_t)COM_URT_IRQHandlerTmp, COM_URT_IRQHandlerTXBuf.W);

        if(COM_URT_pTxTransferCount==0)
        {
            URT_IT_Config(COM_URT,URT_IT_TX,DISABLE);
            URT_IT_Config(COM_URT,URT_IT_TC,ENABLE);
        }
    }
    if((COM_URT_IRQHandlerFlag & URT_IT_TC))
    {
        URT_IT_Config(COM_URT,URT_IT_TC,DISABLE);
        /*USB RX start receiving next transfer.*/
        USB_SetEndpointStatus( COM_DATADOWNSTREAM_EP ,EP_RX_VALID);
    }
}
/**
 *******************************************************************************
 * @brief    UART Error Event Function.
 * @details 
 * @param    	
 * @return         	
 *******************************************************************************
 */ 
static void API_USBD_COM_SetUARTState(void)
{
    if( COM.Status !=0)
    {
        if(COM.COM_USB_StatusUpstream_Busy==0)
        {
            COM.COM_Status_EP_SRAM[8] = COM.Status ;
            
            COM.COM_USB_StatusUpstream_Busy = 1;
            USB_SetEndpointTXData( COM_STATUS_EP, &COM.COM_Status_EP_SRAM[0] , 10);
            
            COM.Status = 0;
        }
    }
    if( COM_USB_ErrorCode == 0 && COM.COM_USB_DataUpstream_OverrunFlag==0)
    {
        return;
    }
    /*
    //-------------------------------------------
    //D0 (bRxCarrier) 
    //    - State of receiver carrier detection mechanism of device .
    //      This signal corresponds to V.24 signal 109 and RS-232 signal DCD.
    
    COM.Status |= PSTN_URT_bRxCarrier;
    
    //--------------------------------------------
    //D1 (bTxCarrier)
    //    - State of transmission carrier. 
    //      This signal corresponds to V.24 signal 106 and RS-232 signal DSR.
    COM.Status |= PSTN_URT_bTxCarrier;
    
    //--------------------------------------------
    //D2 (bBreak)
    //    - State of break detect mechanism of the device.
    COM.Status |= PSTN_URT_bBreak;
    
    //--------------------------------------------
    //D3 (bRingSignal)
    //    - State of ring signal detection of the device.
    COM.Status |= PSTN_URT_bRingSignal;
    
    */
    //--------------------------------------------
    //D4 (bFraming)
    //    - A framing error has occurred.
    if( COM_USB_ErrorCode & URT_IT_FE)
    {
        COM_USB_ErrorCode = COM_USB_ErrorCode & (~URT_IT_FE);
        
        //COM.Status |= PSTN_URT_bFraming;    
        //To do......
    }
    //--------------------------------------------
    //D5 (bParity)
    //    - A parity error has occurred.
    if( COM_USB_ErrorCode & URT_IT_PE)
    {
        COM_USB_ErrorCode = COM_USB_ErrorCode & (~URT_IT_PE);
        
        //COM.Status |= PSTN_URT_bParity;    
        //To do......
    }
    //---------------------------------------------
    //D6 (bOverRun)
    //   - Received data has been discarded due to overrun in the device.
    if( COM.COM_USB_DataUpstream_OverrunFlag == 1 )
    {
        COM.COM_USB_DataUpstream_OverrunFlag = 0;
        
        //COM.Status |= PSTN_URT_bOverRun;
        //To do......
    }
    if( COM_USB_ErrorCode & URT_IT_ROVR)
    {
        COM_USB_ErrorCode = COM_USB_ErrorCode & (~URT_IT_ROVR);
        
        //COM.Status |= PSTN_URT_bOverRun;
        //To do......
    }
    /*
    //---------------------------------------------
    //D7 (Reserved (future use)
    */
    // To do......
    
}

#endif

///@}


