


/**
 ******************************************************************************
 *
 * @file        MG32x02z_SmartCard_API.c
 *
 * @brief       The code is Smart Card C file.
 *
 * @par         Project
 *              Smart Card
 * @version     V1.00
 * @date        2023/01/05
 * @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_Common.h"
#include "MG32x02z_SmartCard_API.h"


/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/

/*! @enum   SmartCard_DelayUnit 
    @brief  Delay function unit.
*/
typedef enum
{
    SmartCard_CLK_f = 1,
    SmartCard_etu   = 0,
}SmartCard_DelayUnit;


/* Private define ------------------------------------------------------------*/
/*GPIO & EXIC Define*/
//IO pin define
#define SmartCard_IO_PINX               PINC(8)           
#define SmartCard_IO_AFS                4
#define SmartCard_IO                    PC8                                  

//CLK pin define
#define SmartCard_CLK_PINX              PINC(3)
#define SmartCard_CLK_AFS               4
                
//RST pin define                
#define SmartCard_RST_PINX              PINC(1)
#define SmartCard_RST_AFS               0

//VCC control pin define
#define SmartCard_VCC_PINX              PINB(14)   
#define SmartCard_VCC_AFS               0
                        
//CDET pin define                        
#define SmartCard_CDET_PINX             PINC(12)
#define SmartCard_CDET_IOM              IOMC
#define SmartCard_CDET_AFS              0
#define SmartCard_CDET_EXIC_TRGS        EXIC_TRGS_PIN12
#define SmartCard_CDET_EXIC_PORT        EXIC_PC
#define SmartCard_CDET_EXIC_PIN         EXIC_PX_PIN12
#define SmartCard_CDET_EXIC_IT          EXIC_PC_IT
#define SmartCard_CDET_EXIC_IRQ         EXINT2_IRQn   
#define SmartCard_CDET_EXIC_IRQHandler  EXINT2_IRQHandler
#define SmartCard_GetCDET_IDSource()    __DRV_EXIC_GET_ID5_SOURCE()                                    
             
//LED pin define
#define SmartCard_LED_PINX              PINB(8)
#define SmartCard_LED_AFS               0


/*URT Define*/                    
#define SmartCard_URTx                  URT1
                                  
#define SmartCard_URTx_IRQn             URT123_IRQn
#define SmartCard_URTx_IRQHandler       URT123_IRQHandler
                                  

/*TM Define*/
#define URTx_CLK_TM                     TM00
                                  
#define SmartCard_DELAY_TM              TM10
#define SmartCard_DELAY_TM_IRQ          TM10_IRQn
                                  
#define SmartCard_DELAY_COMPENSATE      38                                                                  
                                  
/*Macro Define*/                  
#define __SmartCard_GetCDETStatus()     PC12
                                  
                                                          
#define __SmartCard_VCC_OFF()           PB14 = 1
#define __SmartCard_VCC_ON()            PB14 = 0
                                  
#define __SmartCard_RST_SetLow()        PC1 = 0
#define __SmartCard_RST_SetHigh()       PC1 = 1

#define __SmartCard_LED_ON()            PB8 = 0
#define __SmartCard_LED_OFF()           PB8 = 1


/*Smart Card Control Status Define*/
#define SmartCard_STATUS_MAIN_MASK      0xFFFF0000
#define SmartCard_STATUS_SUB_MASK       0x0000FFFF

// MAIN Status of SmartCard_iStatus
#define SmartCard_STATUS_DISABLE        0x00000000
#define SmartCard_STATUS_ACTIVATION_VCC 0x00010000
#define SmartCard_STATUS_COLDRESET      0x00020000
#define SmartCard_STATUS_WARMRESET      0x00040000
#define SmartCard_STATUS_WAITATR        0x00080000
#define SmartCard_STATUS_ATR            0x00100000
#define SmartCard_STATUS_DEACTIVATE     0x00200000
#define SmartCard_STATUS_PPSREQUEST     0x00400000
#define SmartCard_STATUS_PPSRESPONSE    0x00800000
#define SmartCard_STATUS_READY          0x80000000
#define SmartCard_STATUS_TXBUSY         0x10000000
#define SmartCard_STATUS_RXBUSY         0x20000000


// SUB status of SmartCard_iStatus ( When MAIN Status of SmartCard_iStatus = SmartCard_STATUS_ATR)   
#define SmartCard_STATUS_ATR_T0         0x00000001
#define SmartCard_STATUS_ATR_INTERFACE  0x00000002
#define SmartCard_STATUS_ATR_HISTORICAL 0x00000004
#define SmartCard_STATUS_ATR_TCK        0x00000008

// SUB status of SmartCard_iStatus ( When MAIN Status of SmartCard_iStatus = SmartCard_STATUS_PPSRESPONSE) 
#define SmartCard_STATUS_PPSS           0x00000001
#define SmartCard_STATUS_PPS0           0x00000002
#define SmartCard_STATUS_PPS1           0x00000010
#define SmartCard_STATUS_PPS2           0x00000020
#define SmartCard_STATUS_PPS3           0x00000040
#define SmartCard_STATUS_PCK            0x00000004

// TS convention patterns.
#define SmartCard_TS_INVERSE_CONVENTION 0
#define SmartCard_TS_DIRECT_CONVENTION  1

#define SmartCard_TS_INVERSE_PATTERN    0x3F      
#define SmartCard_TS_DIRECT_PATTERN     0x3B        


// TA2 mask
#define SmartCard_ATR_TA2_CHANGE_MASK   0x80
#define SmartCard_ATR_TA2_FD_MASK       0x10
#define SmartCard_ATR_TA2_T_MASK        0x0F

// ATR number of historical characters mask
#define SmartCard_ATR_K_MASK            0x0F


// ATR Default Parameter
#define SmartCard_ETU_Fd                1
#define SmartCard_ETU_Dd                1
#define SmartCard_WI_Deault             10
#define SmartCard_N_Default             0


// PPS related
#define SmartCard_PPS0_T                0x0F
#define SmartCard_PPS0_PPS1             0x10
#define SmartCard_PPS0_PPS2             0x20
#define SmartCard_PPS0_PPS3             0x40
#define SmartCard_PPS0_RFU              0x80

// WT
#define __API_SmartCard_WTStart(__SmartCard_WT__)  API_SmartCard_Delay((__SmartCard_WT__),SmartCard_etu)
#define __API_SmartCard_WTReStart()                API_SmartCard_TriggerDelay()

// ATR the others define
#define SmartCard_ATR_T_MASK            0x0F
#define SmartCard_ATR_T_SUPPORT         0x8003     /* The project whether support the T or not.
                                                If Bit0  = 1 support (T = 0) , = 0 no support (T = 0).
                                                If Bit1  = 1 support (T = 1) , = 0 no support (T = 1).
                                                If Bit2  = 1 support (T = 2) , = 0 no support (T = 2).
                                                ...
                                                If Bit15 = 1 support (T = 15), = 0 no support (T = 15).
                                              */
#define SmartCard_ATR_T0_MASK           0x0001
#define SmartCard_ATR_T1_MASK           0x0002
#define SmartCard_ATR_T2_MASK           0x0004
#define SmartCard_ATR_T3_MASK           0x0008
#define SmartCard_ATR_T4_MASK           0x0010
#define SmartCard_ATR_T5_MASK           0x0020
#define SmartCard_ATR_T6_MASK           0x0040
#define SmartCard_ATR_T7_MASK           0x0080
#define SmartCard_ATR_T8_MASK           0x0100
#define SmartCard_ATR_T9_MASK           0x0200
#define SmartCard_ATR_T10_MASK          0x0400
#define SmartCard_ATR_T11_MASK          0x0800
#define SmartCard_ATR_T12_MASK          0x1000
#define SmartCard_ATR_T13_MASK          0x2000
#define SmartCard_ATR_T14_MASK          0x4000
#define SmartCard_ATR_T15_MASK          0x8000


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

SmartCard_CTRTypeDef SmartCard_CTR;

static uint32_t SmartCard_iStatus;
static uint8_t  SmartCard_Retry;

static __IO uint16_t SmartCard_DelayTmp;
static __IO uint16_t SmartCard_DelayCmp;

static uint8_t  SmartCard_Tmp;
static uint8_t  SmartCard_TmpCmp;


static const uint8_t SmartCard_ATR_Fi_RLRTable[16] = { 23, 23, 35, 47, 71, 95,119, 23, 23, 63, 95,127,191,255, 23, 23};
static const uint8_t SmartCard_ATR_Fi_OSTable[16]  = { 30, 30, 30, 30, 30, 30, 30, 30, 30, 15, 15, 15, 15, 15, 30, 30};
static const uint8_t SmartCard_ATR_Di_PSRTable[16] = {  1,  1,  3,  7, 15, 31, 63,  1, 23,  1,  1,  1,  1,  1,  1,  1};
static const uint8_t SmartCard_ATR_f_TM00Table[16] = {  5,  4,  3,  2,  2,  2,  2,  4,  4,  4,  4,  2,  2,  2,  4,  4};

static uint16_t SmartCard_Delayetu_TMReload;
static uint16_t SmartCard_DelayCLKf_TMReload;


/* Private function prototypes -----------------------------------------------*/
#if 1
//IRQHandler function
void SmartCard_CDET_EXIC_IRQHandler(void);
void TM10_IRQHandler(void);
void SmartCard_URTx_IRQHandler(void);

//Static function
static void API_SmartCard_Delay( uint32_t SmartCard_Delay, SmartCard_DelayUnit SmartCard_dUnit);
static void API_SmartCard_TriggerDelay(void);

static void API_SmartCard_StopCLK(void);
static void API_SmartCard_StartCLK(void);
static void API_SmartCard_IO_Cmd( FunctionalState SmartCard_IO_Cmd);
static void API_SmartCard_DisableWT(void);
static void API_SmartCard_SetConvention( uint8_t ConventionType);
static void API_SmartCard_SetETU( uint8_t CLKRate_Conversion , uint8_t BR_Adjustment);

static void API_SmartCard_Activation(void);
static void API_SmartCard_Deactivate(void);
static void API_SmartCard_WarmReset(void);

static void API_SmartCard_ReceiveATR(void);
static uint32_t API_SmartCard_DecodeATR(void);

static void API_SmartCard_TriggerPPSRequest(uint8_t PPS_T , uint8_t PPS_F , uint8_t PPS_D );
static void API_SmartCard_ReceivePPSResponse(void);
static uint8_t API_SmartCard_CheckPPSResponse(void);

static void API_SmartCard_Receive_IRQHandler(void);
#endif

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/**
 * @name IRQ Handler function
 *   		
 */ 
///@{
/**
 *******************************************************************************
 * @brief	   Detected card IRQ handler.
 * @details     
 * @return      
 * @exception  No
 * @note       Because        
 *******************************************************************************
 */
void SmartCard_CDET_EXIC_IRQHandler(void)
{
    uint32_t EXINTx_IRQHandlerTmp;
    
    if(SmartCard_GetCDET_IDSource() ==1)
    {
        EXINTx_IRQHandlerTmp = EXIC_GetPxAllTriggerEventFlagStatus(SmartCard_CDET_EXIC_PORT);
        
        if( EXINTx_IRQHandlerTmp & SmartCard_CDET_EXIC_PIN)
        {
            /* Card Insert Detected*/
            if(__SmartCard_GetCDETStatus() == 0)
            {
                __SmartCard_LED_ON();
                
                SmartCard_CTR.Status.MBIT.Inserted = 1;
                
                GPIO_PinInverse_Cmd(SmartCard_CDET_PINX,ENABLE);                                  // Change EXIC mode to H level trigger.
                EXIC_ClearPxTriggerEventFlag(SmartCard_CDET_EXIC_PORT,SmartCard_CDET_EXIC_PIN);   // Clear EXIC event flag.
                // Callback function
                API_SmartCard_CardInsertCallback();
                // Start Activation. 
                API_SmartCard_Activation();
                return;    
            }
            /* Card Remove Detected*/
            else if(SmartCard_CTR.Status.W != SmartCard_STATUS_INSERTED)
            {
                __SmartCard_LED_OFF();
                
                GPIO_PinInverse_Cmd(SmartCard_CDET_PINX,DISABLE);                                 // Change EXIC mode to L level trigger.
                EXIC_ClearPxTriggerEventFlag(SmartCard_CDET_EXIC_PORT,SmartCard_CDET_EXIC_PIN);   // Clear EXIC event flag.
                // Start Deactivate
                API_SmartCard_Deactivate();
                
                // Callback function
                API_SmartCard_CardRemoveCallback();
                
            }
            SmartCard_CTR.Status.W = 0;
            
        }
    }
}
/**
 *******************************************************************************
 * @brief	   WT IRQ handler.
 * @details     
 * @return      
 * @exception  No
 * @note       Because        
 *******************************************************************************
 */
void TM10_IRQHandler(void)
{
    uint32_t TM10_IRQHandlerTmp;

    TM_ClearFlag( SmartCard_DELAY_TM, (TMx_TOF | TMx_TOF2));

    SmartCard_DelayTmp = SmartCard_DelayTmp + 1;
    
    if( SmartCard_DelayTmp < SmartCard_DelayCmp)
    {
        return;
    }

    TM_Timer_Cmd( SmartCard_DELAY_TM, DISABLE);
    
    TM10_IRQHandlerTmp = ( SmartCard_iStatus & SmartCard_STATUS_MAIN_MASK);
    
    switch(TM10_IRQHandlerTmp)
    {
        case SmartCard_STATUS_COLDRESET:
        case SmartCard_STATUS_WARMRESET:            
                                                                //RST end
                                                                __SmartCard_RST_SetHigh();
                                                                SmartCard_iStatus = SmartCard_STATUS_WAITATR;
                                                                
                                                                API_SmartCard_Delay(39000,SmartCard_CLK_f);
                                                                break;
        case SmartCard_STATUS_ATR:                                
                                                                SmartCard_CTR.Status.MBIT.ATRError = 1;
                                                                API_SmartCard_DisableWT();
                                                                break;
        case SmartCard_STATUS_PPSRESPONSE:                      
                                                                SmartCard_CTR.Status.MBIT.PPSError = 1;
                                                                API_SmartCard_DisableWT();
                                                                break;
        case (SmartCard_STATUS_READY | SmartCard_STATUS_RXBUSY):
                                                                SmartCard_CTR.Status.MBIT.WTError = 1;
                                                                break;
        case SmartCard_STATUS_ACTIVATION_VCC:
                                                                // I/O in the interface device shall be put in reception mode.
                                                                API_SmartCard_IO_Cmd( ENABLE);
                                                                
                                                                // CLK shall be provided with a clock signal.
                                                                API_SmartCard_StartCLK();
                                                                
                                                                //Set Parameter 
                                                                SmartCard_iStatus  = SmartCard_STATUS_COLDRESET;
                                                                SmartCard_Retry    = 3;
                                                                SmartCard_DelayCmp = 1;
                                                                // Delay (400 / f) to cold reset.
                                                                API_SmartCard_Delay(400,SmartCard_CLK_f); 
                                                                break;
        case SmartCard_STATUS_WAITATR:                    
        default:                                    
                                                                SmartCard_CTR.Status.MBIT.ATRTimeout = 1;
                                                                API_SmartCard_ErrorCallback();
                                                                API_SmartCard_Deactivate();
                                                                break;
    }
}

/**
 *******************************************************************************
 * @brief	   SmartCard of URTx IRQ handler.
 * @details     
 * @return      
 * @exception  No
 * @note       Because        
 *******************************************************************************
 */
void SmartCard_URTx_IRQHandler(void)
{
    uint32_t SmartCard_URTx_IRQHandlerTmp;
    uint32_t SmartCard_URTx_IRQHandlerFlag;

    SmartCard_URTx_IRQHandlerFlag = URT_GetITAllFlagStatus(SmartCard_URTx) & URT_GetITStatus(SmartCard_URTx);
    SmartCard_URTx_IRQHandlerTmp  = ( SmartCard_iStatus & SmartCard_STATUS_MAIN_MASK);
    

    /*Error interrupt handler*/
    if(SmartCard_URTx_IRQHandlerFlag & URT_IT_ERR)
    {
        if(SmartCard_URTx_IRQHandlerFlag & URT_IT_PE) 
        {
            SmartCard_CTR.Status.MBIT.ParityError = 1;
        }

        URT_ClearITFlag( SmartCard_URTx , SmartCard_URTx_IRQHandlerFlag);
        return;
    }
    /*Receive interrupt handler*/
    if(SmartCard_URTx_IRQHandlerFlag & URT_IT_RX)
    {
        /*User Receive data*/
        if((SmartCard_URTx_IRQHandlerTmp & (SmartCard_STATUS_READY | SmartCard_STATUS_RXBUSY))==( SmartCard_STATUS_READY | SmartCard_STATUS_RXBUSY ))
        {
            API_SmartCard_Receive_IRQHandler();
        }
        /*Receive TS*/
        else if(SmartCard_URTx_IRQHandlerTmp==SmartCard_STATUS_WAITATR)
        {
            SmartCard_CTR.ATR.TS = SmartCard_URTx->RDAT.B[0];

            if(SmartCard_CTR.ATR.TS == SmartCard_TS_DIRECT_PATTERN)
            {
                API_SmartCard_SetConvention(SmartCard_TS_DIRECT_CONVENTION);
            }
            else
            {
                API_SmartCard_SetConvention(SmartCard_TS_INVERSE_CONVENTION);
            }
            URT_ClearITFlag(SmartCard_URTx,URT_IT_PE);
            URT_IT_Config( SmartCard_URTx, URT_IT_PE , ENABLE);
            
            //Parameter initial
            SmartCard_iStatus    = (SmartCard_STATUS_ATR | (SmartCard_STATUS_ATR_T0 | SmartCard_STATUS_ATR_INTERFACE | SmartCard_STATUS_ATR_HISTORICAL));
            
            __API_SmartCard_WTStart(SmartCard_CTR.SPITByte.WT);
        }
        /*Receive Answer to Reset (ATR)*/
        else if(SmartCard_URTx_IRQHandlerTmp & SmartCard_STATUS_ATR)
        {
            __API_SmartCard_WTReStart();
            
            API_SmartCard_ReceiveATR();
        }
        /*Receive PPS respons*/
        else if(SmartCard_URTx_IRQHandlerTmp & SmartCard_STATUS_PPSRESPONSE)
        {
            __API_SmartCard_WTReStart();
            
            API_SmartCard_ReceivePPSResponse();
        }
        /*UnKnow Status*/
        else
        {
            URT_ClearITFlag(SmartCard_URTx,URT_IT_RX);
            
            //To do.....
        }
    }
    /*Transmit complete interrupt handler*/
    if(SmartCard_URTx_IRQHandlerFlag & URT_IT_TC)
    {
        URT_ClearITFlag(SmartCard_URTx,URT_IT_TC);
        URT_IT_Config( SmartCard_URTx, URT_IT_TC,DISABLE);
        
        if(SmartCard_iStatus & SmartCard_STATUS_PPSREQUEST)
        {
            SmartCard_iStatus = SmartCard_iStatus & ((uint32_t)(~SmartCard_STATUS_PPSREQUEST));  
            __API_SmartCard_WTReStart();
            
        }
        else if((SmartCard_URTx_IRQHandlerTmp & (SmartCard_STATUS_READY | SmartCard_STATUS_TXBUSY))==( SmartCard_STATUS_READY | SmartCard_STATUS_TXBUSY ))
        {
            SmartCard_iStatus &= ((uint32_t)(~SmartCard_STATUS_TXBUSY));
            //User transmit complete.
            API_SmartCard_TxCpltCallback();
        }
        else 
        {
            //To do...
        }
    }
}
///@}

/**
 *******************************************************************************
 * @brief	    Default initial ATR parameter of SmartCard. 
 * @details     
 * @param[in]   CLK output whether enable or not.
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
void API_SmartCard_ATR_DeInit(FunctionalState CLK_fDefault)
{
    /*ATR parameter Initial*/
    SmartCard_CTR.ATR.TS               = 0;
    SmartCard_CTR.ATR.T0               = 0;
    SmartCard_CTR.ATR.InterfaceLength  = 0;
    SmartCard_CTR.ATR.HistoricalLength = 0;
    SmartCard_CTR.ATR.TCK_present      = 0;
    
    /*GT & WT default*/
    SmartCard_CTR.GITByte.N            = SmartCard_N_Default;      // Extra guard time integer(N) =  default.
    SmartCard_CTR.GITByte.Fi           = SmartCard_ETU_Fd;         // FI = default
    SmartCard_CTR.GITByte.Di           = SmartCard_ETU_Dd;         // DI = default 
    SmartCard_CTR.SPITByte.WT          = 9600;
    URT_TXGuardTime_Select(SmartCard_URTx, SmartCard_CTR.GITByte.N);
    
    /*Set Elementary time unit to default*/
    if( CLK_fDefault == ENABLE)
    {
        API_SmartCard_StopCLK();
        API_SmartCard_SetETU(SmartCard_ETU_Fd,SmartCard_ETU_Dd);
    }
    
}
/**
 *******************************************************************************
 * @brief	    SmartCard initial.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
void API_SmartCard_Init(void)
{
    URT_RXParityError_TypeDef   SmartCard_URTx_RXPE;
    EXIC_TRGSTypeDef            SmartCard_URTx_EXIC_TRGS;

    /*============Parameter Initial================*/
    SmartCard_CTR.Status.W = 0;
    SmartCard_Retry        = 3;
    
    /*=================GPIO Init=================*/
    //Set pin initial status.
    API_SmartCard_StopCLK();
    __SmartCard_RST_SetLow(); 
    __SmartCard_VCC_OFF();
    SmartCard_IO = 0;
    
    __SmartCard_LED_OFF();
    
    //Set Pin mode.
    API_GPIO_PinConfig(SmartCard_IO_PINX,Data_DIR_OUT_OD_RU,0);
    API_GPIO_PinConfig(SmartCard_CLK_PINX,Data_DIR_OUT_PP,SmartCard_CLK_AFS);
    API_GPIO_PinConfig(SmartCard_RST_PINX,Data_DIR_OUT_PP,SmartCard_RST_AFS);
    API_GPIO_PinConfig(SmartCard_VCC_PINX,Data_DIR_OUT_PP,SmartCard_VCC_AFS);
    API_GPIO_PinConfig(SmartCard_LED_PINX,Data_DIR_OUT_PP,SmartCard_LED_AFS);

    GPIO_PortFilterClockSource_Select(SmartCard_CDET_IOM,GPIO_FT_CLK_ILRCO);
    API_GPIO_PinConfig(SmartCard_CDET_PINX,Data_DIR_IN_RU,SmartCard_CDET_AFS);
    GPIO_PinInFilterDivider_Select(SmartCard_CDET_PINX,PINX_FilterDivider_16);
    
    /*=================URT Initial=================*/

    /*Set ETU (Elementary time unit)*/
    API_SmartCard_SetETU(SmartCard_ETU_Fd,SmartCard_ETU_Dd);
                                                                
    // Set TX / RX clock source.                                                          
    URT_TXClockSource_Select(SmartCard_URTx, URT_TXClock_Internal);	                          //URT_TX use BaudRateGenerator
    URT_RXClockSource_Select(SmartCard_URTx, URT_RXClock_Internal);	                          //URT_RX use BaudRateGenerator
    
    // Set TX / RX data oversampling mode.               
    URT_RXOverSamplingMode_Select(SmartCard_URTx, URT_RXSMP_3TIME);
                             
    /*Set convention decoded type */
    API_SmartCard_SetConvention(SmartCard_TS_DIRECT_CONVENTION);
    
    /*Set Mode*/
    //Set SC 1 line mode
    URT_Mode_Select(SmartCard_URTx, URT_URT_mode);
    URT_DataLine_Select(SmartCard_URTx, URT_DataLine_1);
    URT_HalfDuplexMode_Cmd(SmartCard_URTx, ENABLE);
    
    //Set RX error retry
    SmartCard_URTx_RXPE.URT_RXPERetryMode = URT_RXPERetry_Disable;
    SmartCard_URTx_RXPE.URT_RXErrorSignal = URT_RXErrorSignal_1BIT;
    SmartCard_URTx_RXPE.URT_RXPERetryTime = URT_RXPERetry_3;
    URT_RXParityError_Config( SmartCard_URTx , &SmartCard_URTx_RXPE);
    
    //Set TX error retry
    URT_TXErrorDetectMode_Select( SmartCard_URTx,URT_TXErrorDetect_ErrorSignal);
    URT_TXErrorResendTime_Select( SmartCard_URTx, URT_TXErrorResend_3);
    
    //Set Gaud-Time 
    URT_TXGuardTime_Select(SmartCard_URTx, 0);                // Set Gaud-Time.
    
    //Set Wait time ( Use idle timeout & the idle timeout only set 1 ~ 65535 bit)
    URT_TimeoutMode_Select(SmartCard_URTx,URT_TMOMDS_URT);
    URT_TimeoutTimerClockSource_Select(SmartCard_URTx,URT_TMOCLK_BitTime);
    URT_IdleTimeoutDetect_Config(SmartCard_URTx,DISABLE,(SmartCard_WI_Deault*960*SmartCard_ETU_Dd));
    URT_TimeroutTimer_Cmd(SmartCard_URTx,ENABLE);
    
    
    //Set CLK output ( Use URTx_CLK of URT module)
    URT_CLKSignal_Cmd( SmartCard_URTx , ENABLE);              // URT_CLK output disable.
    URT_CLKSignalSource_Select( SmartCard_URTx, URT_CK_SC);   // URT_CLK source from CK_URTx_SC of URT module.
    URT_CtrlCLKSignalStatus_SW( SmartCard_URTx, CLR);         // URT_CLK default status is low.
    
    /*Set Interrupt */
    URT_IT_Config( SmartCard_URTx, (URT_IT_TC | URT_IT_TX | URT_IT_RX | URT_IT_PE | URT_IT_TXE | URT_IT_IDTMO), DISABLE);
    URT_IT_Config( SmartCard_URTx, (URT_IT_ERR), ENABLE);
    URT_ITEA_Cmd(SmartCard_URTx,ENABLE);
    NVIC_EnableIRQ(SmartCard_URTx_IRQn);
    
    
    /*Default Buffer Status*/
    // Set Buffer control.
    URT_RXShadowBufferThreshold_Select(SmartCard_URTx, URT_RXTH_1BYTE);
    URT_IdlehandleMode_Select(SmartCard_URTx, URT_IDLEMode_No);
    URT_ClearITFlag(SmartCard_URTx,URT_IT_Mask);
    URT_ClearTXData(SmartCard_URTx);
    URT_ClearRXData(SmartCard_URTx);
    
    /*URT Initial Completing*/
    URT_TX_Cmd(SmartCard_URTx, ENABLE);	                         
    URT_RX_Cmd(SmartCard_URTx, DISABLE);                // RX default disable.
    
    
    URT_Cmd(SmartCard_URTx, ENABLE);

    /*TM Initial (For Delay)*/
    //Set timer interrupt
    TM_ClearFlag( SmartCard_DELAY_TM, (TMx_TOF | TMx_TOF2));
    TM_IT_Config(SmartCard_DELAY_TM, TMx_TIE_IE,ENABLE);
    TM_ITEA_Cmd(SmartCard_DELAY_TM,ENABLE);
    
    NVIC_EnableIRQ(SmartCard_DELAY_TM_IRQ);
    
    /*EXIC Init*/
    GPIO_PinInverse_Cmd(SmartCard_CDET_PINX,DISABLE);
    
    SmartCard_URTx_EXIC_TRGS.EXIC_Pin       = SmartCard_CDET_EXIC_TRGS;
    SmartCard_URTx_EXIC_TRGS.EXIC_TRGS_Mode = Level;                                         
    EXIC_PxTriggerMode_Select(SmartCard_CDET_EXIC_PORT,&SmartCard_URTx_EXIC_TRGS);                            
    
    EXIC_PxTriggerOrMask_Select(SmartCard_CDET_EXIC_PORT  , SmartCard_CDET_EXIC_PIN);
    EXIC_ClearPxTriggerEventFlag(SmartCard_CDET_EXIC_PORT, SmartCard_CDET_EXIC_PIN ); 
    EXIC_PxTriggerITEA_Cmd(SmartCard_CDET_EXIC_IT , ENABLE); 
    NVIC_EnableIRQ(SmartCard_CDET_EXIC_IRQ);
}
/**
 *******************************************************************************
 * @brief	    Trigger transmitting  data (by DMA).
 * @details     
 * @param[in]   pBuf  : data source pointer.
 * @param[in]   Length: transmit data size ( max 65535 bytes)
 * @return      Trigger transmitting  whether success or not.     
 * @exception   No
 * @note        
 *******************************************************************************
 */
uint8_t API_SmartCard_Transmit( uint8_t *pBuf, uint16_t Length)
{
    if((SmartCard_iStatus & SmartCard_STATUS_MAIN_MASK)!=SmartCard_STATUS_READY)
    {
        return(SmartCard_FAILURE);
    }
    
    SmartCard_iStatus |= SmartCard_STATUS_TXBUSY;
    
    DMA_ClearFlag(DMA,SmartCard_TX_DMA_FLAG); 
    DMA_SetTransferDataNumber(SmartCard_TX_DMA_Channel,Length);           // Set DMA data size.
    DMA_SetSourceAddress(SmartCard_TX_DMA_Channel,pBuf);                  // Set DMA source address
    
    URT_TXDMA_Cmd(SmartCard_URTx,ENABLE);                                 // Enable URT TX DMA.
    URT_ClearITFlag( SmartCard_URTx, URT_IT_TC);
    URT_IT_Config( SmartCard_URTx, URT_IT_TC,ENABLE);
    
    DMA_StartRequest(SmartCard_TX_DMA_Channel);                           // Trigger DMA module channel.
    
    return(SmartCard_SUCCESS);
}
/**
 *******************************************************************************
 * @brief	    Trigger receiving data.
 * @details     
 * @param[in]   pBuf   : Receive data store destination
 * @param[in]   Length : In the time receive data length.
 * @return      Trigger receiving whether success or not.      
 * @exception   No
 * @note        
 *******************************************************************************
 */
uint8_t API_SmartCard_Receive(uint8_t *pBuf, uint16_t Length)
{
    if((SmartCard_iStatus & SmartCard_STATUS_MAIN_MASK)!=SmartCard_STATUS_READY)
    {
        return(SmartCard_FAILURE);
    }
    
    SmartCard_iStatus |= SmartCard_STATUS_RXBUSY;
    
    SmartCard_CTR.RxBuf    = pBuf;
    SmartCard_CTR.RXLength = Length; 
    
    __API_SmartCard_WTReStart();
    
    return(SmartCard_SUCCESS); 
}
/**
 *******************************************************************************
 * @brief	    SmartCard main funciton.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
void API_SmartCard_main(void)
{
    SmartCard_CTRStatus_TypeDef SmartCard_mainTmp;
    

    SmartCard_mainTmp.W = SmartCard_CTR.Status.W;
    
    /*
    *. No card insert.
    or
    *. Card aready insert but ATR not yet completed.
    */
    if( SmartCard_mainTmp.W == 0 || SmartCard_mainTmp.W == SmartCard_STATUS_INSERTED)
    {
        return;
    }
    
    /*Error handler*/
    if((SmartCard_mainTmp.W & SmartCard_STATUS_ERROR) !=0)
    {
        API_SmartCard_ErrorCallback();
        
        /*Receive error signal.*/
        if( SmartCard_mainTmp.MBIT.ParityError == 1)
        {
            // To do...
            
            API_SmartCard_Deactivate();
            return;
        }
        /*Answer to Reset data error.*/
        else if( SmartCard_mainTmp.MBIT.ATRError == 1)
        {
            // To do...
            
            API_SmartCard_Deactivate();
            return;
        }
        /*PPS request error*/
        else if( SmartCard_mainTmp.MBIT.PPSError == 1)
        {
            // To do...
            
            API_SmartCard_Deactivate();
            return;
        }
        /*User Receive timeout.*/
        else if(SmartCard_CTR.Status.MBIT.WTError==1)
        {
            // To do....
        }
        return;
    }
    /*Normal handler*/
    else if( SmartCard_mainTmp.MBIT.TransmissionActive == 1)
    {
        // User transmission.
        API_SmartCard_UserTransmission();
        return;    
    }
    else if( SmartCard_mainTmp.MBIT.Transmission_Init == 1)
    {
        /* Process transmission protocol and transmission parameter.*/
        // Set ETU.
        API_SmartCard_SetETU(SmartCard_CTR.GITByte.Fi,SmartCard_CTR.GITByte.Di);
        API_SmartCard_StartCLK();

        // Set parameter
        SmartCard_iStatus = SmartCard_STATUS_READY;
        SmartCard_CTR.Status.MBIT.TransmissionActive = 1;
        
        // Form SmartCard_CTR.GITByte.T to get transmisson protocol.
        API_SmartCard_ATRCpltCallback();
    }
    /*PPS exchange*/
    else if(SmartCard_CTR.Status.MBIT.PPSExchange == 1)
    {
        // PPS exchange not yet complete.
        if( SmartCard_CTR.PPS.Status == SmartCard_PPS_STATUS_BUSY)
        {
            return;
        }
        if(SmartCard_CTR.PPS.Status!=SmartCard_PPS_STATUS_RESPONSE)
        {
            SmartCard_mainTmp.MBIT.PPSError = 1;
        }
        if(API_SmartCard_CheckPPSResponse()==SmartCard_SUCCESS)
        {
            SmartCard_CTR.Status.MBIT.TransmissionActive = 1;
        }
        else
        {
            SmartCard_mainTmp.MBIT.PPSError = 1;
        }
    }
    /*ATR Decode*/
    else if( SmartCard_mainTmp.MBIT.ATRReceiveComplete == 1)
    {
        //Decode ATR
        if( API_SmartCard_DecodeATR()!= SmartCard_SUCCESS)
        {
            if(SmartCard_Retry!=0)
            {
                SmartCard_Retry = SmartCard_Retry - 1;
                SmartCard_CTR.Status.W = SmartCard_CTR.Status.W & ((uint32_t)(~(SmartCard_STATUS_ATR_RECEIVECOMPLETE | SmartCard_STATUS_TRANSMISSION_ACTIVE)));
                API_SmartCard_WarmReset();
                return;
            } 
            else
            {
                SmartCard_CTR.Status.MBIT.ATRError = 1;
                return;
            }
        }
        // Process PPS exchange.
        if( SmartCard_CTR.PPS.Status == SmartCard_PPS_STATUS_TRG)
        {
            if(SmartCard_Retry!=0)
            {
                SmartCard_Retry = SmartCard_Retry - 1;
                
                SmartCard_CTR.Status.MBIT.PPSExchange = 1;
                SmartCard_CTR.PPS.Status      = SmartCard_PPS_STATUS_BUSY;       
                API_SmartCard_TriggerPPSRequest(SmartCard_CTR.GITByte.T,SmartCard_CTR.GITByte.Fi,SmartCard_CTR.GITByte.Di);
                return;
            }
            
            SmartCard_CTR.Status.MBIT.ATRError = 1;
            return;
        }
        
        SmartCard_CTR.Status.MBIT.Transmission_Init = 1;
       
    }
}

/**
 * @name Static function
 *   		
 */ 
///@{
/**
 *******************************************************************************
 * @brief	    Delay function inital.
 * @details     
 * @return      
 * @exception   No
 * @note        The function can't use __API_SmartCard_WTStart together.
 *******************************************************************************
 */
static void API_SmartCard_Delay( uint32_t SmartCard_Delay, SmartCard_DelayUnit SmartCard_dUnit)
{
    /*
    1. Disable Timer 
    2. Clear Timer overflow flag.
    3. Clear Timer counter.
    4. Set Timer reload data.
    */
    SmartCard_DELAY_TM->CR0.B[0] &= ~(TM_CR0_EN_mask_b0 | TM_CR0_EN2_mask_b0);
    SmartCard_DELAY_TM->STA.W     = (TMx_TOF | TMx_TOF2);
    
    if( SmartCard_dUnit == SmartCard_CLK_f)
    {
        SmartCard_DELAY_TM->PSARR.H[0] =  SmartCard_DelayCLKf_TMReload;
    }
    else
    {
        SmartCard_DELAY_TM->PSARR.H[0] =  SmartCard_Delayetu_TMReload;
    }
    
    SmartCard_DELAY_TM->CNT.H[0]   = 0;
    
    SmartCard_DelayTmp = 0;
    if((SmartCard_Delay & 0xFFFF0000)==0)
    {
        SmartCard_DelayCmp = 1;

        SmartCard_DELAY_TM->ARR.H[0] = ((uint16_t)(SmartCard_Delay&0x0000FFFF));
    }
    /*Round down 65536 integer multiple.*/
    else
    {
        SmartCard_DelayCmp = (SmartCard_Delay >> 16); 
  
        SmartCard_DELAY_TM->ARR.H[0] = 0xFFFF;
    }        
    
    SmartCard_DELAY_TM->CR0.B[0] |= TM_CR0_EN_enable_b0 | TM_CR0_EN2_enable_b0;
}
/**
 *******************************************************************************
 * @brief	    Delay function.
 * @details     If delay time no change can using the function to trigger delay.
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_TriggerDelay(void)
{
    SmartCard_DELAY_TM->CR0.B[0] &= ~(TM_CR0_EN_mask_b0 | TM_CR0_EN2_mask_b0);        // Disable Timer
    SmartCard_DELAY_TM->STA.W     = (TMx_TOF | TMx_TOF2);                             // Clear Timer overflow flag.
    SmartCard_DelayTmp            = 0;                                                // Clear software count.
    SmartCard_DELAY_TM->CNT.H[0]  = 0;                                                // Clear timer counter.
    SmartCard_DELAY_TM->CR0.B[0] |= TM_CR0_EN_enable_b0 | TM_CR0_EN2_enable_b0;       // Enable Timer.
}

/**
 *******************************************************************************
 * @brief	    Disable WT timer count.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_DisableWT(void)
{
    TM_Timer_Cmd( SmartCard_DELAY_TM,DISABLE);
    TM_ClearFlag( SmartCard_DELAY_TM, (TMx_TOF | TMx_TOF2));
}
/**
 *******************************************************************************
 * @brief	    Stop CLK signal output.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_StopCLK(void)
{
    TM_Timer_Cmd(URTx_CLK_TM, DISABLE);
    URT_BaudRateGenerator_Cmd(SmartCard_URTx, DISABLE);
    URT_CtrlCLKSignalStatus_SW( SmartCard_URTx, CLR); 
}
/**
 *******************************************************************************
 * @brief	    Start CLK signal output.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_StartCLK(void)
{
    SmartCard_URTx->CNT.W = 0;
    URT_CtrlCLKSignalStatus_SW( SmartCard_URTx, CLR); 
    URT_BaudRateGenerator_Cmd(SmartCard_URTx, ENABLE);
    TM_Timer_Cmd(URTx_CLK_TM, ENABLE);
}
/**
 *******************************************************************************
 * @brief	    IO receive enable or disable.
 * @details     
 * @param[in]   SmartCard_IO_Cmd : Control IO receive function enable or disable.
 *  @arg\b      ENABLE : Enable IO receive function.
 *  @arg\b      DISABLE: Disable IO receive function.
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_IO_Cmd( FunctionalState SmartCard_IO_Cmd)
{
    if( SmartCard_IO_Cmd == ENABLE)
    {
        SmartCard_IO = 1;
        SmartCard_IO_PINX->CR.MBIT.AFS = SmartCard_IO_AFS;
        URT_RX_Cmd(SmartCard_URTx, ENABLE);
        
        URT_ClearRxHoldFlag(SmartCard_URTx);
        URT_ClearRXData( SmartCard_URTx);
        URT_ClearITFlag( SmartCard_URTx, URT_IT_Mask);
        URT_IT_Config( SmartCard_URTx, URT_IT_RX , ENABLE);
    }
    else
    {
        URT_RX_Cmd(SmartCard_URTx, DISABLE);
        URT_IT_Config( SmartCard_URTx, (URT_IT_TC | URT_IT_TX | URT_IT_RX | URT_IT_PE | URT_IT_TXE | URT_IT_RXTMO), DISABLE);
        SmartCard_IO_PINX->CR.MBIT.AFS = 0;
        SmartCard_IO = 0;
    }
}
/**
 *******************************************************************************
 * @brief	    Set etu 
 * @details     
 * @param[in]   etu_Fi_f: F of etu parameter.
 * @param[in]   etu_Di: D of etu parameter.
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_SetETU( uint8_t etu_Fi_f , uint8_t etu_Di) 
{
    URT_BRG_TypeDef         ETU_URTx_BRG;
    TM_TimeBaseInitTypeDef  TM_TimeBase_InitStruct;
    uint32_t                SmartCard_SetETU_Tmp;             
    
    /*Set etu*/
    //Stop CLK output
    API_SmartCard_StopCLK();

    //Set Baud-Rate generator clock source. (Use TM00)
    TM_TimeBaseStruct_Init(&TM_TimeBase_InitStruct);
    
    TM_TimeBase_InitStruct.TM_Period      = SmartCard_ATR_f_TM00Table[etu_Fi_f];
    TM_TimeBase_InitStruct.TM_Prescaler   = 1 - 1;
    TM_TimeBase_InitStruct.TM_CounterMode = Cascade;
    TM_TimeBase_Init(URTx_CLK_TM, &TM_TimeBase_InitStruct);
    
    TM_TRGO_Select(URTx_CLK_TM, TRGO_UEV);
    TM_UEV_Config(URTx_CLK_TM, UEV_TOF);
    TM_UEV_Cmd(URTx_CLK_TM, ENABLE);
    TM_Timer_Cmd(URTx_CLK_TM, DISABLE);
        

    //Set Baud-Rate generator
    ETU_URTx_BRG.URT_InternalClockSource    = URT_BDClock_Timer00TRGO;
    ETU_URTx_BRG.URT_BaudRateMode           = URT_BDMode_Separated;
    ETU_URTx_BRG.URT_PrescalerCounterReload = SmartCard_ATR_Di_PSRTable[etu_Di];	                
    ETU_URTx_BRG.URT_BaudRateCounterReload  = SmartCard_ATR_Fi_RLRTable[etu_Fi_f];	                
    URT_BaudRateGenerator_Config(SmartCard_URTx, &ETU_URTx_BRG);   
    URT_BaudRateCounterClockSource_Select( SmartCard_URTx,URT_BRCountClock_CK_URT);             // Baud-Rate 8-bit Counter of URT Baud-Rate Generator
    
    SmartCard_SetETU_Tmp = ((SmartCard_ATR_f_TM00Table[etu_Fi_f]+1) * (SmartCard_ATR_Di_PSRTable[etu_Di]+1));

    if( SmartCard_SetETU_Tmp > 48)
    {
        SmartCard_URTx->CLK.MBIT.CK_SEL = URT_CLK_BR_CKS_psc_b3;
    }
    
    // clock source from CK_URTx.
    //Set TX / RX data oversampling
    URT_TXOverSamplingSampleNumber_Select(SmartCard_URTx, SmartCard_ATR_Fi_OSTable[etu_Fi_f]);	                    
    URT_RXOverSamplingSampleNumber_Select(SmartCard_URTx, SmartCard_ATR_Fi_OSTable[etu_Fi_f]);
    
    /*Set f delay*/
    //Use TM10
    TM_TimeBaseStruct_Init(&TM_TimeBase_InitStruct);
    
    //Set Timer mode
    TM_TimeBase_InitStruct.TM_Prescaler   = 1 - 1;
    TM_TimeBase_InitStruct.TM_Period      = 1 - 1; 
    TM_TimeBase_InitStruct.TM_CounterMode = Cascade;
    TM_TimeBase_Init(SmartCard_DELAY_TM, &TM_TimeBase_InitStruct);
    TM_Timer_Cmd(SmartCard_DELAY_TM, DISABLE);
    TM_ClearFlag( SmartCard_DELAY_TM, (TMx_TOF | TMx_TOF2));
    
    
    if( SmartCard_SetETU_Tmp > 48)
    {
        SmartCard_Delayetu_TMReload   = (SmartCard_ATR_Fi_RLRTable[etu_Fi_f]+1)*(SmartCard_ATR_Fi_OSTable[etu_Fi_f]+1);
        SmartCard_DelayCLKf_TMReload  = SmartCard_ATR_Di_PSRTable[etu_Di];
    }
    else
    {
        SmartCard_Delayetu_TMReload   = (SmartCard_ATR_Fi_RLRTable[etu_Fi_f]+1)*(SmartCard_ATR_Fi_OSTable[etu_Fi_f]+1)*(SmartCard_ATR_f_TM00Table[etu_Fi_f]+1);
        SmartCard_DelayCLKf_TMReload  = (SmartCard_ATR_Di_PSRTable[etu_Di]+1)*(SmartCard_ATR_f_TM00Table[etu_Fi_f]+1);
    }
    
    SmartCard_Delayetu_TMReload--;
    SmartCard_DelayCLKf_TMReload--;
    
}
/**
 *******************************************************************************
 * @brief	    Set character frame encode.
 * @details   
 * @param[in]   ConventionType:
 *  @arg\b      SmartCard_TS_INVERSE_CONVENTION: inverse convention
 *  @arg\b      SmartCard_TS_DIRECT_CONVENTION : direct convention
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_SetConvention( uint8_t ConventionType)
{
    URT_Data_TypeDef   SmartCard_URTx_DataDef;
    
    SmartCard_URTx_DataDef.URT_TX_DataLength  = URT_DataLength_8;
    SmartCard_URTx_DataDef.URT_RX_DataLength  = URT_DataLength_8;
    SmartCard_URTx_DataDef.URT_TX_StopBits    = URT_StopBits_2_0;
    SmartCard_URTx_DataDef.URT_RX_StopBits    = URT_StopBits_2_0;


    // Convention default = Direct convention.
    if(ConventionType == SmartCard_TS_INVERSE_CONVENTION)
    {
        SmartCard_URTx_DataDef.URT_TX_DataOrder   = URT_DataTyped_MSB;
        SmartCard_URTx_DataDef.URT_RX_DataOrder   = URT_DataTyped_MSB;
        SmartCard_URTx_DataDef.URT_TX_Parity      = URT_Parity_Odd;
        SmartCard_URTx_DataDef.URT_RX_Parity      = URT_Parity_Odd;
        SmartCard_URTx_DataDef.URT_TX_DataInverse = ENABLE;
        SmartCard_URTx_DataDef.URT_RX_DataInverse = ENABLE;
    }
    // Convention default = Direct convention.
    else
    {
        SmartCard_URTx_DataDef.URT_TX_DataOrder   = URT_DataTyped_LSB;
        SmartCard_URTx_DataDef.URT_RX_DataOrder   = URT_DataTyped_LSB;
        SmartCard_URTx_DataDef.URT_TX_Parity      = URT_Parity_Even;
        SmartCard_URTx_DataDef.URT_RX_Parity      = URT_Parity_Even;
        SmartCard_URTx_DataDef.URT_TX_DataInverse = DISABLE;
        SmartCard_URTx_DataDef.URT_RX_DataInverse = DISABLE;
    }
    
    URT_DataCharacter_Config(SmartCard_URTx, &SmartCard_URTx_DataDef);
      
}
/**
 *******************************************************************************
 * @brief	    Trigger activation.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_Activation(void)
{
    // Answer to Reset data to default.
    API_SmartCard_ATR_DeInit(ENABLE);

    
    // RST shall be put to state L
    __SmartCard_RST_SetLow();
    
    // Set default convention.
    API_SmartCard_SetConvention(SmartCard_TS_DIRECT_CONVENTION);
    
    // VCC shall be powered.
    __SmartCard_VCC_ON();
    
    SmartCard_iStatus  = SmartCard_STATUS_ACTIVATION_VCC;
    
    API_SmartCard_Delay(10000,SmartCard_CLK_f);                 // Wait for VCC power on steady.
    
       
}

/**
 *******************************************************************************
 * @brief	    Trigger deactivate.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_Deactivate(void)
{
    SmartCard_iStatus      = SmartCard_STATUS_DEACTIVATE;
    
    /*Disable delay / WT timer.*/
    API_SmartCard_DisableWT();
    
    /* RST shall be put to state L. */
    __SmartCard_RST_SetLow();
    
    /* CLK shall be stopped and put to state L. */
    API_SmartCard_StopCLK();
    
    /* I/O shall be put to state L. */
    API_SmartCard_IO_Cmd( DISABLE);
    
    /* VCC shal be deactivated. */
    __SmartCard_VCC_OFF();
    
    /* Set parameter. */
    SmartCard_iStatus      = SmartCard_STATUS_DISABLE;
    SmartCard_CTR.Status.W = SmartCard_STATUS_INSERTED;
}
/**
 *******************************************************************************
 * @brief	    Trigger warm reset.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_WarmReset(void)
{
    // Protocol parameter to default.
    API_SmartCard_ATR_DeInit(DISABLE);
    API_SmartCard_StartCLK();
    
    // RST shall be put to state L
    API_SmartCard_IO_Cmd( DISABLE);
    __SmartCard_RST_SetLow();
    API_SmartCard_IO_Cmd( ENABLE);
    
    //Set Parameter 
    SmartCard_iStatus = SmartCard_STATUS_WARMRESET;
    
    // Delay (400 / f) to cold reset.
    API_SmartCard_Delay(360,SmartCard_CLK_f);

}
/**
 *******************************************************************************
 * @brief	    Receive ATR data handler.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_ReceiveATR(void)
{
    uint8_t  SmartCard_ReceiveATR_8Tmp;
    uint32_t SmartCard_ReceiveATR_Tmp;
    
    SmartCard_ReceiveATR_Tmp = ( SmartCard_iStatus & SmartCard_STATUS_SUB_MASK);
            
    /*Receive Format byte T0*/
    if( SmartCard_ReceiveATR_Tmp & SmartCard_STATUS_ATR_T0)
    {
        SmartCard_iStatus                  = SmartCard_iStatus & ((uint32_t)(~SmartCard_STATUS_ATR_T0));
        SmartCard_CTR.ATR.T0               = SmartCard_URTx->RDAT.B[0];
                                     
        SmartCard_Tmp                      = SmartCard_CTR.ATR.T0 & SmartCard_ATR_Y_MASK;     // Get TA1,TB1,TC1,TD1 whether present or not.
        SmartCard_TmpCmp                   = SmartCard_ATR_Y_TA;
        SmartCard_CTR.ATR.InterfaceLength  = 0;                                   // Interface byte of ATR total byte to default.

        SmartCard_CTR.ATR.HistoricalLength = SmartCard_CTR.ATR.T0 & SmartCard_ATR_K_MASK;     // Get Historical byte of ATR size.
        
        return;
    }
    /*Receive Interface bytes*/
    else if( SmartCard_ReceiveATR_Tmp & SmartCard_STATUS_ATR_INTERFACE)
    {
        for( SmartCard_ReceiveATR_8Tmp = 0; SmartCard_ReceiveATR_8Tmp < 4; SmartCard_ReceiveATR_8Tmp++)
        {
            if( SmartCard_Tmp & SmartCard_TmpCmp)
            {
                if( SmartCard_CTR.ATR.InterfaceLength < SmartCard_ATR_MAX_TOTAOL_INTERFACEBYTE)
                {
                    SmartCard_CTR.ATR.Interface[SmartCard_CTR.ATR.InterfaceLength] = SmartCard_URTx->RDAT.B[0];
                }
                SmartCard_CTR.ATR.InterfaceLength  = SmartCard_CTR.ATR.InterfaceLength + 1;
                break;
            }
            SmartCard_TmpCmp = ((uint8_t)(SmartCard_TmpCmp << 1));
        }
        
        SmartCard_ReceiveATR_8Tmp = SmartCard_Tmp & ((uint8_t)(~SmartCard_TmpCmp));
        
        if( SmartCard_ReceiveATR_8Tmp != 0) 
        {
            SmartCard_Tmp = SmartCard_ReceiveATR_8Tmp;
            return;
        }
        if(SmartCard_TmpCmp == SmartCard_ATR_Y_TD)
        {
            SmartCard_ReceiveATR_8Tmp = SmartCard_CTR.ATR.Interface[(SmartCard_CTR.ATR.InterfaceLength-1)];
            
            SmartCard_Tmp     = SmartCard_ReceiveATR_8Tmp & SmartCard_ATR_Y_MASK;
            SmartCard_TmpCmp  = SmartCard_ATR_Y_TA;
            
            if((SmartCard_ReceiveATR_8Tmp & SmartCard_ATR_T_MASK)!=0)
            {
                SmartCard_CTR.ATR.TCK_present = 1;
            }
            return;
        }
        
        SmartCard_iStatus  = SmartCard_iStatus & ((uint32_t)(~SmartCard_STATUS_ATR_INTERFACE));
        
        if( SmartCard_CTR.ATR.HistoricalLength == 0)
        {
            SmartCard_iStatus  = SmartCard_iStatus & ((uint32_t)(~SmartCard_STATUS_ATR_HISTORICAL));
        }
        if( SmartCard_CTR.ATR.TCK_present == 1)
        {
            SmartCard_iStatus  = SmartCard_iStatus | SmartCard_STATUS_ATR_TCK;
        }
        
        SmartCard_Tmp = 0;
        return;
    }
    /*Receive Historical bytes*/
    else if( SmartCard_ReceiveATR_Tmp & SmartCard_STATUS_ATR_HISTORICAL)
    {
        SmartCard_CTR.ATR.Historical[SmartCard_Tmp] = SmartCard_URTx->RDAT.B[0];
        SmartCard_Tmp                         = SmartCard_Tmp + 1;
        
        if(SmartCard_Tmp== SmartCard_CTR.ATR.HistoricalLength)
        {
            SmartCard_iStatus = SmartCard_iStatus & ((uint32_t)(~SmartCard_STATUS_ATR_HISTORICAL));
        }
    }
    /*Receive Check byte TCK*/
    else if( SmartCard_ReceiveATR_Tmp & SmartCard_STATUS_ATR_TCK)
    {
        SmartCard_CTR.ATR.TCK = SmartCard_URTx->RDAT.B[0];
        
        SmartCard_iStatus = SmartCard_iStatus & ((uint32_t)(~SmartCard_STATUS_ATR_TCK));
    }
    
    if((SmartCard_iStatus & SmartCard_STATUS_SUB_MASK)==0)
    {
        API_SmartCard_DisableWT();
        SmartCard_CTR.Status.MBIT.ATRReceiveComplete = 1;
    }
}
/**
 *******************************************************************************
 * @brief	    Decode ATR data.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static uint32_t API_SmartCard_DecodeATR(void)
{
    uint8_t SmartCard_DecodeATR_Tmp;
    uint8_t SmartCard_DecodeATR_Cmp;
    uint8_t SmartCard_DecodeATR_Index;
    
    uint8_t  SmartCard_ATR_Yi;
    uint8_t  SmartCard_ATR_CheckSum;

    uint16_t SmartCard_ATR_T;                       // The card support T.
    uint16_t SmartCard_DecodeATR_Tmp16;
    
    /*Check ATR interface total bytes whether correct or not.*/
    if( SmartCard_CTR.ATR.InterfaceLength > SmartCard_ATR_MAX_TOTAOL_INTERFACEBYTE)
    {
        return(SmartCard_FAILURE);
    }
    
    /*Check (TCK) */
    // Check TCK whether present or not.
    if( SmartCard_CTR.ATR.TCK_present == 1)
    {
        //Operation T0 to TCK.
        SmartCard_ATR_CheckSum = SmartCard_CTR.ATR.T0;
        
        for( SmartCard_DecodeATR_Tmp = 0; SmartCard_DecodeATR_Tmp < SmartCard_CTR.ATR.InterfaceLength; SmartCard_DecodeATR_Tmp++)
        {
            SmartCard_ATR_CheckSum = SmartCard_ATR_CheckSum ^ SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Tmp];
        }
        
        for( SmartCard_DecodeATR_Tmp = 0; SmartCard_DecodeATR_Tmp < SmartCard_CTR.ATR.HistoricalLength; SmartCard_DecodeATR_Tmp++)
        {
            SmartCard_ATR_CheckSum = SmartCard_ATR_CheckSum ^ SmartCard_CTR.ATR.Historical[SmartCard_DecodeATR_Tmp];
        }
        
        SmartCard_ATR_CheckSum = SmartCard_ATR_CheckSum ^ SmartCard_CTR.ATR.TCK;
        
        // TCK check error.
        if( SmartCard_ATR_CheckSum != 0x00)
        {
            return(SmartCard_FAILURE);
        }
    }
    /*Parameter Default*/
    SmartCard_CTR.GITByte.Fi                        = SmartCard_ETU_Fd;               // FI = default
    SmartCard_CTR.GITByte.Di                        = SmartCard_ETU_Dd;               // DI = default
    SmartCard_CTR.SPITByte.WI                       = SmartCard_WI_Deault;            // WI = default
    SmartCard_CTR.GITByte.N                         = SmartCard_N_Default;            // Extra guard time integer(N) =  default.
    SmartCard_CTR.GITByte.TA2_present               = SmartCard_FALSE;                // TA2 default is no present;
    SmartCard_CTR.GITByte.T_15_present              = SmartCard_FALSE;                // T = 15 default default is no present.
    SmartCard_CTR.GITByte.T15_Data[SmartCard_ATR_SPIT_TD] = 0x00;                     // T = 15 TA,TB,TC,TD default is no present.
    SmartCard_ATR_T                                 = 0x0000;                   // The ATR support T mask default is 0x0000 ( no T support)
    SmartCard_CTR.PPS.Status                        = SmartCard_PPS_STATUS_IDLE;      // PPS exchange status default IDLE.
    
    /*T0*/
    SmartCard_ATR_Yi            = SmartCard_CTR.ATR.T0 & SmartCard_ATR_Y_MASK;
    SmartCard_DecodeATR_Index   = 0;
    
    /*Decode TA1 ~ TD1*/
    //TA1
    if( SmartCard_ATR_Yi & SmartCard_ATR_Y_TA)
    {
        SmartCard_ATR_Yi         &=  (uint8_t)(~SmartCard_ATR_Y_TA);
        
        SmartCard_CTR.GITByte.Fi  = (SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index]>>4);                 // clock rate conversion integer (Fi)
        SmartCard_CTR.GITByte.Di  = (SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index]&0x0F);               // baud rate adjustment integer (Di)
        SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
    }
    //TB1 (Deprecated)
    if( SmartCard_ATR_Yi & SmartCard_ATR_Y_TB)
    {
        SmartCard_ATR_Yi         &=  (uint8_t)(~SmartCard_ATR_Y_TB);
        
        SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
    }
    //TC1 ( the extra guard time integer (N))
    if( SmartCard_ATR_Yi & SmartCard_ATR_Y_TC)
    {
        SmartCard_ATR_Yi         &=  (uint8_t)(~SmartCard_ATR_Y_TC);
        
        SmartCard_CTR.GITByte.N   = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
        SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
    }
    //TD1 
    if( SmartCard_ATR_Yi & SmartCard_ATR_Y_TD)
    {
        SmartCard_ATR_Yi         &=  (uint8_t)(~SmartCard_ATR_Y_TD);
        
        SmartCard_ATR_Yi  = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index] & SmartCard_ATR_Y_MASK;
        
        SmartCard_ATR_T  |= ((uint32_t)( 1 << (SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index] & SmartCard_ATR_T_MASK)));               
        
        if( SmartCard_ATR_T & SmartCard_ATR_T15_MASK)
        {
            return( SmartCard_FAILURE);
        }
        SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
    }
    
    /*TA2 ~ TD2*/
    //TA2
    if( SmartCard_ATR_Yi & SmartCard_ATR_Y_TA)
    {
        SmartCard_ATR_Yi                 &=  (uint8_t)(~SmartCard_ATR_Y_TA);
        SmartCard_CTR.GITByte.TA2_present = SmartCard_TRUE;
        SmartCard_CTR.GITByte.TA2         = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
        SmartCard_DecodeATR_Index         = SmartCard_DecodeATR_Index + 1;
    }
    //TB2 (Deprecated)
    if( SmartCard_ATR_Yi & SmartCard_ATR_Y_TB)
    {
        SmartCard_ATR_Yi         &= (uint8_t)(~SmartCard_ATR_Y_TB);
        SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
    }
    //TC2
    if(SmartCard_ATR_Yi & SmartCard_ATR_Y_TC)
    {
        SmartCard_ATR_Yi &= (uint8_t)(~SmartCard_ATR_Y_TC);
        
        if( SmartCard_ATR_T & SmartCard_ATR_T0_MASK)
        {
            SmartCard_CTR.SPITByte.WI = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
        }
        SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
    }
    //TD2
    if( SmartCard_ATR_Yi & SmartCard_ATR_Y_TD)
    {
        SmartCard_ATR_Yi &= (uint8_t)(~SmartCard_ATR_Y_TD);
        
        SmartCard_ATR_Yi  = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index] & SmartCard_ATR_Y_MASK;
        SmartCard_ATR_T  |= ((uint32_t)( 1 << (SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index] & SmartCard_ATR_T_MASK))); 
        
        if( SmartCard_ATR_T & SmartCard_ATR_T15_MASK)
        {
            SmartCard_CTR.GITByte.T_15_present = SmartCard_TRUE;  
            SmartCard_CTR.GITByte.T15_Data[0] = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
        }
        else
        {
            SmartCard_CTR.SPITByte.Total_SPinterface          = 1;
            SmartCard_CTR.SPITByte.SpData[0][SmartCard_ATR_SPIT_TD] = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
        }

        SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
    }
    
    /*TAi ( i > 2)*/
    if( SmartCard_ATR_Yi !=0)
    {
        SmartCard_DecodeATR_Cmp = SmartCard_ATR_Y_TA;
        SmartCard_DecodeATR_Tmp = SmartCard_ATR_SPIT_TA;
        
        if(SmartCard_CTR.GITByte.T_15_present == SmartCard_TRUE)
        {
            do{
                if(SmartCard_CTR.GITByte.T15_Data[0] & SmartCard_DecodeATR_Cmp)
                {
                    SmartCard_CTR.GITByte.T15_Data[SmartCard_DecodeATR_Tmp] = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
                    SmartCard_DecodeATR_Tmp = SmartCard_DecodeATR_Tmp + 1;
                }
                SmartCard_DecodeATR_Tmp = SmartCard_DecodeATR_Tmp + 1;
                SmartCard_DecodeATR_Cmp = ((uint8_t)(SmartCard_DecodeATR_Cmp << 1));
            }while(SmartCard_DecodeATR_Cmp!=SmartCard_ATR_Y_TD);
        }
        else
        {
            while( SmartCard_DecodeATR_Index < SmartCard_CTR.ATR.InterfaceLength)
            {
                if( SmartCard_ATR_Yi & SmartCard_DecodeATR_Cmp)
                {
                     // TD interface byte
                     if( SmartCard_DecodeATR_Cmp == SmartCard_ATR_Y_TD)
                     {
                         SmartCard_CTR.SPITByte.Total_SPinterface = SmartCard_CTR.SPITByte.Total_SPinterface + 1;
                         
                         // ATR interface bytes too much.
                         if(SmartCard_CTR.SPITByte.Total_SPinterface > SmartCard_ATR_MAX_PROTOCOLS)
                         {
                             return( SmartCard_FAILURE);
                         }
                         
                         SmartCard_CTR.SPITByte.SpData[(SmartCard_CTR.SPITByte.Total_SPinterface-1)][SmartCard_ATR_SPIT_TD] = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
                         
                         SmartCard_ATR_Yi        = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index] & SmartCard_ATR_Y_MASK;
                         SmartCard_ATR_T        |= ((uint32_t)( 1 << (SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index] & SmartCard_ATR_T_MASK)));
                         SmartCard_DecodeATR_Tmp = SmartCard_ATR_SPIT_TA;
                     }
                     // TA ~ TC interface byte.
                     else
                     {
                         SmartCard_CTR.SPITByte.SpData[(SmartCard_CTR.SPITByte.Total_SPinterface-1)][SmartCard_DecodeATR_Tmp] = SmartCard_CTR.ATR.Interface[SmartCard_DecodeATR_Index];
                         SmartCard_DecodeATR_Tmp = SmartCard_DecodeATR_Tmp + 1;
                     }
                     
                     SmartCard_DecodeATR_Index = SmartCard_DecodeATR_Index + 1;
                }
                else if(SmartCard_DecodeATR_Cmp==SmartCard_ATR_Y_TD)
                {
                    return(SmartCard_FAILURE);
                }
                else
                {
                    SmartCard_DecodeATR_Cmp = (uint8_t)(SmartCard_DecodeATR_Cmp << 1);
                    SmartCard_DecodeATR_Tmp = SmartCard_DecodeATR_Tmp + 1;
                }
            }
        }
    }

    /*Check transmission protocol*/
    if(SmartCard_ATR_T == 0x00)                      // No default protocol found in ATR using T = 0
    {
        SmartCard_ATR_T = SmartCard_ATR_T0_MASK;
    }
    
    /*Check TA2 whether presetn or not.*/
    //Specific mode.
    if( SmartCard_CTR.GITByte.TA2_present == SmartCard_TRUE)
    {
        SmartCard_DecodeATR_Tmp = SmartCard_CTR.GITByte.TA2 & SmartCard_ATR_TA2_T_MASK;
        
        //The specific protocol no support.
        if(( SmartCard_ATR_T_SUPPORT & ((uint16_t)(1 << SmartCard_DecodeATR_Tmp)))==0)
        {
            return(SmartCard_FAILURE);
        }
        SmartCard_CTR.GITByte.T = SmartCard_DecodeATR_Tmp;
        
        // F & D use default
        if(SmartCard_CTR.GITByte.TA2 & SmartCard_ATR_TA2_FD_MASK)
        {
            SmartCard_CTR.GITByte.Fi    = SmartCard_ETU_Fd;         // FI = default
            SmartCard_CTR.GITByte.Di    = SmartCard_ETU_Dd;         // DI = default 
        }
    }
    
    //In Negotiable mode and T type support.
    else if( SmartCard_ATR_T & SmartCard_ATR_T_SUPPORT)
    {
        SmartCard_DecodeATR_Tmp16 = SmartCard_ATR_T;
        SmartCard_DecodeATR_Tmp   = 0;

        //Store number of protocols
        do{
            if( SmartCard_DecodeATR_Tmp16 & 0x0001)
            {
                SmartCard_DecodeATR_Tmp   = SmartCard_DecodeATR_Tmp + 1;
            }
            SmartCard_DecodeATR_Tmp16 = SmartCard_DecodeATR_Tmp16 >> 1;
            
        }while(SmartCard_DecodeATR_Tmp16!=0);
        
        //If the card support multi protocols process PPS exchange.
        if(SmartCard_DecodeATR_Tmp!=1)
        {
            SmartCard_CTR.PPS.Status = SmartCard_PPS_STATUS_TRG;
        }    
            
        //Decide to T type.
        SmartCard_DecodeATR_Tmp16 = SmartCard_ATR_T & SmartCard_ATR_T_SUPPORT;
        SmartCard_DecodeATR_Tmp   = 0;
        
        do{
            if(SmartCard_DecodeATR_Tmp16 & 0x0001)
            {
                break;
            }
         
            SmartCard_DecodeATR_Tmp   = SmartCard_DecodeATR_Tmp + 1;
            SmartCard_DecodeATR_Tmp16 = SmartCard_DecodeATR_Tmp16 >> 1;
            
        }while( SmartCard_DecodeATR_Tmp16!=0);
        
        SmartCard_CTR.GITByte.T = SmartCard_DecodeATR_Tmp;
        
    }
    //In Negotiable mode and T type no support.
    else 
    {
        return(SmartCard_FAILURE);
    }
    return(SmartCard_SUCCESS);
}

/**
 *******************************************************************************
 * @brief	    Trigger PPS request
 * @details     
 * @param[in]   PPS_T: expect T.
 * @param[in]   PPS_F: expect F.
 * @param[in]   PPS_D: expect D.
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_TriggerPPSRequest(uint8_t PPS_T , uint8_t PPS_F , uint8_t PPS_D )
{
    SmartCard_CTR.PPS.Request[0] = 0xFF;                     // PPSS
    SmartCard_CTR.PPS.Request[1] = (SmartCard_PPS0_PPS1 | PPS_T);  // PPS0 ( PPS1 presence + T)
    SmartCard_CTR.PPS.Request[2] = (((PPS_F << 4) & 0xF0) + PPS_D);
    SmartCard_CTR.PPS.Request[3] = (SmartCard_CTR.PPS.Request[0] ^ SmartCard_CTR.PPS.Request[1] ^ SmartCard_CTR.PPS.Request[2]);
    
    SmartCard_iStatus = ( SmartCard_STATUS_PPSREQUEST  | \
                    SmartCard_STATUS_PPSRESPONSE | (SmartCard_STATUS_PPSS|SmartCard_STATUS_PPS0|SmartCard_STATUS_PCK));
    
    SmartCard_Tmp     = 0;

    API_SmartCard_Transmit(&SmartCard_CTR.PPS.Request[0], 4);
    
}

/**
 *******************************************************************************
 * @brief	    Receive PPS response handler.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_ReceivePPSResponse(void)
{
    uint32_t  SmartCard_ReceivePPSResponseTmp;
    
    SmartCard_ReceivePPSResponseTmp = ( SmartCard_iStatus & SmartCard_STATUS_SUB_MASK);
    
    if( SmartCard_ReceivePPSResponseTmp & SmartCard_STATUS_PPSS)
    {
        SmartCard_CTR.PPS.Response[SmartCard_Tmp] = SmartCard_URTx->RDAT.B[0];
        SmartCard_iStatus &= ((uint32_t)(~SmartCard_STATUS_PPSS));
    }
    else if( SmartCard_ReceivePPSResponseTmp & SmartCard_STATUS_PPS0)
    {
        SmartCard_CTR.PPS.Response[SmartCard_Tmp]  = SmartCard_URTx->RDAT.B[0];
        SmartCard_iStatus                   |= (SmartCard_CTR.PPS.Response[SmartCard_Tmp] & ( SmartCard_PPS0_PPS3 | SmartCard_PPS0_PPS2 | SmartCard_PPS0_PPS1));
        SmartCard_iStatus &= ((uint32_t)(~SmartCard_STATUS_PPSS));
    }
    else if( SmartCard_ReceivePPSResponseTmp & SmartCard_STATUS_PPS1)
    {
        SmartCard_CTR.PPS.Response[SmartCard_Tmp]  = SmartCard_URTx->RDAT.B[0];
        SmartCard_iStatus &= ((uint32_t)(~SmartCard_STATUS_PPS1));
    }
    else if( SmartCard_ReceivePPSResponseTmp & SmartCard_STATUS_PPS2)
    {
        SmartCard_CTR.PPS.Response[SmartCard_Tmp]  = SmartCard_URTx->RDAT.B[0];   
        SmartCard_iStatus &= ((uint32_t)(~SmartCard_STATUS_PPS2));
    }
    else if( SmartCard_ReceivePPSResponseTmp & SmartCard_STATUS_PPS3)
    {
        SmartCard_CTR.PPS.Response[SmartCard_Tmp]  = SmartCard_URTx->RDAT.B[0];
        SmartCard_iStatus &= ((uint32_t)(~SmartCard_STATUS_PPS3));
    }        
    else if( SmartCard_ReceivePPSResponseTmp & SmartCard_STATUS_PCK)
    {
        SmartCard_CTR.PPS.Response[SmartCard_Tmp]  = SmartCard_URTx->RDAT.B[0]; 
        SmartCard_iStatus &= ((uint32_t)(~(SmartCard_STATUS_PCK | SmartCard_STATUS_PPSRESPONSE))); 
        
        API_SmartCard_DisableWT();   
        
        SmartCard_CTR.PPS.Status = SmartCard_PPS_STATUS_RESPONSE;
        return;       
    }  

    SmartCard_Tmp = SmartCard_Tmp + 1;
}

/**
 *******************************************************************************
 * @brief	    To check PPS reponse whether success or not.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static uint8_t API_SmartCard_CheckPPSResponse(void)
{
    uint8_t SmartCard_CKPPSResponseTmp;
    uint8_t SmartCard_CKPPSResponseCmp;
    
    if(SmartCard_CTR.PPS.Response[0]!=0xFF)
    {
        return(SmartCard_FAILURE);
    }
    if((SmartCard_CTR.PPS.Request[1]&SmartCard_PPS0_T)!=(SmartCard_CTR.PPS.Response[1]&SmartCard_PPS0_T))
    {
        return(SmartCard_FAILURE);
    }
    
    SmartCard_CKPPSResponseCmp = SmartCard_PPS0_PPS1;
    
    for( SmartCard_CKPPSResponseTmp = 0; SmartCard_CKPPSResponseTmp < 4; SmartCard_CKPPSResponseTmp++)
    {
        if((SmartCard_CTR.PPS.Request[1]&SmartCard_CKPPSResponseCmp)==0 && (SmartCard_CTR.PPS.Response[1]&SmartCard_CKPPSResponseCmp)!=0)
        {
            return(SmartCard_FAILURE);
        }
    }
    
    if( (SmartCard_CTR.PPS.Response[1] & SmartCard_PPS0_PPS1)==0)
    {
        SmartCard_CTR.GITByte.Fi = SmartCard_ETU_Fd;
        SmartCard_CTR.GITByte.Di = SmartCard_ETU_Dd;
        
    }

    return(SmartCard_SUCCESS);
}

/**
 *******************************************************************************
 * @brief	    User receive data IRQ handler function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
static void API_SmartCard_Receive_IRQHandler(void)
{
    API_SmartCard_DisableWT();
    
    *SmartCard_CTR.RxBuf = SmartCard_URTx->RDAT.B[0];
    
    SmartCard_CTR.RxBuf    = SmartCard_CTR.RxBuf + 1;
    SmartCard_CTR.RXLength = SmartCard_CTR.RXLength - 1;
    
    if(SmartCard_CTR.RXLength == 0)
    {
        SmartCard_iStatus &= ((uint32_t)(~SmartCard_STATUS_RXBUSY));
        
        API_SmartCard_RxCpltCallback();
        return;
    }
    __API_SmartCard_WTReStart();
}

///@}

/**
 * @name call back function.
 *   		
 */ 
///@{

/**
 *******************************************************************************
 * @brief	    ATR success callback function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
__WEAK void API_SmartCard_CardInsertCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modified , when the
    //       callback is needed, the API_SmartCard_CardInsertCallback can
    //       be implemented in the user file.
}
/**
 *******************************************************************************
 * @brief	    ATR success callback function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
__WEAK void API_SmartCard_CardRemoveCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modified , when the
    //       callback is needed, the API_SmartCard_CardRemoveCallback can
    //       be implemented in the user file.
}
/**
 *******************************************************************************
 * @brief	    ATR success callback function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
__WEAK void API_SmartCard_ATRCpltCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modified , when the
    //       callback is needed, the API_SmartCard_ATRCpltCallback can
    //       be implemented in the user file.
    
}
/**
 *******************************************************************************
 * @brief	    User can start transmission callback function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
__WEAK void API_SmartCard_UserTransmission(void)
{
    //=========================================================
    //NOTE : This function should not be modified , when the
    //       callback is needed, the API_SmartCard_UserTransmission can
    //       be implemented in the user file.    
}
/**
 *******************************************************************************
 * @brief	    Transmitting complete callback function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
__WEAK void API_SmartCard_TxCpltCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modified , when the
    //       callback is needed, the API_SmartCard_TxCpltCallback can
    //       be implemented in the user file.
    
}
/**
 *******************************************************************************
 * @brief	    Receiving complete callback function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
__WEAK void API_SmartCard_RxCpltCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modified , when the
    //       callback is needed, the API_SmartCard_RxCpltCallback can
    //       be implemented in the user file.
}

/**
 *******************************************************************************
 * @brief	    Receiving complete callback function.
 * @details     
 * @return      
 * @exception   No
 * @note        
 *******************************************************************************
 */
__WEAK void API_SmartCard_ErrorCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modified , when the
    //       callback is needed, the API_SmartCard_ErrorCallback can
    //       be implemented in the user file.
}

///@}






