Index: yc_7816_emv_L1/yc_7816.h
===================================================================
--- /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816.h	(nonexistent)
+++ /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816.h	(working copy)
@@ -0,0 +1,332 @@
+/*
+File Name    : yc_iso7816.h
+Author       : Yichip
+Version      : V1.0TI
+Date         : 2020/7/28
+Description  : iso7816 encapsulation.
+*/
+
+#ifndef __YC_ISO7816_H__
+#define __YC_ISO7816_H__
+
+#include "yc_gpio.h"
+
+#define POLL_PROCESS      //不开启中断，轮询模式收发数据，主循环内处理协议
+
+//#define DEBUG_7816_FPGA
+#define DEBUG_7816_EMV          //定义时开启EMV测试时打印交互状态
+//#define DEBUG_7816              //定义时开启打印交互数据
+//#define HARD_BGT
+#define EMV_L1_43D
+
+/**
+ * @brief  sci7816 Timer define
+ */
+#define SCI7816_TIMX                        (TIM_NumTypeDef)SCIx->SCI_Tran_StateCB.atrovertime_index
+#define SCI7816_TIMER_PERIOD                (0xFFFFFFFF)
+#define SCI7816_TIMX_CNT                    (MTIM->CNT.reg[SCI7816_TIMX])
+
+/**
+ * @brief  sci7816 pwm clk define
+ */
+#define SCI7816_PWMClK4M_TIMX               (TIM_NumTypeDef)SCIx->SCI_Tran_StateCB.pwmclk_index
+#define SCI7816_PWM4M_PERIOD                SCIx->SCI_Tran_StateCB.pwmclk_num
+
+#define SCI17816_PWMClK4M_TIMX              (TIM_NumTypeDef)SCIx->SCI_Tran_StateCB.pwmclk_index
+
+//set val
+#define TX_APDU_FIFO_WATERLEVER_VAL         (4)
+#define RX_APDU_FIFO_WATERLEVER_VAL         (4)
+#define RX_ATR_FIFO_WATERLEVER_VAL          (1)
+
+#define     CONTACT_RESET_L_CNT             SCIx->SCI_Tran_StateCB.contact_reset_l_cnt         //(40000-45000) 复位引脚保持低电平持续时间
+#define     CONTACT_ATR_RFB_TIME_CNT        SCIx->SCI_Tran_StateCB.contact_atr_rfb_time_cnt    //42019(400-40000)	等待IC回应第一个ATR字节的最大时间
+#define     CONTACT_ATR_RAB_TIME_CNT        SCIx->SCI_Tran_StateCB.contact_atr_rab_time_cnt    //19200etu内复位信息应答完成(TS - LAST)
+#define     CONTACT_OVER_TIME_CNT           SCIx->SCI_Tran_StateCB.contact_over_time_cnt       //量产中最大的接收、发送超时时间，设置为3S
+#define     CONTACT_OVER_TIME_VAL           (3)                           //量产中最大的接收、发送超时时间，设置为3S
+
+#define     ATR_SIZE_MAX                    (0x33)        //51
+#define     REC_SIZE_MAX                    (0x10A)       //5+256+5
+#define     SEND_SIZE_MAX                   (0x106)       //3+254+5
+
+
+#define     PROTOCOL_T0                     (0)
+#define     PROTOCOL_T1                     (1)
+#define     PROTOCOL_T1_IBLOCK              (1)
+#define     PROTOCOL_T1_SBLOCK              (2)
+#define     PROTOCOL_T1_SENDDATA            (3)
+#define     PROTOCOL_T1_SENDDATA_SEC        (0)
+#define     PROTOCOL_T1_SBLOCK_IFS          (2)
+#define     PROTOCOL_T1_SBLOCK_ABORT        (3)
+
+#define     T1_SEND                         (0)
+#define     T1_REC                          (1)
+#define     T1_IDLE                         (2)
+
+//错误码定义
+#define     OK                              (0)
+#define     NOK                             (1)
+
+#define     ISO7816_POWER_OFF               (0x4E)
+#define     ISO7816_ATR_ERROR               (0x4F)
+#define     ISO7816_ATR_LEN_ERROR           (0x50)
+#define     ISO7816_ATR_TCK_ERROR           (0x51)
+#define     ISO7816_PROTOCOL_ERROE          (0x53)
+#define     ISO7816_T1_LRC_ERROR            (0x54)
+#define     ISO7816_CARD_STUTES_ERROR       (0x56)
+#define     ISO7816_OPERATE_MODE_ERROR      (0x57)
+#define     ISO7816_PARA_ERROR              (0x59)
+#define     ISO7816_REC_TIMEOUT             (0x5A)
+#define     ISO7816_SEND_TIMEOUT            (0x5B)
+#define     ISO7816_ERR_NUM_OVER            (0x5C)
+#define     ISO7816_T1_TRANSFER_ERROR       (0x60)
+#define     ISO7816_CARD_PRESENT            (0x61)
+#define     ISO7816_CARD_ABSENT             (0x62)
+#define     ISO7816_ATR_TB1_ERROR           (0x70)
+#define     ISO7816_PROCEDURE_INS_ERROR     (0x71)
+#define     ISO7816_PARITY_ERROR            (0x73)
+#define     ISO7816_ATR_TA1_ERROR           (0x74)
+#define     ISO7816_ATR_TC2_ERROR           (0x75)
+#define     ISO7816_ATR_TC3_ERROR           (0x76)
+#define     ISO7816_ATR_TA2_ERROR           (0x77)
+#define     ISO7816_ATR_TC1_ERROR           (0x78)
+#define     ISO7816_ATR_TD2_ERROR           (0x79)
+#define     ISO7816_ATR_TB2_ERROR           (0x80)
+#define     ISO7816_ATR_TA3_ERROR           (0x78)
+#define     ISO7816_ATR_TB3_ERROR           (0x79)
+#define     ISO7816_RET_RESPONSE_DIFFERENT  (0x7C)
+#define     ISO7816_RET_BROKEN_CHAIN        (0x7D)
+#define     ISO7816_RET_CHAIN               (0x7E)
+#define     ISO7816_DATALEN_ERR             (0x7F)
+#define     ISO7816_NOTLRC_ERROR            (0x81)
+
+
+/**
+ * @brief  sci7816 card status
+ */
+#define     ISO7816_ACTIVE_CARD             (0x00)
+#define     ISO7816_WARM_RESET              (0x01)
+#define     ISO7816_DEACTIVE_CARD           (0x02)
+
+
+/**
+ * @brief  sci7816 active vcc mode define
+ */
+#define     ISO7816_VCC_5V                  (0x03)
+#define     ISO7816_VCC_3V                  (0x02)
+#define     ISO7816_VCC_1_8V                (0x01)
+#define     ISO7816_VCC_0V                  (0x00)
+
+#define     ISO7816_TYPE_T0                 (0x00)
+#define     ISO7816_TYPE_T1                 (0x01)
+
+#define  R_BLK                              (0x80)     /*R-BLK的高2位*/
+#define  S_BLK                              (0xC0)     /*S-BLK的高2位*/
+#define  S_RQS_MSK                          (0x3F)     /*S-BLK request  低6位mask*/
+#define  S_RSP_MSK                          (0x23)     /*S-BLK response 低6位mask*/
+#define  IFSC                               (0xFE)     /*信息域size*/
+#define  HALF_FIFO                          (8)        /*半空*/
+#define  M_BIT                              (0x20)     /*表示chain状态*/
+#define  NS_BIT                             (0x40)     /*I-BLK序列号位*/
+#define  NR_BIT                             (0x10)     /*R-BLK序列号位*/
+
+#define  ERR_PARITY                         (1)        /*奇偶校验错*/
+#define  ERR_CHKSUM                         (2)        /*校验出错*/
+#define  ERR_PCB                            (4)        /*协议控制字节错*/
+#define  ERR_LEN                            (8)        /*长度字节错*/
+#define  ERR_RELVNT_S                       (16)       /*有S request, 无s response*/
+#define  ERR_FF                             (32)       /*接收到数据长度为FF*/
+
+/*7816发送接收*/
+#define RECV                                (1)
+#define SEND                                (0)
+#define I_BLOCK_C                           (0)
+#define R_BLOCK_C                           (1)
+#define S_BLOCK_C                           (2)
+#define T_S_IFS                             (2)        /*调整信息域的S-BLK*/
+#define T_S_ABORT                           (3)        /*打断CHAIN的S-BLK*/
+#define T_S_WTS                             (4)        /*请求延长等待时的S-BLK*/
+
+#define T1_HEAD_LEN                         (3)        /*帧头长度*/
+#define ERR_SEND_CNT                        (3)        /*错误重发次数*/
+
+#define     ISO7816_NULL_T0                 (0x60)
+
+#define     COMPARE_RETURN(ret);            if(OK != ret)     \
+                                            {                 \
+                                              return  ret;    \
+                                            }
+#define     GET_4_BITS_H(a)                (((a) >>4)& 0x0F)
+#define     GET_4_BITS_L(a)                ((a)& 0x0F)
+
+#define CheckSendState(); if (SCIx->SCI_Tran_StateCB.SCI_TX_Result == 0)    \
+    {                                               \
+        SCIx->SCI_Send_Data.state = 2;              \
+    }                                               \
+    if ((SCIx->SCI_Tran_StateCB.SCI_TX_Result > 0) && (SCIx->SCI_Tran_StateCB.SCI_TX_Result != 0xff))\
+    {                                               \
+        SCIx->SCI_Send_Data.state = 2;              \
+        SCIx->SCI_Send_Data.sw = SCIx->SCI_Tran_StateCB.SCI_TX_Result;      \
+        return SCIx->SCI_Tran_StateCB.SCI_TX_Result;                        \
+    }                                               \
+
+
+#define CheckRecState();	if (SCIx->SCI_Tran_StateCB.SCI_RX_Result != 1)  \
+    {                                               \
+        SCIx->SCI_Rec_Data.state = 2;               \
+        SCIx->SCI_Rec_Data.sw = SCIx->SCI_Tran_StateCB.SCI_RX_Result;       \
+        return SCIx->SCI_Tran_StateCB.SCI_RX_Result;                        \
+    }                                               \
+
+#define CheckRecState_T1();	if (SCIx->SCI_Tran_StateCB.SCI_RX_Result != 1)  \
+    {                                               \
+        SCIx->SCI_Rec_Data.state = 2;               \
+        SCIx->SCI_Rec_Data.sw = SCIx->SCI_Tran_StateCB.SCI_RX_Result;       \
+        return SCIx->SCI_Tran_StateCB.SCI_RX_Result;                        \
+    }                                                \
+
+
+/**
+ * @brief  sci7816 para init define
+ */
+
+typedef struct
+{
+    uint16_t  fi_table[16];                   //配置PPS时高半字节，时钟速率转换因子
+    uint16_t  di_table[16];                   //配置PPS时低半字节，位速率调节因子
+    uint32_t  contact_reset_l_cnt;            //复位引脚保持低电平持续时间
+    uint32_t  contact_atr_rfb_time_cnt;       //42019(400-40000)等待IC回应第一个ATR字节的最大时间
+    uint32_t  contact_atr_rab_time_cnt;       //19200etu内复位信息应答完成(TS - LAST)
+    uint32_t  contact_over_time_cnt;          //量产中最大的接收、发送超时时间，设置为3S
+    uint8_t   *sci_send_ptr;
+    uint8_t   *sci_rec_ptr;
+    uint16_t  SCI_SendLen;                    //发送数据长度
+    uint16_t  SCI_RecLen;                     //接收数据长度
+    uint8_t   SCI_ApduCmd[280];               //APDU数据存储单元
+    volatile  uint8_t  Sci_Pin_Detect_State;  //检测插卡状态，未插卡时，卡到位IO电平状态为1；插卡时，卡到位IO电平状态为0
+    volatile  uint8_t  SCI_State;             //0-rx 1-tx
+    volatile  uint8_t  SCI_RX_Result;         //1-rec finsh
+    volatile  uint8_t  SCI_TX_Result;         //0-send finsh
+    volatile  uint8_t  Card_Type;             //0-T0  1-T1
+    volatile  uint8_t  T1_parity_flag;        //T1传输时奇偶校验标志位
+    volatile  uint8_t  atr_cwt_valid_flag ;   //接收复位信息时，如果未收到第一个字节之前cwt标志置一，此标志此时无效
+    volatile  uint8_t  sci_atr_byte_parity;
+    volatile  uint8_t  contact_atr_reset_l_flag;       //复位IO保持低电平到时间标志
+    volatile  uint8_t  contact_atr_rfb_overtime_falg;  //ICC 回应第一个字节超时标志
+    volatile  uint8_t  contact_atr_rab_overtime_falg;  //ICC 回应所有字节超时标志
+    volatile  uint8_t  SCI_RX_Buf[280];       //rx buf
+    volatile  uint8_t  SCI_TX_Buf[280];       //tx buf
+    volatile  uint32_t terminal_send_cwt;     //配置7816CWT定时值，发送字节完成、接收起始启动计时
+    volatile  uint32_t terminal_rec_cwt;      //配置7816接收CWT超时定时值
+    volatile  uint32_t terminal_rec_bwt;      //配置7816接收BWT超时定时值
+    volatile  uint32_t terminal_send_bgt;     //配置7816块反向发送时间间隔
+    volatile  uint32_t terminal_rec_bwt_atr;  //设置接收BWT复位信息等待时间
+    volatile  uint32_t terminal_change_rec_bwt_num;
+    volatile  uint16_t SCI_Rec_Data_Index;    //接收数据指标
+    volatile  uint8_t  SCI_Process_Step;	  //0-idle 1-rec atr //2-apdu
+    volatile  uint8_t  tpdu_t0_step;          //传输协议数据单元T0步骤
+    volatile  uint8_t  tpdu_t1_step;          //传输协议数据单元T1步骤
+    volatile  uint8_t  tpdu_t1_type;          //传输协议数据单元T1类型
+    volatile  uint32_t time3_cnt_last;        //定时器3减计数器
+    volatile  uint32_t time3_cnt_new;
+    volatile  uint8_t  SCI_tmp61Flag;
+    volatile  uint8_t  SCI_Protocol_Step ;    //interrupt code use
+    volatile  uint8_t atrovertime_index;
+    volatile  uint8_t pwmclk_index;
+    volatile  uint32_t pwmclk_num;
+}SCI_Tran_Status_Type;
+
+//跟T1相关全局变量参数
+typedef struct
+{
+    uint8_t   bIFSC;      //IC卡信息域大小
+    uint8_t   bIFSD;      //终端信息域大小
+    uint8_t   bNum;       //帧序号
+    uint8_t   bNumCard;
+    uint8_t   bLink;      //指示数据是否有级联
+    uint8_t   bEDCType;   //
+    uint16_t  wtx;        //NC
+    uint8_t   bFlgSBSnd;  //S_BLOCK块标志
+    uint8_t   bFlgSRec;
+    uint8_t   bFlgIRec;
+    uint8_t   bRecRBLink;
+    uint8_t   bErrCnt;
+    uint8_t   bErrNotify;
+    uint8_t   bFlagSendChain;
+    uint8_t   aRBlk[5];
+    uint16_t  sendlen;
+    uint16_t  restlen;
+    uint8_t   resendflag;
+    uint8_t   IFS_issued;
+    uint16_t  reclen;
+    uint8_t   process;
+    uint8_t   r_cnt;
+    uint8_t   r_chain_cnt;
+    uint8_t	  state;
+} SCI_T1_Para_Type;
+
+//ATR等7816需要用的参数
+typedef struct
+{
+    uint8_t bFlag;                  //BIT0为1时表示收到TA1。BIT1 为1时表示热复位、为0时表示冷复位。BIT2为1时表示自动发送C0取响应帧。BIT3为1时，表示收到卡片的SW字节
+    uint8_t bTA1;                   //TA1的值
+    uint8_t bTA2;                   //TA2的值
+    uint8_t bTA2Flag;               //TA2是否存在标志
+    uint8_t bProlType;              //协议类型标志 0为T0  1为T1
+    uint8_t aAtr[ATR_SIZE_MAX];     //ATR缓存区
+    uint8_t aRecBuff[REC_SIZE_MAX]; //接收数据缓存区
+} SCI_ATR_Para_Type;
+
+//跟7816数据有关的参数
+typedef struct
+{
+    uint8_t  state;     //0-idle 1-start 2-finsh
+    uint8_t  step;      //0-5
+    uint16_t sw;
+    uint16_t expected_len;
+    uint16_t write_index;
+    uint16_t read_index;
+    uint8_t  data[256+10]; //rx buf
+}SCI_Data_Type;
+
+
+typedef struct
+{
+    MSCI0_Type*            SCIx7816;              //跟7816寄存器有关的参数
+    SCI_T1_Para_Type       g_T1;                   //跟T1有关的参数
+    SCI_ATR_Para_Type      g_7816Para;             //跟7816协议参数有关的参数
+    SCI_Tran_Status_Type   SCI_Tran_StateCB;       //跟7816状态有关的参数
+    SCI_Data_Type          SCI_Rec_Data, SCI_Send_Data; //跟7816数据有关的参数
+}SCI_Struct_Type;
+
+
+uint8_t ISO7816_Cold_Reset(SCI_Struct_Type* SCIx);
+void ISO7816_Init(SCI_Struct_Type* SCIx);
+void ISO7816_Warm_Reset(SCI_Struct_Type* SCIx);
+void ISO7816_Vcard_Control(uint8_t state);
+void ISO7816_Deactive(SCI_Struct_Type* SCIx);
+void ISO7816_Config_Mode_Fun(SCI_Struct_Type* SCIx);
+void ISO7816_Atr_Timer_Start(SCI_Struct_Type* SCIx);
+//void ISO7816_IRQ(SCI_Struct_Type* SCIx);
+
+//卡检测
+uint8_t ISO7816_Detect_Io_State(void);
+uint16_t ISO7816_LoopBack(SCI_Struct_Type *SCIx);
+uint16_t ISO7816_OperateSelect(uint8_t OperateMode, SCI_Struct_Type* SCIx);
+uint16_t ISO7816_GetAtr_IRQ(SCI_Struct_Type* SCIx,uint8_t *pAtr, uint8_t *pLength);
+uint16_t ISO7816_GetAtr_LOOP(SCI_Struct_Type* SCIx,uint8_t *pAtr, uint8_t *pLength);
+uint16_t ISO7816_DisposeATR(SCI_Struct_Type *SCIx,uint8_t *pATR, uint8_t ATRLen);
+uint16_t ISO7816_DisposePPS(SCI_Struct_Type *SCIx,uint8_t TA1);
+
+uint16_t ISO7816_TPDU_T1Send_LOOP(SCI_Struct_Type *SCIx , uint8_t *pCommand, uint16_t CommandLength, uint8_t Type);
+
+uint16_t ISO7816_Dispose_CMD_LOOP(SCI_Struct_Type *SCIx,uint8_t *pCmd, uint16_t CmdLen, uint8_t *pResp,  uint16_t *pRespLen);
+uint16_t ISO7816_Transceive_CMD(SCI_Struct_Type *SCIx,uint8_t *pCmd, uint16_t CmdLen, uint8_t *pResp,  uint16_t *pRespLen);
+
+void ISO7816_TXRX_TIME_Init(SCI_Struct_Type* SCIx7816);
+void ISO7816_TX_APDU_Config(SCI_Struct_Type* SCIx7816);
+void ISO7816_RX_APDU_Config(SCI_Struct_Type* SCIx7816,uint8_t rx_waterlevel);
+
+
+
+#endif	/* __YC_ISO7816_H__ */
Index: yc_7816_emv_L1/yc_7816.c
===================================================================
--- /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816.c	(nonexistent)
+++ /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816.c	(working copy)
@@ -0,0 +1,1787 @@
+/*
+File Name    : yc_iso7816.c
+Author       : Yichip
+Version      : V1.0TI
+Date         : 2022/08/03
+Description  : iso7816 4.3c or 4.3d encapsulation.
+*/
+
+#include"string.h"
+
+#include "yc_7816.h"
+#include "system.h"
+#include "yc_timer.h"
+#include "yc_sysctrl.h"
+#include "yc_7816_T1.h"
+#include "yc_7816_T0.h"
+#include "yc3122.h"
+
+#define SCI_RX_RESULT_IDLE	0
+#define SCI_TX_RESULT_IDLE	0XFF
+
+/* Exported functions -------------------------------------------------------*/
+
+/**
+  * @method  ISO7816_Init
+  * @brief  Init para
+  * @param  SCIx=SCI0/SCI1
+  * @retval None
+  */
+void ISO7816_Init(SCI_Struct_Type* SCIx)
+{
+    uint16_t buff_f[] = {372, 372, 558, 744, 1116, 1488, 1860, 0,0, 512, 768, 1024, 1536, 2048, 0, 0};
+    uint16_t buff_d[] = {0, 1, 2, 4, 8, 16, 32, 64,12, 20, 0, 0, 0, 0, 0, 0};
+    SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State = 0;
+    SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State = 0;
+    SCIx->SCI_Tran_StateCB.SCI_State = 0;            //0-rx 1-tx
+    SCIx->SCI_Tran_StateCB.SCI_RX_Result = 0;        //1-rec finsh
+    SCIx->SCI_Tran_StateCB.SCI_TX_Result = 0xff;     //0-send finsh
+    SCIx->SCI_Tran_StateCB.Card_Type = 0;         //0-T0  1-T1
+    SCIx->SCI_Tran_StateCB.T1_parity_flag = 0;
+    SCIx->SCI_Tran_StateCB.terminal_send_cwt = 12;
+    SCIx->SCI_Tran_StateCB.terminal_rec_cwt = 10086;
+    SCIx->SCI_Tran_StateCB.terminal_rec_bwt = 15380;
+    SCIx->SCI_Tran_StateCB.terminal_send_bgt = 26;
+    SCIx->SCI_Tran_StateCB.terminal_rec_bwt_atr = 0;
+    SCIx->SCI_Tran_StateCB.terminal_change_rec_bwt_num = 0;
+    SCIx->SCI_Tran_StateCB.atr_cwt_valid_flag = 0;
+    SCIx->SCI_Tran_StateCB.sci_atr_byte_parity = 0;
+    SCIx->SCI_Tran_StateCB.SCI_Rec_Data_Index = 0;
+    SCIx->SCI_Tran_StateCB.SCI_Process_Step = 0;
+    SCIx->SCI_Tran_StateCB.tpdu_t0_step = 0;
+    SCIx->SCI_Tran_StateCB.tpdu_t1_step = 0;
+    SCIx->SCI_Tran_StateCB.tpdu_t1_type = 0;
+    SCIx->SCI_Tran_StateCB.time3_cnt_last = 0;
+    SCIx->SCI_Tran_StateCB.time3_cnt_new = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_reset_l_flag = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rfb_overtime_falg = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rab_overtime_falg = 0;
+    SCIx->SCI_Tran_StateCB.contact_reset_l_cnt = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rfb_time_cnt = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rab_time_cnt = 0;
+    SCIx->SCI_Tran_StateCB.contact_over_time_cnt = 0;
+    SCIx->SCI_Tran_StateCB.SCI_Protocol_Step = 0;
+    memcpy(SCIx->SCI_Tran_StateCB.fi_table,buff_f,sizeof(buff_f));
+    memcpy(SCIx->SCI_Tran_StateCB.di_table,buff_d,sizeof(buff_d));
+
+}
+
+/**
+  * @method  ISO7816_Detect_Io_State
+  * @brief  Test whether the card is in place and the level of IO port is in place
+  * @param  None
+  * @retval 0 : Card in place
+  *         1 : Card not place
+  */
+uint8_t ISO7816_Detect_Io_State(void)
+{
+    return GPIO_ReadInputDataBit(SCI7816_DETECT_PORT, SCI7816_DETECT_IO_PIN);
+}
+
+/**
+  * @method  ISO7816_Card_In_Io_Filter
+  * @brief  crad in io filter
+  * @param  None
+  * @retval 0 : Card in place
+  *         1 : Card not place
+  *         2 ：Card shake
+  */
+static uint8_t ISO7816_Card_In_Io_Filter(void)
+{
+    uint8_t ret[2] = {0};
+
+    ret[0] = ISO7816_Detect_Io_State();
+    delay_ms(2);
+    ret[1] = ISO7816_Detect_Io_State();
+    if (ret[0] == ret[1])
+    {
+        return ret[0];
+    }
+
+    return 2;
+}
+
+/**
+  * @method  ISO7816_Vcard_Control
+  * @brief  Vcard control
+  * @param  state:  ISO7816_VCC_0V:   vcard off
+                    ISO7816_VCC_3V:   3 vcard
+                    ISO7816_VCC_1_8V: 1.8 vcard
+                    ISO7816_VCC_5V:   5 vcard
+  * @retval None
+  */
+void ISO7816_Vcard_Control(uint8_t state)
+{
+    if (state == ISO7816_VCC_3V)
+    {
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_OCP_EN = 1;
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_EN = 1;
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_VSEL = 1;
+    }
+    else if (state == ISO7816_VCC_1_8V)
+    {
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_OCP_EN = 1;
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_EN = 1;
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_VSEL = 0;
+
+    }
+    else if (state == ISO7816_VCC_5V)
+    {
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_OCP_EN = 1;
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_EN = 1;
+        ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_VSEL = 2;
+    }
+
+    else if (state == ISO7816_VCC_0V)
+    {
+      ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_OCP_EN = 0;
+      ANA_LDO_CLK->LDO_CTRL.bit.LDO_CARD_EN = 0;
+    }
+}
+
+/**
+  * @method  ISO7816_TXRX_TIME_Init
+  * @brief  Tx and rx time init
+  * @param  None
+  * @retval None
+  */
+void ISO7816_TXRX_TIME_Init(SCI_Struct_Type* SCIx)
+{
+    SCIx->SCIx7816->CTRL2.bit.BWT_ST = 1;
+    SCIx->SCIx7816->CTRL2.bit.CWT_ST = 1;
+    SCIx->SCIx7816->BWT_TO.reg = SCIx->SCI_Tran_StateCB.terminal_rec_bwt;
+    SCIx->SCIx7816->CWT_TO.reg = SCIx->SCI_Tran_StateCB.terminal_rec_cwt;
+    SCIx->SCIx7816->BGT.reg = SCIx->SCI_Tran_StateCB.terminal_send_bgt;
+    SCIx->SCIx7816->CWT.reg = SCIx->SCI_Tran_StateCB.terminal_send_cwt;
+}
+
+/**
+  * @method  ISO7816_Reg_Init
+  * @brief  Iso7816 reg init
+  * @param  None
+  * @retval None
+  */
+void ISO7816_Reg_Init(SCI_Struct_Type* SCIx)
+{
+    SCIx->SCIx7816->IE.reg = 0;
+    SCIx->SCIx7816->IS.reg = 0XFFFFFFFF;
+    SCIx->SCIx7816->IES.reg = 0XFFFFFFFF;
+    SCIx->SCIx7816->CTRL2.bit.BWTA_ST = 1;
+    SCIx->SCIx7816->CTRL2.bit.BWTA_SRT = 1;
+    SCIx->SCIx7816->CTRL2.bit.BWT_ST = 1;
+    SCIx->SCIx7816->CTRL2.bit.BWT_EN = 1;
+    SCIx->SCIx7816->CTRL2.bit.CWTA_SRT = 1;
+    SCIx->SCIx7816->CTRL2.bit.CWT_ST = 1;
+    SCIx->SCIx7816->CTRL2.bit.CWT_EN = 1;
+    SCIx->SCIx7816->CTRL2.bit.CWTC_DSA = 1;
+    SCIx->SCIx7816->CTRL2.bit.CWTS_SL = 1;
+    SCIx->SCIx7816->CTRL2.bit.BGTS_SL = 1;
+    SCIx->SCIx7816->CTRL2.bit.FST_W = 1;
+    SCIx->SCIx7816->CTRL2.bit.FST_EN = 1;
+
+#ifdef DEBUG_7816
+    MyPrintf("CTRL2 %08x \r\n", SCIx->SCIx7816->CTRL2.reg);
+#endif
+
+    SCIx->SCIx7816->CWT_TO.reg = 0XFFFFFFFF;
+    SCIx->SCIx7816->CWT_TO.reg = 0XFFFFFFFF;
+    SCIx->SCIx7816->BGT.reg = 0XFFFFFFFF;
+    SCIx->SCIx7816->CWT.reg = 0XFFFFFFFF;
+    SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL = 0;
+    SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL = RX_APDU_FIFO_WATERLEVER_VAL;
+}
+
+/**
+  * @method  ISO7816_RX_APDU_Config
+  * @brief  Iso7816 rx apdu waterlevel
+  * @param  state:  rx_waterlevel
+  * @retval None
+  */
+void ISO7816_RX_APDU_Config(SCI_Struct_Type* SCIx,uint8_t rx_waterlevel)
+{
+    SCIx->SCI_Tran_StateCB.SCI_State = 0;
+
+    SCIx->SCI_Tran_StateCB.SCI_RX_Result = 0;
+
+    SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &=~0x0f;
+    SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL = rx_waterlevel;
+    SCIx->SCIx7816->CTRL2.bit.RX_EN = 1;
+}
+
+/**
+  * @method  ISO7816_TX_First_Byte_Enable
+  * @brief  Iso7816 tx first byte enable
+  * @param  state:  rx_waterlevel
+  * @retval None
+  */
+void ISO7816_TX_First_Byte_Enable(SCI_Struct_Type* SCIx)
+{
+    SCIx->SCIx7816->CTRL2.bit.FST_RF = 1;
+}
+
+/**
+  * @method  ISO7816_TX_APDU_Config
+  * @brief  Iso7816 tx apdu config
+  * @param  None
+  * @retval None
+  */
+void ISO7816_TX_APDU_Config(SCI_Struct_Type* SCIx)
+{
+    SCIx->SCIx7816->CTRL2.bit.CWT_ST = 1;
+    SCIx->SCIx7816->IS.bit.CWT_TO = 1;
+    SCIx->SCIx7816->IES.bit.CWT_TO = 1;
+	SCIx->SCIx7816->CTRL2.bit.BWT_ST = 1;
+    SCIx->SCIx7816->IS.bit.BWT_TO = 1;
+    SCIx->SCIx7816->IES.bit.BWT_TO = 1;
+
+    SCIx->SCI_Tran_StateCB.SCI_State = 1;
+
+    SCIx->SCI_Tran_StateCB.SCI_TX_Result = 0xff;
+    SCIx->SCIx7816->CTRL2.bit.FST_RF = 1;
+
+    SCIx->SCIx7816->CTRL2.bit.TX_EN = 1;
+    SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &= ~0x0f;
+    SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL = TX_APDU_FIFO_WATERLEVER_VAL;
+}
+
+/**
+  * @method ISO7816_Deactive
+  * @brief  Power down the 7816 pin
+  * @param  None
+  * @retval None
+  */
+void ISO7816_Deactive(SCI_Struct_Type* SCIx)
+{
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        GPIO_Config(SCI7816_RESET_PORT, SCI7816_RESET_IO_PIN, OUTPUT_LOW);//RST
+        delay_ms(1);
+
+        GPIO_Config(SCI7816_CLK_PORT, SCI7816_CLK_IO_PIN, OUTPUT_LOW);//CLK
+        TIM_Cmd(MTIM, SCI7816_PWMClK4M_TIMX, DISABLE);
+
+        GPIO_Config(SCI7816_DATA_PORT, SCI7816_DATA_IO_PIN, OUTPUT_LOW);//IO
+
+        ISO7816_Vcard_Control(ISO7816_VCC_0V);
+    }
+    else
+    {
+        GPIO_Config(SCI17816_RESET_PORT, SCI17816_RESET_IO_PIN, OUTPUT_LOW);//RST
+        delay_ms(1);
+
+        GPIO_Config(SCI17816_CLK_PORT, SCI17816_CLK_IO_PIN, OUTPUT_LOW);//CLK
+        TIM_Cmd(MTIM, SCI17816_PWMClK4M_TIMX, DISABLE);
+
+        GPIO_Config(SCI17816_DATA_PORT, SCI17816_DATA_IO_PIN, OUTPUT_LOW);//IO
+
+        GPIO_Config(SCI17816_CARD1_EN_PORT, SCI17816_CARD1_EN_IO_PIN, OUTPUT_HIGH);
+    }
+
+    #ifdef DEBUG_7816
+    MyPrintf("SCI7816_RX_BWT_TIMEONT %08x= \r\n", SCIx->SCIx7816->BWT_TO.reg);
+    MyPrintf("SCI7816_RX_CWT_TIMEONT %08x= \r\n", SCIx->SCIx7816->CWT_TO.reg);
+    MyPrintf("SCI7816_SEND_BGT %08x= \r\n", SCIx->SCIx7816->BGT.reg);
+    MyPrintf("SCI7816_SEND_CWT %08x= \r\n", SCIx->SCIx7816->CWT.reg);
+
+    MyPrintf("terminal_rec_bwt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_rec_bwt);
+    MyPrintf("terminal_rec_cwt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_rec_cwt);
+    MyPrintf("terminal_send_bgt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_send_bgt);
+    MyPrintf("terminal_send_cwt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_send_cwt);
+
+    MyPrintf("power down\n");
+    #endif
+}
+
+/**
+  * @method  ISO7816_Timer_Enable
+  * @brief  iso7816 timer init
+  * @param  None
+  * @retval None
+  */
+static void ISO7816_Timer_Enable(TIM_NumTypeDef Timx, uint32_t TimerPeriod)
+{
+    TIM_InitTypeDef TIM_InitStruct;
+    TIM_InitStruct.period = TimerPeriod;
+    TIM_InitStruct.TIMx = Timx;
+    TIM_InitStruct.Auto_Reload = ENABLE;
+
+    /*timer core init*/
+    TIM_Init(MTIM, &TIM_InitStruct);
+
+    /*timer mode init*/
+    TIM_ModeConfig(MTIM, Timx, TIM_Mode_TIMER);
+
+    /*timer enable*/
+    TIM_Cmd(MTIM, Timx, ENABLE);
+}
+
+/**
+  * @method  ISO7816_Atr_Timer_Start
+  * @brief  Turn on the timer function (used to calculate the timeout of card reset)
+  * @param  None
+  * @retval None
+  */
+void ISO7816_Atr_Timer_Start(SCI_Struct_Type* SCIx)
+{
+    ISO7816_Timer_Enable(SCI7816_TIMX, SCI7816_TIMER_PERIOD);
+    SCIx->SCI_Tran_StateCB.contact_over_time_cnt = CONTACT_OVER_TIME_VAL * 24000000;
+}
+
+/**
+  * @method ISO7816_RecAtrBytes
+  * @brief  7816  receive data function
+  * @param  RxBuf: Receiving data storage unit
+  * @param  RxLen: Length of received data
+  * @retval OK:    0 on success
+  */
+uint16_t ISO7816_RecAtrBytes(SCI_Struct_Type* SCIx,uint8_t *RxBuf, uint16_t RxLen)
+{
+    uint16_t  RemainLen = 0;
+    uint16_t i = 0;
+    uint8_t waterlevel = 0;
+    uint16_t len = 0;
+    uint16_t index = 0;
+    uint16_t val = 0;
+    uint8_t rx_num = 0;
+
+    if ((!RxLen) || (NULL == RxBuf))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[0] = RxLen/0x100;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[1] = RxLen%0x100;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2] = 0;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3] = 0;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Result = 0;
+
+    if (RxLen >= 8)
+    {
+        waterlevel = 4;
+    }
+    else
+    {
+        waterlevel = RxLen;
+    }
+    ISO7816_RX_APDU_Config(SCIx,waterlevel);
+    do
+    {
+        if (SCIx->SCIx7816->IS.bit.RFIFO_HA == 1)
+        {
+            len = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[0] * 0x100 + SCIx->SCI_Tran_StateCB.SCI_RX_Buf[1];
+            index = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2] * 0x100 + SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3];
+
+            rx_num = SCIx->SCIx7816->FIFO_CTRL.bit.R_ITEMS;
+            if (len > index)
+            {
+                val = len - index;
+                if (val <= rx_num)
+                {
+                    for (i = 0; i < val; i++)
+                    {
+                        SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4 + index++] = SCIx->SCIx7816->DATA.reg;
+                    }
+                }
+                else
+                {
+                    for (i = 0; i < rx_num; i++)
+                    {
+                        SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4 + index++] = SCIx->SCIx7816->DATA.reg;
+                    }
+                }
+            }
+
+            if (index >= len)
+            {
+                SCIx->SCI_Tran_StateCB.SCI_RX_Result = 1;  //rec finsh
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &= ~0x0f;
+                SCIx->SCIx7816->IS.bit.RFIFO_HA = 1;
+            }
+            else if (((len - index) > 0) && ((len - index) < 4))
+            {
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &= ~0x0f;
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL = (len - index);
+            }
+
+            SCIx->SCIx7816->IS.bit.RFIFO_HA = 1;
+            SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2] = index / 0x100;
+            SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3] = index % 0x100;
+        }
+
+
+        if ((SCIx->SCIx7816->IS.bit.CWT_TO == 1) || (SCIx->SCIx7816->IS.bit.BWT_TO == 1))
+        {
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_REC_TIMEOUT;
+            SCIx->SCIx7816->IS.bit.CWT_TO = 1;
+            SCIx->SCIx7816->IS.bit.BWT_TO = 1;
+        }
+        if ((SCIx->SCIx7816->IS.bit.R_ERR == 1) && (SCIx->SCI_Tran_StateCB.Card_Type == 0))
+        {
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_ERR_NUM_OVER;
+            SCIx->SCIx7816->IS.bit.R_ERR = 1;
+        }
+        if ((SCIx->SCIx7816->IS.bit.R_ERR == 1) && (SCIx->SCI_Tran_StateCB.Card_Type == 1))
+        {
+            SCIx->SCI_Tran_StateCB.T1_parity_flag = 1;
+            SCIx->SCIx7816->IS.bit.R_ERR = 1;
+        }
+        if (SCIx->SCIx7816->IS.bit.RFIFO_OVF == 1)
+        {
+#ifdef DEBUG_7816_FPGA
+            MyPrintf("sci isr %08x \r\n", SCIx->SCIx7816->IS.reg);
+#endif
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_ERR_NUM_OVER;
+
+            SCIx->SCIx7816->IS.bit.RFIFO_OVF = 1;
+        }
+        if ((SCIx->SCIx7816->IS.bit.TFIFO_OVF == 1) | (SCIx->SCIx7816->IS.bit.TFIFO_LA == 1)  \
+                | (SCIx->SCIx7816->IS.bit.T_ERR == 1) | (SCIx->SCIx7816->IS.bit.T_DONE == 1))
+        {
+#ifdef DEBUG_7816_FPGA
+            MyPrintf("irq_SCI_State %08x \r\n", SCIx->SCI_Tran_StateCB.SCI_State);
+            MyPrintf("irq_sci isr= %08x \r\n", SCIx->SCIx7816->IS.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IE.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IES.reg);
+            MyPrintf("irq_sci ctrl2= %08x \r\n", SCIx->SCIx7816->CTRL2.reg);
+#endif
+            SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &= ~0x0f;
+            SCIx->SCIx7816->IS.reg = 0XFFFFFFFF;
+        }
+        if (SCIx->SCI_Tran_StateCB.SCI_RX_Result == 1)
+        {
+            for (i=0; i<RxLen; i++)
+            {
+                *RxBuf++ = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4+i];
+            }
+
+            RemainLen = RxLen;
+        }
+        else if (SCIx->SCI_Tran_StateCB.SCI_RX_Result > 1)
+        {
+            return SCIx->SCI_Tran_StateCB.SCI_RX_Result;
+        }
+
+        if (ISO7816_Detect_Io_State() == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+        {
+            return ISO7816_CARD_ABSENT;
+        }
+
+        if (SCIx->SCI_Tran_StateCB.contact_atr_rfb_overtime_falg == 0)
+        {
+            SCIx->SCI_Tran_StateCB.time3_cnt_new = SCI7816_TIMX_CNT;
+            SCIx->SCI_Tran_StateCB.time3_cnt_new = SCIx->SCI_Tran_StateCB.time3_cnt_last - SCIx->SCI_Tran_StateCB.time3_cnt_new;
+            if (SCIx->SCI_Tran_StateCB.time3_cnt_new >= CONTACT_ATR_RFB_TIME_CNT) //icc not response atr
+            {
+                #ifdef DEBUG_7816
+                MyPrintf("receive atr firstbyte overtime %d\n", CONTACT_ATR_RFB_TIME_CNT);
+                #endif
+                return ISO7816_REC_TIMEOUT;
+            }
+        }
+
+        if (SCIx->SCI_Tran_StateCB.contact_atr_rab_overtime_falg == 0)
+        {
+        SCIx->SCI_Tran_StateCB.time3_cnt_new = SCI7816_TIMX_CNT;
+            SCIx->SCI_Tran_StateCB.time3_cnt_new = SCIx->SCI_Tran_StateCB.time3_cnt_last - SCIx->SCI_Tran_StateCB.time3_cnt_new;
+            if (SCIx->SCI_Tran_StateCB.time3_cnt_new >= CONTACT_ATR_RAB_TIME_CNT) //icc response atr overtime
+            {
+                #ifdef DEBUG_7816
+                MyPrintf("receive atr allbyte overtime\n");
+                #endif
+                return ISO7816_REC_TIMEOUT;
+            }
+        }
+    }
+    while (RemainLen < RxLen);
+
+    return OK;
+}
+
+/**
+  * @method  ISO7816_Gpio_Reset
+  * @brief  reset gpio
+  * @param  None
+  * @retval None
+  */
+static void ISO7816_Gpio_Reset(SCI_Struct_Type* SCIx)
+{
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        GPIO_Config(SCI7816_CLK_PORT, SCI7816_CLK_IO_PIN, OUTPUT_LOW); //clk
+        GPIO_Config(SCI7816_RESET_PORT, SCI7816_RESET_IO_PIN, OUTPUT_LOW); //reset
+        GPIO_Config(SCI7816_DATA_PORT, SCI7816_DATA_IO_PIN, OUTPUT_LOW); //io
+    }
+    else
+    {
+        GPIO_Config(SCI17816_CLK_PORT, SCI17816_CLK_IO_PIN, OUTPUT_LOW); //clk
+        GPIO_Config(SCI17816_RESET_PORT, SCI17816_RESET_IO_PIN, OUTPUT_LOW); //reset
+        GPIO_Config(SCI17816_DATA_PORT, SCI17816_DATA_IO_PIN, OUTPUT_LOW); //io
+    }
+}
+
+/**
+  * @method  ISO7816_PwmClkNM_Init
+  * @brief  reset gpio
+  * @param  None
+  * @retval None
+  */
+static void ISO7816_PwmClkNM_Init(SCI_Struct_Type* SCIx)
+{
+    /*get pclk clock*/
+    uint32_t PllClockFreq = SYSCTRL_GetClocksFreq(PCLK_FRE);
+
+    uint32_t HighLevelPeriod = 0;
+    uint32_t LowLevelPeriod = 0;
+
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        HighLevelPeriod = ((PllClockFreq/SCI7816_PWM4M_PERIOD)- 1);
+        LowLevelPeriod = HighLevelPeriod;
+
+        if((PllClockFreq % SCI7816_PWM4M_PERIOD) != 0)
+        {
+            HighLevelPeriod += 1;
+        }
+
+        PWM_InitTypeDef PWM_InitStruct;
+        PWM_InitStruct.HighLevelPeriod = HighLevelPeriod;
+        PWM_InitStruct.LowLevelPeriod  = LowLevelPeriod ;
+        PWM_InitStruct.StartLevel      = HIGH_LEVEL;
+        PWM_InitStruct.TIMx = SCI7816_PWMClK4M_TIMX;
+        TIM_PWMInit(MTIM, &PWM_InitStruct);
+        TIM_ModeConfig(MTIM, SCI7816_PWMClK4M_TIMX, TIM_Mode_PWM);
+        TIM_Cmd(MTIM, SCI7816_PWMClK4M_TIMX, ENABLE);
+
+        /*pwm io init*/
+        GPIO_Config(SCI7816_CLK_PORT, SCI7816_CLK_IO_PIN, PWM_OUT);
+    }
+    else
+    {
+        HighLevelPeriod = ((PllClockFreq/SCI7816_PWM4M_PERIOD)- 1);
+        LowLevelPeriod = HighLevelPeriod;
+
+        if((PllClockFreq % SCI7816_PWM4M_PERIOD) != 0)
+        {
+            HighLevelPeriod += 1;
+        }
+
+        PWM_InitTypeDef PWM_InitStruct;
+        PWM_InitStruct.HighLevelPeriod = HighLevelPeriod;
+        PWM_InitStruct.LowLevelPeriod  = LowLevelPeriod ;
+        PWM_InitStruct.StartLevel      = HIGH_LEVEL;
+        PWM_InitStruct.TIMx = SCI17816_PWMClK4M_TIMX;
+        TIM_PWMInit(MTIM, &PWM_InitStruct);
+        TIM_ModeConfig(MTIM, SCI17816_PWMClK4M_TIMX, TIM_Mode_PWM);
+        TIM_Cmd(MTIM, SCI17816_PWMClK4M_TIMX, ENABLE);
+
+        /*pwm io init*/
+        GPIO_Config(SCI17816_CLK_PORT, SCI17816_CLK_IO_PIN, PWM_OUT);
+
+    }
+}
+
+/**
+  * @method  ISO7816_Cold_Reset
+  * @brief  7816 cold reset function
+  * @param  state: VCard voltage setting
+  * @retval OK:    0 on success
+  */
+uint8_t ISO7816_Cold_Reset(SCI_Struct_Type* SCIx)
+{
+    uint8_t TempChar;
+    uint16_t fi_table_1[16] = {372, 372, 558, 744, 1116, 1488, 1860, 0,
+                                0, 512, 768, 1024, 1536, 2048, 0, 0
+                                };
+    uint16_t di_table_1[16] = {0, 1, 2, 4, 8, 16, 32, 64,
+                                12, 20, 0, 0, 0, 0, 0, 0
+                                };
+
+#ifdef DEBUG_7816
+    MyPrintf("sci7816 cold reset\n");
+#endif
+
+    memcpy(SCIx->SCI_Tran_StateCB.fi_table, fi_table_1, 16);
+    memcpy(SCIx->SCI_Tran_StateCB.di_table, di_table_1, 16);
+
+    SCIx->SCI_Tran_StateCB.terminal_send_cwt = 20;
+    SCIx->SCI_Tran_StateCB.terminal_rec_cwt = 10086;               //当atr第一个字节在10080个etu回复时，6个dummy
+    SCIx->SCI_Tran_StateCB.terminal_rec_bwt = 15380;
+
+    SCIx->SCI_Tran_StateCB.terminal_send_bgt = 26;
+
+    SCIx->g_7816Para.bTA1 = 0xff;
+    SCIx->g_7816Para.bTA2 = 0xFF;
+    SCIx->g_7816Para.bTA2Flag = 0;
+    SCIx->g_7816Para.bFlag = 0;
+
+    SCIx->SCI_Tran_StateCB.contact_atr_reset_l_flag = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rfb_overtime_falg = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rab_overtime_falg = 0;
+
+    SCIx->SCI_Tran_StateCB.atr_cwt_valid_flag = 0;
+
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        MRSTGEN->RESET.bit.RESET = 0xab;  //oxf857c，此寄存器是YSCTRL_RESET，写入oxab，触发sci0复位
+    }
+    else
+    {
+        MRSTGEN->RESET.bit.RESET = 0xae;  //oxf857c，此寄存器是YSCTRL_RESET，写入oxae，触发sci1复位
+    }
+
+    SCIx->SCIx7816->CTRL.bit.RFIFO_CL = 1;
+    SCIx->SCIx7816->CTRL.bit.TFIFO_CL = 1;
+
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+         ISO7816_Vcard_Control(ISO7816_VCC_0V);  //CARD0 供电
+    }
+    else
+    {
+        GPIO_Config(SCI17816_CARD1_EN_PORT, SCI17816_CARD1_EN_IO_PIN, OUTPUT_HIGH); //CARD1 供电
+    }
+
+    ISO7816_Gpio_Reset(SCIx);
+
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+         ISO7816_Vcard_Control(ISO7816_VCC_3V); //CARD0 VCC
+    }
+    else
+    {
+        GPIO_Config(SCI17816_CARD1_EN_PORT, SCI17816_CARD1_EN_IO_PIN, OUTPUT_LOW); //CARD1 VCC
+    }
+
+
+    delay_ms(10);
+
+    ISO7816_Reg_Init(SCIx);
+
+    ISO7816_PwmClkNM_Init(SCIx);
+
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        /*data io init*/
+        GPIO_Config(SCI7816_DATA_PORT, SCI7816_DATA_IO_PIN, SCI7816_IO|PULL_PU);
+    }
+    else
+    {
+        GPIO_Config(SCI17816_DATA_PORT, SCI17816_DATA_IO_PIN, SCI7816_IO2|PULL_PU);
+    }
+
+    while ((SCIx->SCIx7816->STATUS.bit.RFIFO_N & 1) || (SCIx->SCIx7816->FIFO_CTRL.bit.R_ITEMS & 0xf))
+    {
+        TempChar = SCIx->SCIx7816->DATA.bit.VAL;
+        MyPrintf("%02x", TempChar);
+        MyPrintf("\n");
+
+        if (ISO7816_Detect_Io_State() == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+        {
+            return ISO7816_CARD_ABSENT;
+        }
+    }
+
+    //check atr first byte and tx/rx fifo
+    SCIx->SCIx7816->CTRL.bit.RFIFO_CL = 1;
+    SCIx->SCIx7816->CTRL.bit.TS_TEST = 1;
+    SCIx->SCIx7816->CTRL.bit.TFIFO_CL = 1;
+    SCIx->SCIx7816->STATUS.bit.RET_CHK = 1;//clear tx/rx retry error
+    SCIx->SCIx7816->STATUS.bit.PRT_CHK = 1;
+    SCIx->SCIx7816->STATUS.bit.CHK_BIT = 1;
+
+    //clk
+    //delay 40000-45000clk  (250ns*42000clk = 10.5ms)
+    SCIx->SCI_Tran_StateCB.time3_cnt_last = SCI7816_TIMX_CNT;
+    SCIx->SCI_Tran_StateCB.time3_cnt_new = 0;
+    while (SCIx->SCI_Tran_StateCB.time3_cnt_new <= CONTACT_RESET_L_CNT)
+    {
+        SCIx->SCI_Tran_StateCB.time3_cnt_new = SCI7816_TIMX_CNT;
+        SCIx->SCI_Tran_StateCB.time3_cnt_new = SCIx->SCI_Tran_StateCB.time3_cnt_last - SCIx->SCI_Tran_StateCB.time3_cnt_new;
+    }
+
+    //config sci7816 tmode bit=1 实现ATR发送字节校验位错误时只要判断出检验错误即可，不需要将IO拉低
+    SCIx->SCIx7816->MODE.bit.ETU_NUM = 0;
+    SCIx->SCIx7816->MODE.bit.MST_EN = 1;
+    SCIx->SCIx7816->MODE.bit.BGT_EN = 1;
+    SCIx->SCIx7816->MODE.bit.CWT_EN = 1;
+    SCIx->SCIx7816->MODE.bit.EDC_EN = 1;
+    SCIx->SCIx7816->MODE.bit.EN = 1;
+    SCIx->SCIx7816->MODE.bit.TPS = 1;
+    SCIx->SCIx7816->ETU.bit.VAL = 372;
+
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        SCIx->SCIx7816->MODE.bit.CLK_SEL = SCI7816_PWMClK4M_TIMX; //SCI时钟源  TIMx
+    }
+    else
+    {
+        SCIx->SCIx7816->MODE.bit.CLK_SEL = SCI17816_PWMClK4M_TIMX; //SCI时钟源  TIMx
+    }
+    ISO7816_TXRX_TIME_Init(SCIx);
+
+
+    ISO7816_RX_APDU_Config(SCIx,1);
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        //rst disable
+       GPIO_Config(SCI7816_RESET_PORT, SCI7816_RESET_IO_PIN, OUTPUT_HIGH); //reset
+    }
+    else
+    {
+        GPIO_Config(SCI17816_RESET_PORT, SCI17816_RESET_IO_PIN, OUTPUT_HIGH); //reset
+    }
+
+    //icc response atr firstbyte max time 42020 clk
+    SCIx->SCI_Tran_StateCB.time3_cnt_last = SCI7816_TIMX_CNT;
+    SCIx->SCI_Tran_StateCB.contact_atr_rfb_overtime_falg = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rab_overtime_falg = 1;
+
+    return  OK;
+}
+
+/**
+  * @method ISO7816_Warm_Reset
+  * @brief  7816 warm reset function
+  * @param  None
+  * @retval None
+  */
+void ISO7816_Warm_Reset(SCI_Struct_Type* SCIx)
+{
+#ifdef DEBUG_7816
+    MyPrintf("sci7816 warm reset\n");
+#endif
+
+    SCIx->g_7816Para.bTA1 = 0xff;
+    SCIx->g_7816Para.bTA2 = 0xFF;
+    SCIx->g_7816Para.bTA2Flag = 0;
+
+    SCIx->SCI_Tran_StateCB.atr_cwt_valid_flag = 0;
+
+    ISO7816_Reg_Init(SCIx);
+
+    //check atr first byte and tx/rx fifo
+    SCIx->SCIx7816->CTRL.bit.RFIFO_CL = 1;
+    SCIx->SCIx7816->CTRL.bit.TS_TEST = 1;
+    SCIx->SCIx7816->CTRL.bit.TFIFO_CL = 1;
+    SCIx->SCIx7816->STATUS.bit.RET_CHK = 1;//clear tx/rx retry error
+    SCIx->SCIx7816->STATUS.bit.PRT_CHK = 1;
+    SCIx->SCIx7816->STATUS.bit.CHK_BIT = 1;
+
+
+    //config sci7816 tmode bit=1 实现ATR发送字节校验位错误时只要判断出检验错误即可，不需要将IO拉低
+    SCIx->SCIx7816->MODE.bit.ETU_NUM = 0;
+    SCIx->SCIx7816->MODE.bit.MST_EN = 1;
+    SCIx->SCIx7816->MODE.bit.BGT_EN = 1;
+    SCIx->SCIx7816->MODE.bit.CWT_EN = 1;
+    SCIx->SCIx7816->MODE.bit.EDC_EN = 1;
+    SCIx->SCIx7816->MODE.bit.EN = 1;
+    SCIx->SCIx7816->MODE.bit.TPS = 1;
+
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        SCIx->SCIx7816->MODE.bit.CLK_SEL = SCI7816_PWMClK4M_TIMX; //SCI时钟源  TIMx
+        GPIO_Config(SCI7816_RESET_PORT, SCI7816_RESET_IO_PIN, OUTPUT_LOW); //reset
+    }
+    else
+    {
+        SCIx->SCIx7816->MODE.bit.CLK_SEL = SCI17816_PWMClK4M_TIMX; //SCI时钟源  TIMx
+        GPIO_Config(SCI17816_RESET_PORT, SCI17816_RESET_IO_PIN, OUTPUT_LOW); //reset
+    }
+
+
+    //delay 40000-45000clk  (250ns*42000clk = 10.5ms)
+    SCIx->SCI_Tran_StateCB.time3_cnt_last = SCI7816_TIMX_CNT;
+    SCIx->SCI_Tran_StateCB.time3_cnt_new = 0;
+    while (SCIx->SCI_Tran_StateCB.time3_cnt_new <= CONTACT_RESET_L_CNT)
+    {
+        SCIx->SCI_Tran_StateCB.time3_cnt_new = SCI7816_TIMX_CNT;
+        SCIx->SCI_Tran_StateCB.time3_cnt_new = SCIx->SCI_Tran_StateCB.time3_cnt_last - SCIx->SCI_Tran_StateCB.time3_cnt_new;
+    }
+
+    ISO7816_TXRX_TIME_Init(SCIx);
+
+    ISO7816_RX_APDU_Config(SCIx,1);
+    if(SCIx->SCIx7816 == MSCI0)
+    {
+        GPIO_Config(SCI7816_RESET_PORT, SCI7816_RESET_IO_PIN, OUTPUT_HIGH); //reset
+    }
+    else
+    {
+        GPIO_Config(SCI17816_RESET_PORT, SCI17816_RESET_IO_PIN, OUTPUT_HIGH); //reset
+    }
+
+    //icc response atr firstbyte max time 42020 clk
+    SCIx->SCI_Tran_StateCB.time3_cnt_last = SCI7816_TIMX_CNT;
+    SCIx->SCI_Tran_StateCB.contact_atr_rfb_overtime_falg = 0;
+    SCIx->SCI_Tran_StateCB.contact_atr_rab_overtime_falg = 1;
+}
+
+/**
+  * @method ISO7816_Config_Mode_Fun
+  * @brief  Set the card type to T0 or T1 card
+  * @param  None
+  * @retval None
+  */
+void ISO7816_Config_Mode_Fun(SCI_Struct_Type* SCIx)
+{
+    if (SCIx->g_7816Para.bProlType == PROTOCOL_T0)
+    {
+        SCIx->SCIx7816->MODE.bit.RET_EN = 1;
+        SCIx->SCIx7816->MODE.bit.RET_TIME = 4;
+        SCIx->SCIx7816->MODE.bit.TPS &=~1;
+        SCIx->SCI_Tran_StateCB.Card_Type = 0;
+
+    }
+    else
+    {
+        SCIx->SCIx7816->MODE.bit.TPS = 1;
+        SCIx->SCI_Tran_StateCB.Card_Type = 1;
+
+    }
+}
+
+/**
+  * @method ISO7816_GetAtr_LOOP
+  * @brief  Receive reset information
+  * @param  pAtr:    ATR data storage unit
+  * @param  pLength: ATR data length
+  * @retval OK:      0 on success
+  */
+uint16_t ISO7816_GetAtr_LOOP(SCI_Struct_Type* SCIx,uint8_t *pAtr, uint8_t *pLength)
+{
+    uint8_t i;
+    uint8_t Len, Y, K, Tck;
+    uint16_t ret;
+    uint8_t TDn = 0;
+    uint8_t TD2Flag = 0;
+
+    if ((NULL == pAtr) || (NULL == pLength))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    ret = ISO7816_RecAtrBytes(SCIx,pAtr, 1);  //Ts
+
+    if (OK != ret)
+    {
+        #ifdef DEBUG_7816_EMV
+        MyPrintf("rec atr erro %2x\r\n",ret);
+        #endif
+        return ret;
+    }
+
+    SCIx->SCIx7816->CTRL.reg &= 0XFB;
+
+    if ((pAtr[0] != 0x3b) && (pAtr[0] != 0x3f))
+    {
+        if (pAtr[0] == 0x23)
+        {
+            SCIx->SCIx7816->MODE.bit.CODE_DRT =0; //正向卡片
+        }
+        else if (pAtr[0] == 0x03)
+        {
+            SCIx->SCIx7816->MODE.bit.CODE_DRT =1; //反向卡片
+        }
+        else
+        {
+            return ISO7816_ATR_ERROR;
+        }
+    }
+
+    SCIx->SCI_Tran_StateCB.contact_atr_rfb_overtime_falg = 1;
+    SCIx->SCI_Tran_StateCB.time3_cnt_last = SCI7816_TIMX_CNT;
+    SCIx->SCI_Tran_StateCB.contact_atr_rab_overtime_falg = 0;
+    SCIx->SCI_Tran_StateCB.atr_cwt_valid_flag = 1;
+
+    ret = ISO7816_RecAtrBytes(SCIx,pAtr + 1, 1); //T0
+    COMPARE_RETURN(ret);
+
+    Y = pAtr[1] & 0xF0;
+    K = pAtr[1] & 0x0F;
+    Len = 2;
+    SCIx->g_7816Para.bProlType = 0xff;
+    while (Y)
+    {
+        TDn++;
+        if (Y & BIT4)
+        {
+            ret = ISO7816_RecAtrBytes(SCIx,&pAtr[Len++], 1);
+            COMPARE_RETURN(ret);
+        }
+        if (Y & BIT5)
+        {
+            ret = ISO7816_RecAtrBytes(SCIx,&pAtr[Len++], 1);
+            COMPARE_RETURN(ret);
+        }
+        if (Y & BIT6)
+        {
+            ret = ISO7816_RecAtrBytes(SCIx,&pAtr[Len++], 1);
+            COMPARE_RETURN(ret);
+        }
+        if (Y & BIT7)
+        {
+            ret = ISO7816_RecAtrBytes(SCIx,&pAtr[Len], 1);
+            COMPARE_RETURN(ret);
+            Y = pAtr[Len] & 0xF0;
+            if (SCIx->g_7816Para.bProlType == 0xff)
+            {
+                SCIx->g_7816Para.bProlType = pAtr[Len] & 0x0F;
+                if (1 < SCIx->g_7816Para.bProlType)
+                {
+                    //如果协议大于1，默认为0
+                    SCIx->g_7816Para.bProlType = 0;
+                }
+            }
+            //TD2存在，并且值为1 或 E
+            if (TDn == 2) /*&& (((pAtr[Len] & 0x0F) == 1) || ((pAtr[Len] & 0x0F) == 14))*/
+            {
+                TD2Flag = 1;
+            }
+
+            Len++;
+        }
+        else
+        {
+            Y = 0;
+        }
+    }
+
+    //如果协议没有修改，默认为0
+    if (SCIx->g_7816Para.bProlType == 0xff)
+    {
+        SCIx->g_7816Para.bProlType = 0;
+    }
+
+    if (K)
+    {
+        ret = ISO7816_RecAtrBytes(SCIx,&pAtr[Len], K);
+        COMPARE_RETURN(ret);
+        Len += K;
+    }
+
+    if (SCIx->g_7816Para.bProlType || (TD2Flag == 1))
+    {
+        ret = ISO7816_RecAtrBytes(SCIx,&pAtr[Len], 1);
+        COMPARE_RETURN(ret);
+        Len++;
+    }
+
+    if ((ATR_SIZE_MAX - 1) < Len)
+    {
+        return ISO7816_ATR_LEN_ERROR;
+    }
+    if (SCIx->g_7816Para.bProlType)
+    {
+        for (i = 1, Tck = 0; i < Len; i++)
+        {
+            Tck ^= pAtr[i];
+        }
+        if (Tck)
+        {
+            return ISO7816_ATR_TCK_ERROR;
+        }
+    }
+
+    *pLength = Len;
+
+    //判断Rx Fifo 中是否还有数据，如果有的话，直接Warmrest
+    delay_ms(6);
+    i = 3;
+    ret = 0;
+    do
+    {
+        while ((SCIx->SCIx7816->STATUS.bit.RFIFO_N & 1) || (SCIx->SCIx7816->FIFO_CTRL.bit.R_ITEMS))
+        {
+            ret = 1;
+            ISO7816_RecAtrBytes(SCIx,&pAtr[Len], 1);
+
+            if (ISO7816_Detect_Io_State() == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+            {
+                return ISO7816_CARD_ABSENT;
+            }
+        }
+        if (ret == 1)
+        {
+            return ISO7816_ATR_LEN_ERROR;
+        }
+
+    }
+    while (i--);
+
+    return OK;
+}
+
+/**
+  * @method  ISO7816_DisposeATR
+  * @brief  Processing ATR data
+  * @param  pATR:    ATR data storage unit
+  * @param  ATRLen:  ATR data length
+  * @retval OK:      0 on success
+  */
+uint16_t ISO7816_DisposeATR(SCI_Struct_Type *SCIx,uint8_t *pATR, uint8_t ATRLen)
+{
+    uint8_t tmpLen;
+    uint8_t tmpTDx;
+    uint8_t offset;
+    uint32_t tmpTimer;
+    uint8_t TC1_N = 0;
+    uint8_t TD1_N = 0, TD1_Flag = 0;
+    uint8_t tmpCWI, tmpBWI;
+
+    //IFSC IC卡信息域大小 默认值32
+    SCIx->g_T1.bIFSC = 32;
+    SCIx->g_7816Para.bFlag &= (~BIT0);
+    if ((pATR == NULL) || (ATRLen < 3) || (ATRLen > ATR_SIZE_MAX))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    tmpTDx = pATR[1] & 0xF0;   //高4位
+
+    offset = 2;
+    //TA1--TD1
+    //TA1   BIT4
+    if ((tmpTDx & BIT4) != 0)
+    {
+        offset++;
+        SCIx->g_7816Para.bFlag |= BIT0;  //BIT0为1时表示收到TA1
+        SCIx->g_7816Para.bTA1 = pATR[2];
+
+        if ((SCIx->g_7816Para.bTA1 != 0x11) && (SCIx->g_7816Para.bTA1 != 0x12) && (SCIx->g_7816Para.bTA1 != 0x13))
+        {
+            //不发PPS
+            //return ISO7816_ATR_TA1_ERROR;
+        }
+    }
+    //TB1
+    if ((tmpTDx & BIT5) != 0)
+    {
+        //如果是冷复位，必须要有TB1,并且值为0
+        if (((SCIx->g_7816Para.bFlag & BIT1) == 0) && (pATR[offset]) != 0)
+        {
+			#ifndef EMV_L1_43D
+            return ISO7816_ATR_TB1_ERROR;
+			#endif
+        }
+        offset++;
+    }
+    else
+    {
+        //如果是冷复位，必须要有TB1
+        if ((SCIx->g_7816Para.bFlag & BIT1) == 0)
+        {
+			#ifndef EMV_L1_43D
+            return ISO7816_ATR_TB1_ERROR;
+			#endif
+        }
+    }
+
+    //TC1
+    if ((tmpTDx & BIT6) != 0)
+    {
+        if (pATR[offset] == 0xFF)
+        {
+            if (SCIx->g_7816Para.bProlType == 1)   //T1
+            {
+                SCIx->SCI_Tran_StateCB.terminal_send_cwt = 12;
+            }
+            else//T0
+            {
+                SCIx->SCI_Tran_StateCB.terminal_send_cwt = 12;
+            }
+        }
+        else
+        {
+            SCIx->SCI_Tran_StateCB.terminal_send_cwt = pATR[offset] + 12;
+        }
+        //保存N值，后面会用到
+        TC1_N = pATR[offset];
+        //TC1_Flag = 1;
+        offset++;
+    }
+    else
+    {
+        if (SCIx->g_7816Para.bProlType == 1)
+        {
+            SCIx->SCI_Tran_StateCB.terminal_send_cwt = 12;
+        }
+        else//T0
+        {
+            SCIx->SCI_Tran_StateCB.terminal_send_cwt = 12;
+        }
+    }
+
+
+    //TD1
+    if ((tmpTDx & BIT7) != 0)
+    {
+        //只支持T=0  T=1
+        TD1_N = pATR[offset];
+        if ((TD1_N & 0x0F) == 1)
+        {
+            TD1_Flag = 1;
+        }
+        SCIx->g_7816Para.bProlType = pATR[offset] & 0x0f;
+        tmpTDx = pATR[offset];
+        offset++;
+    }
+    else
+    {
+        tmpTDx = 0;
+        SCIx->g_7816Para.bTA1 = 0x11;
+    }
+
+    //TA2-TD2
+    if (tmpTDx != 0)
+    {
+        //TA2
+        if ((tmpTDx & BIT4) != 0)
+        {
+            SCIx->g_7816Para.bTA2Flag = 1;
+            SCIx->g_7816Para.bTA2 = pATR[offset];
+            if ((pATR[offset] & 0x10) != 0)  //b5
+            {
+                return ISO7816_ATR_TA2_ERROR;
+            }
+            offset++;
+
+            tmpTimer = 10080;
+            if ((SCIx->g_7816Para.bFlag & BIT0) && (SCIx->g_7816Para.bTA1 != 0x11))
+            {
+                if ((SCIx->g_7816Para.bTA1 & 0xF) > 1)
+                {
+                    tmpTimer *= SCIx->SCI_Tran_StateCB.di_table[SCIx->g_7816Para.bTA1 & 0xF];  // * DI
+
+                    if ((SCIx->g_7816Para.bTA1 & 0x0f) == 3)
+                    {
+                        //tmpTimer += 20;
+                    }
+                }
+                //多加2个ETU
+                //tmpTimer += 20;
+                //如果没有超限，设置WT时间
+                SCIx->SCI_Tran_StateCB.terminal_rec_cwt = tmpTimer;
+            }
+        }
+        else
+        {
+            SCIx->g_7816Para.bTA1 = 0x11;
+        }
+        //TB2
+        if ((tmpTDx & BIT5) != 0)
+        {
+            #ifndef EMV_L1_43D
+                return ISO7816_ATR_TB2_ERROR;
+            #else
+                if (pATR[offset] == 0x31)
+                {
+                    return ISO7816_ATR_TB2_ERROR;
+                }
+                offset++;
+            #endif
+        }
+
+        //TC2
+        if ((tmpTDx & BIT6) != 0)       //专用T=0协议 WI
+        {
+            if (SCIx->g_7816Para.bProlType == PROTOCOL_T0)
+            {
+                //TC2只支持10
+                if (10 != pATR[offset])
+                {
+                    return ISO7816_ATR_TC2_ERROR;
+                }
+                else
+                {
+                    tmpTimer = 960 *  pATR[offset] + 480;   //默认9600 + 480
+                    if (SCIx->g_7816Para.bFlag & BIT0)
+                    {
+                        tmpTimer *= SCIx->SCI_Tran_StateCB.di_table[SCIx->g_7816Para.bTA1 & 0xF];  // * DI
+                    }
+                    SCIx->SCI_Tran_StateCB.terminal_rec_cwt = tmpTimer;
+                }
+            }
+            offset++;
+        }
+        //TD2
+        if ((tmpTDx & BIT7) != 0)
+        {
+            //TD1指明了T=1协议，TD2不支持 T=1的话报错。
+            if (TD1_Flag)
+            {
+                if ((pATR[offset] & 0x0f) != 1)
+                {
+                    return ISO7816_ATR_TD2_ERROR;
+                }
+            }
+            //支持T=1
+            else if (((pATR[offset] & 0x0f) != 1) && ((pATR[offset] & 0x0f) != 14))
+            {
+                return ISO7816_ATR_ERROR;
+            }
+            tmpTDx = pATR[offset];
+            offset++;
+        }
+        else
+        {
+            tmpTDx = 0;
+        }
+    }
+
+    //TA3-TD3
+    if (tmpTDx != 0)
+    {
+        //TA3
+        if ((tmpTDx & BIT4) != 0)
+        {
+            if ((pATR[offset] < 16) || (pATR[offset] == 0xff))
+            {
+                return ISO7816_ATR_TA3_ERROR;
+            }
+            //设置卡片最大数据长度
+            SCIx->g_T1.bIFSC = pATR[offset];
+            offset++;
+        }
+        //TB3
+        if ((tmpTDx & BIT5) != 0)
+        {
+            if (SCIx->g_7816Para.bProlType != 0)
+            {
+                tmpCWI = pATR[offset] & 0x0f;
+                tmpBWI = (pATR[offset] & 0xf0) >> 4;
+                if ((tmpCWI > 5) || (tmpBWI > 4))
+                {
+                    return ISO7816_ATR_TB3_ERROR;
+                }
+                #ifndef EMV_L1_43D
+                    if ((TC1_N > 0x1e) && (TC1_N != 0xff))
+                    {
+                        return ISO7816_ATR_TB3_ERROR;
+                    }
+                #else
+                    if ((TC1_N > 0x1f) && (TC1_N != 0xff))
+                    {
+                        return ISO7816_ATR_TB3_ERROR;
+                    }
+                #endif
+                //2的CWI次幂
+                tmpLen = 1;
+                while (tmpCWI > 0)
+                {
+                    tmpLen = tmpLen * 2;
+                    tmpCWI--;
+                }
+                #ifndef EMV_L1_43D
+                    if ((tmpLen <= (TC1_N + 1)) && (TC1_N != 0xff))
+                    {
+                        return ISO7816_ATR_TB3_ERROR;
+                    }
+                #else
+                    if ((tmpLen < (TC1_N + 1)) && (TC1_N != 0xff))
+                    {
+                        return ISO7816_ATR_TB3_ERROR;
+                    }
+                #endif
+
+                //设置CWI  BWI
+                tmpLen = 0;
+                if ((SCIx->g_7816Para.bFlag & BIT0) != 0)
+                {
+                    tmpLen = SCIx->SCI_Tran_StateCB.di_table[SCIx->g_7816Para.bTA1 & 0x0f];
+                }
+
+                if(tmpLen == 0)
+                {
+                    tmpLen = 1;
+                }
+
+                SCIx->SCI_Tran_StateCB.terminal_rec_cwt = (1 << (pATR[offset] & 0x0F)) + 11 + 4;    //YC3121T
+                SCIx->SCI_Tran_StateCB.terminal_rec_bwt = (1 << ((pATR[offset] & 0xF0) >> 4));
+                if (SCIx->SCI_Tran_StateCB.terminal_rec_bwt == 0)
+                {
+                    SCIx->SCI_Tran_StateCB.terminal_rec_bwt = 1;
+                }
+                SCIx->SCI_Tran_StateCB.terminal_rec_bwt = SCIx->SCI_Tran_StateCB.terminal_rec_bwt * 960 * tmpLen + 11 + 960 * tmpLen;     //YC1321T + 20;
+
+                SCIx->SCI_Tran_StateCB.terminal_rec_bwt_atr = SCIx->SCI_Tran_StateCB.terminal_rec_bwt;
+
+                #ifdef DEBUG_7816
+                MyPrintf("para_1\n");
+                MyPrintf("%02x", SCIx->SCI_Tran_StateCB.terminal_send_cwt);
+                MyPrintf("\n");
+
+                MyPrintf("%02x", SCIx->SCI_Tran_StateCB.terminal_rec_cwt);
+                MyPrintf("\n");
+
+                MyPrintf("%02x", SCIx->SCI_Tran_StateCB.terminal_rec_bwt);
+                MyPrintf("\n");
+
+                MyPrintf("%02x", SCIx->SCI_Tran_StateCB.terminal_send_bgt);
+                MyPrintf("\n");
+                #endif
+            }
+
+            offset++;
+        }
+        else
+        {
+            if (SCIx->g_7816Para.bProlType == 1)
+            {
+                return ISO7816_ATR_TB3_ERROR;
+            }
+        }
+
+        //TC3
+        if ((tmpTDx & BIT6) != 0)
+        {
+            //TC3只支持0
+            if (0 != pATR[offset])
+            {
+                return ISO7816_ATR_TC3_ERROR;
+            }
+            offset++;
+        }
+    }
+    else
+    {
+        //如果是T1协议，没有TB3，则需要复位操作
+        if (SCIx->g_7816Para.bProlType == 1)
+        {
+            return ISO7816_ATR_TB3_ERROR;
+        }
+    }
+
+    if (SCIx->g_7816Para.bProlType == 0)
+    {
+        SCIx->SCI_Tran_StateCB.terminal_rec_cwt += 12;
+        SCIx->SCI_Tran_StateCB.terminal_rec_bwt = SCIx->SCI_Tran_StateCB.terminal_rec_cwt;
+    }
+    else
+    {
+        SCIx->SCI_Tran_StateCB.terminal_rec_cwt += 1;
+    }
+
+    ISO7816_TXRX_TIME_Init(SCIx);
+
+    #ifdef DEBUG_7816
+    MyPrintf("SCI7816_RX_BWT_TIMEONT %08x= \r\n", SCIx->SCIx7816->CWT_TO.reg);
+    MyPrintf("SCI7816_RX_CWT_TIMEONT %08x= \r\n", SCIx->SCIx7816->CWT_TO.reg);
+    MyPrintf("SCI7816_SEND_BGT %08x= \r\n", SCIx->SCIx7816->BGT.reg);
+    MyPrintf("SCI7816_SEND_CWT %08x= \r\n", SCIx->SCIx7816->CWT.reg);
+
+    MyPrintf("terminal_rec_bwt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_rec_bwt);
+    MyPrintf("terminal_rec_cwt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_rec_cwt);
+    MyPrintf("terminal_send_bgt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_send_bgt);
+    MyPrintf("terminal_send_cwt %08x= \r\n", SCIx->SCI_Tran_StateCB.terminal_send_cwt);
+    #endif
+    return OK;
+}
+
+/**
+  * @method  ISO7816_OperateSelect
+  * @brief  7816 operation selection function, select to activate card, hot reset or cold reset function
+  * @param  OperateMode:0x00  ISO7816_ACTIVE_CARD
+                        0x01  ISO7816_WARM_RESET
+                        0x02  ISO7816_DEACTIVE_CARD
+  * @param  SCIx:       x=0:sci0    x=1;sci1
+  * @retval OK:         0 on success
+  */
+uint16_t ISO7816_OperateSelect(uint8_t OperateMode, SCI_Struct_Type* SCIx)
+{
+    uint16_t ret = 0;
+
+    switch (OperateMode)
+    {
+    case ISO7816_ACTIVE_CARD:
+        ret = ISO7816_Card_In_Io_Filter();
+
+        #ifdef DEBUG_7816
+        MyPrintf("card detect ret = %02x \r\n",ret);
+        #endif
+
+        if (ret == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+        {
+            return ISO7816_CARD_STUTES_ERROR;
+        }
+
+        {
+            ret = ISO7816_Cold_Reset(SCIx);
+        }
+
+        if (ret != OK)
+        {
+            return ISO7816_CARD_STUTES_ERROR;
+        }
+
+        //表示冷复位  bFlag = 0
+        SCIx->g_7816Para.bFlag &= (~BIT1);
+        break;
+    case ISO7816_WARM_RESET:
+        ISO7816_Warm_Reset(SCIx);
+
+        //表示热复位  bFlag = 1
+        SCIx->g_7816Para.bFlag |= BIT1;
+        break;
+    case ISO7816_DEACTIVE_CARD:
+        //IC卡下电
+        ISO7816_Deactive(SCIx);
+        break;
+    default:
+        return ISO7816_OPERATE_MODE_ERROR;
+    }
+    return OK;
+}
+
+/**
+  * @method ISO7816_DisposePPS
+  * @brief  7816 set communication rate
+  * @param  TA1: TA1 data
+  * @retval OK:  0 on success
+  */
+uint16_t ISO7816_DisposePPS(SCI_Struct_Type *SCIx,uint8_t TA1)
+{
+    uint16_t f = 0;
+    uint8_t   fi = 0, di = 0;
+
+    fi = GET_4_BITS_H(TA1);
+    di = GET_4_BITS_L(TA1);
+    if ((!SCIx->SCI_Tran_StateCB.fi_table[fi]) || (!SCIx->SCI_Tran_StateCB.di_table[di]))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+    f = SCIx->SCI_Tran_StateCB.fi_table[fi] / SCIx->SCI_Tran_StateCB.di_table[di];
+
+    if (SCIx->g_7816Para.bTA2Flag == 0)
+    {
+        f = 372;
+    }
+    else
+    {
+        if ((SCIx->g_7816Para.bTA2 & 0x10) != 0)
+        {
+            f = 372;
+        }
+    }
+
+    //设置通讯速率寄存器
+    SCIx->SCIx7816->ETU.bit.VAL = f;
+
+    return OK;
+}
+
+/**
+  * @method ISO7816_Dispose_CMD_LOOP
+  * @brief  7816APDU interaction functions
+  * @param  pCmd：    Send data storage unit
+  * @param  CmdLen：  Send data length
+  * @param  pResp：   Receive data storage unit
+  * @param  pRespLen：Length of receive data
+  * @retval None
+  */
+uint16_t ISO7816_Dispose_CMD_LOOP(SCI_Struct_Type *SCIx,uint8_t *pCmd, uint16_t CmdLen, uint8_t *pResp,  uint16_t *pRespLen)
+{
+    uint16_t  ret;
+    uint16_t  tmpRespLen, tmpCmdLen;
+    uint16_t  tmpOffset;
+    uint8_t   tmpCMDBuf[5];
+    uint8_t   tmpRECBuf[286];
+    uint8_t   tmp61Flag;
+
+    tmpOffset = 0;
+    tmp61Flag = 0;
+    tmpCmdLen =  CmdLen;
+
+    if (PROTOCOL_T0 == SCIx->g_7816Para.bProlType)
+    {
+        //处理61xx 6cxx  也可以返回给上层应用处理
+        if ((SCIx->g_7816Para.bFlag & BIT2) != 0) //T0 Process
+        {
+            memcpy(tmpCMDBuf, pCmd, 5);
+            ret = ISO7816_TPDU_T0_LOOP(SCIx, pCmd, tmpCmdLen,  tmpRECBuf + tmpOffset, &tmpRespLen);
+            COMPARE_RETURN(ret);
+            tmpOffset += tmpRespLen;
+
+            while (1)
+            {
+                if (tmpRespLen >= 2)
+                {
+                    if (tmpRECBuf[tmpOffset - 2] == 0x61)
+                    {
+                        tmpCMDBuf[0] = 0;
+                        tmpCMDBuf[1] = 0xC0;
+                        tmpCMDBuf[2] = 0;
+                        tmpCMDBuf[3] = 0;
+                        tmpCMDBuf[4] = tmpRECBuf[tmpOffset - 1];
+                        tmpOffset -= 2;
+                        ret = ISO7816_TPDU_T0_LOOP(SCIx, tmpCMDBuf, 5, tmpRECBuf + tmpOffset, &tmpRespLen);
+                        COMPARE_RETURN(ret);
+
+                        tmp61Flag = 1;
+                        tmpOffset += tmpRespLen;
+
+                        continue;
+                    }
+                    else if (tmpRECBuf[tmpOffset - 2] == 0x6C)
+                    {
+                        tmpCMDBuf[4] = tmpRECBuf[tmpOffset - 1];
+                        tmpOffset -= 2;
+                        ret = ISO7816_TPDU_T0_LOOP(SCIx, tmpCMDBuf, 5, tmpRECBuf + tmpOffset, &tmpRespLen);
+                        COMPARE_RETURN(ret);
+
+                        tmpOffset += tmpRespLen;
+
+                        continue;
+                    }
+                    else if ((tmpRECBuf[tmpOffset - 2] == 0x90) && (tmpRECBuf[tmpOffset - 1] == 0x00))
+                    {
+                        break;
+                    }
+                    //data
+                    else if ((tmpRECBuf[tmpOffset - 2] == 0x62) || (tmpRECBuf[tmpOffset - 2] == 0x63) || ((tmpRECBuf[tmpOffset - 2] & 0xF0) == 0x90))
+                    {
+                        if (tmp61Flag == 1)
+                        {
+                            break;
+                        }
+
+                        if ((SCIx->g_7816Para.bFlag & BIT3) != 0)
+                        {
+                            break;
+                        }
+
+                        if ((CmdLen > 5) && (tmpCMDBuf[1] == 0xA4))
+                        {
+                            tmpCMDBuf[0] = 0;
+                            tmpCMDBuf[1] = 0xC0;
+                            tmpCMDBuf[2] = 0;
+                            tmpCMDBuf[3] = 0;
+                            tmpCMDBuf[4] = 0;
+                            tmpOffset -= 2;
+                            ret = ISO7816_TPDU_T0_LOOP(SCIx, tmpCMDBuf, 5, tmpRECBuf + tmpOffset, &tmpRespLen);
+                            COMPARE_RETURN(ret);
+
+                            tmpOffset += tmpRespLen;
+                            continue;
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                else
+                {
+                    break;
+                }
+
+
+            }
+
+            memcpy(pResp, tmpRECBuf, tmpOffset);
+            *pRespLen = tmpOffset;
+            return OK;
+        }
+        else
+        {
+            return ISO7816_TPDU_T0_LOOP(SCIx, pCmd, CmdLen, pResp, pRespLen);
+        }
+    }
+    else
+    {
+        SCIx->g_T1.bIFSD = 254;
+        return ISO7816_TPDU_T1(SCIx, pCmd, CmdLen, pResp, pRespLen);
+    }
+
+}
+
+/**
+  * @method ISO7816_LoopBack
+  * @brief  7816 main loop function
+  * @param  None
+  * @retval None
+  */
+uint16_t ISO7816_LoopBack(SCI_Struct_Type *SCIx)
+{
+    uint8_t ATRLen;
+
+    uint16_t Ret;
+    uint8_t SELECT_PSE[]	= {0x00, 0xA4, 0x04, 0x00, 0x0E,
+                                0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00
+                              };  /* SELECT_PPSE */
+
+    ISO7816_Atr_Timer_Start(SCIx);  //开始计时
+
+TOResetCard:
+#if 1
+    delay_ms(5000);  //延时5s
+#endif
+
+    //激活卡片
+    Ret = ISO7816_OperateSelect(ISO7816_ACTIVE_CARD, SCIx);  //激活卡片内涵冷复位
+    if (Ret == ISO7816_CARD_STUTES_ERROR)
+    {
+        goto TOResetCard;
+    }
+
+TOWarmResetCard:
+   // 接收ATR
+    ATRLen = 0;
+    Ret = ISO7816_GetAtr_LOOP(SCIx,&SCIx->g_7816Para.aAtr[1], &ATRLen);
+    if (OK != Ret)
+    {
+        if ((ISO7816_ATR_LEN_ERROR == Ret))
+        {
+            if ((SCIx->g_7816Para.bFlag & BIT1) == 0)   //BIT1 为1时表示热复位、为0时表示冷复位
+            {
+                delay_ms(10);
+                ISO7816_OperateSelect(ISO7816_WARM_RESET, SCIx);
+                goto TOWarmResetCard;
+            }
+
+        }
+        ISO7816_Deactive(SCIx);
+        delay_ms(5);
+        goto TOResetCard;
+    }
+
+    SCIx->g_7816Para.aAtr[0] = ATRLen;
+    delay_ms(50);
+
+    //自动发送C0
+    SCIx->g_7816Para.bFlag |= BIT2;
+    memset(&SCIx->g_T1.bIFSC, 0, sizeof(SCIx->g_T1));
+    SCIx->g_T1.bIFSC = 32;  //IC卡信息域大小
+
+    //ATR数据处理
+    Ret = ISO7816_DisposeATR(SCIx,&SCIx->g_7816Para.aAtr[1], ATRLen);
+    if (OK != Ret)
+    {
+        if ((Ret == ISO7816_ATR_TA1_ERROR) || (Ret == ISO7816_ATR_TB1_ERROR)
+                || (Ret == ISO7816_ATR_TB3_ERROR) || (Ret == ISO7816_ATR_TA3_ERROR)
+                || (Ret == ISO7816_ATR_TC2_ERROR) || (Ret == ISO7816_ATR_TC3_ERROR)
+                || (Ret == ISO7816_ATR_TA2_ERROR) || (Ret == ISO7816_ATR_TD2_ERROR)
+                || (Ret == ISO7816_ATR_TB2_ERROR))
+        {
+            if ((SCIx->g_7816Para.bFlag & BIT1) == 0)
+            {
+                ISO7816_OperateSelect(ISO7816_WARM_RESET, SCIx);
+                goto TOWarmResetCard;
+            }
+            else
+            {
+                ISO7816_OperateSelect(ISO7816_DEACTIVE_CARD, SCIx);
+                delay_ms(10);
+                goto TOResetCard;
+            }
+        }
+        else
+        {
+            ISO7816_OperateSelect(ISO7816_DEACTIVE_CARD, SCIx);
+            delay_ms(10);
+            goto TOResetCard;
+        }
+    }
+
+    ISO7816_Config_Mode_Fun(SCIx);
+#ifdef DEBUG_7816_EMV
+    MyPrintf("reset ok\n");
+#endif
+
+    //处理PPS
+    if ((SCIx->g_7816Para.bFlag & BIT0) == 1)
+    {
+        if (SCIx->g_7816Para.bTA1 != 0x11)
+        {
+            Ret = ISO7816_DisposePPS(SCIx,SCIx->g_7816Para.bTA1);
+            if (OK != Ret)
+            {
+                ISO7816_OperateSelect(ISO7816_DEACTIVE_CARD, SCIx);
+                delay_ms(10);
+                goto TOResetCard;
+            }
+        }
+    }
+
+    memcpy(SCIx->SCI_Tran_StateCB.SCI_ApduCmd, SELECT_PSE, 20);
+    SCIx->SCI_Tran_StateCB.SCI_SendLen = 20;
+
+    if (SCIx->g_7816Para.bProlType == PROTOCOL_T1)
+    {
+        uint8_t TmpCmd[5];
+        //设置IFSD
+        SCIx->g_T1.bIFSD = 254;
+        TmpCmd[0] = 254;
+
+        Ret = ISO7816_TPDU_T1Send_LOOP(SCIx , TmpCmd, 1, T_S_IFS);
+        if (Ret != OK)
+        {
+            ISO7816_OperateSelect(ISO7816_DEACTIVE_CARD, SCIx);
+            delay_ms(10);
+            goto TOResetCard;
+        }
+    }
+
+TOSendCMD:
+    delay_ms(2);
+
+#ifdef DEBUG_7816_EMV
+    MyPrintf("cmd\n");
+#endif
+
+    Ret = ISO7816_Dispose_CMD_LOOP(SCIx,SCIx->SCI_Tran_StateCB.SCI_ApduCmd, SCIx->SCI_Tran_StateCB.SCI_SendLen, SCIx->g_7816Para.aRecBuff, &SCIx->SCI_Tran_StateCB.SCI_RecLen);
+    if (OK != Ret)
+    {
+        if ((ISO7816_PARITY_ERROR == Ret))
+        {
+            ISO7816_OperateSelect(ISO7816_WARM_RESET, SCIx);
+            delay_ms(10);
+            goto TOWarmResetCard;
+        }
+
+        ISO7816_OperateSelect(ISO7816_DEACTIVE_CARD, SCIx);
+        delay_ms(10);
+        goto TOResetCard;
+
+    }
+#ifdef DEBUG_7816_EMV
+    MyPrintf("cmd ok\n");
+#endif
+    delay_ms(2);
+
+    if (SCIx->SCI_Tran_StateCB.SCI_RecLen >= 6)
+    {
+        if (SCIx->g_7816Para.aRecBuff[1] == 0x70)
+        {
+            ISO7816_OperateSelect(ISO7816_DEACTIVE_CARD, SCIx);
+            delay_ms(100);
+            goto TOResetCard;
+        }
+        else
+        {
+            SCIx->SCI_Tran_StateCB.SCI_SendLen = SCIx->SCI_Tran_StateCB.SCI_RecLen - 2;
+            memcpy(SCIx->SCI_Tran_StateCB.SCI_ApduCmd, SCIx->g_7816Para.aRecBuff, SCIx->SCI_Tran_StateCB.SCI_SendLen);
+
+            delay_ms(2);
+            goto TOSendCMD;
+        }
+    }
+    else
+    {
+        if (SCIx->g_7816Para.aRecBuff[0] == 0xff)
+        {
+            ISO7816_OperateSelect(ISO7816_DEACTIVE_CARD, SCIx);
+            delay_ms(10);
+            goto TOResetCard;
+        }
+    }
+
+    delay_ms(2);
+
+    memcpy(SCIx->SCI_Tran_StateCB.SCI_ApduCmd, SELECT_PSE, 20);
+    SCIx->SCI_Tran_StateCB.SCI_SendLen = 20;
+    goto TOSendCMD ;
+}
Index: yc_7816_emv_L1/yc_7816_T0.h
===================================================================
--- /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T0.h	(nonexistent)
+++ /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T0.h	(working copy)
@@ -0,0 +1,10 @@
+
+uint16_t ISO7816_RecBytes(SCI_Struct_Type *SCIx ,uint8_t *RxBuf, uint16_t RxLen);
+
+uint16_t ISO7816_SendBytes_T0(SCI_Struct_Type *SCIx,uint8_t *pBuff, uint16_t Len);
+
+uint16_t ISO7816_TPDU_T0_LOOP(SCI_Struct_Type *SCIx, uint8_t *pCommand, uint16_t CommandLength,uint8_t *pResponse, uint16_t *pResponseLength);
+
+uint16_t ISO7816_TPDU_T0_IRQ(SCI_Struct_Type *SCIx,uint16_t CmdLen);
+
+
Index: yc_7816_emv_L1/yc_7816_T0.c
===================================================================
--- /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T0.c	(nonexistent)
+++ /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T0.c	(working copy)
@@ -0,0 +1,467 @@
+#include "string.h"
+#include "yc_7816.h"
+#include "yc_timer.h"
+
+/**
+  * @brief  7816 T0 mode receive data function
+  * @param  RxBuf: Receiving data storage unit
+  * @param  RxLen: Length of received data
+  * @retval OK:    0 on success
+  */
+uint16_t ISO7816_RecBytes(SCI_Struct_Type *SCIx ,uint8_t *RxBuf, uint16_t RxLen)
+{
+    uint16_t  RemainLen = 0;
+    uint8_t waterlevel = 0;
+    uint16_t i=0;
+    uint16_t len = 0;
+    uint16_t index = 0;
+    uint16_t val = 0;
+    uint8_t rx_num = 0;
+
+    if ((!(RxLen)) || (NULL == RxBuf))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[0] = RxLen/0x100;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[1] = RxLen%0x100;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2] = 0;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3] = 0;
+    if (RxLen >= 8)
+    {
+        waterlevel = 4;
+    }
+    else
+    {
+        waterlevel = RxLen;
+    }
+
+    SCIx->SCI_Tran_StateCB.Card_Type = 0;
+    ISO7816_RX_APDU_Config(SCIx,waterlevel);
+    do
+    {
+        if (SCIx->SCIx7816->IS.bit.RFIFO_HA )
+        {
+            len = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[0]*0x100 + SCIx->SCI_Tran_StateCB.SCI_RX_Buf[1];
+            index = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2]*0x100 + SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3];
+
+            rx_num = SCIx->SCIx7816->FIFO_CTRL.bit.R_ITEMS;
+            if(len > index)
+            {
+                val = len - index;
+                if (val <= rx_num)
+                {
+                    for (i = 0; i <val; i++)
+                    {
+                        SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4 + index++] = SCIx->SCIx7816->DATA.reg;
+                    }
+                }
+                else
+                {
+                    for (i = 0; i < rx_num; i++)
+                    {
+                        SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4 + index++] = SCIx->SCIx7816->DATA.reg;
+                    }
+                }
+            }
+
+            if(index >= len)
+            {
+                SCIx->SCI_Tran_StateCB.SCI_RX_Result = 1;  //接收完成
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &= ~0x0f;
+                SCIx->SCIx7816->IS.bit.RFIFO_HA = 1;
+            }
+            else if (((len - index) > 0) && ((len - index) < 4))
+            {
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &=~0x0f;
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL = (len - index);
+            }
+
+            SCIx->SCIx7816->IS.bit.RFIFO_HA = 1;
+
+            SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2] = index/0x100;
+            SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3] = index%0x100;
+        }
+        //rx flag
+        if ((SCIx->SCIx7816->IS.bit.CWT_TO == 1) || (SCIx->SCIx7816->IS.bit.BWT_TO == 1))
+        {
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_REC_TIMEOUT;  //5a
+
+            SCIx->SCIx7816->IS.bit.CWT_TO = 1;
+            SCIx->SCIx7816->IS.bit.BWT_TO = 1;
+        }
+        if ((SCIx->SCIx7816->IS.bit.R_ERR == 1) && (SCIx->SCI_Tran_StateCB.Card_Type == 0))
+        {
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_ERR_NUM_OVER;
+
+            SCIx->SCIx7816->IS.bit.R_ERR = 1;
+        }
+        if ((SCIx->SCIx7816->IS.bit.R_ERR == 1) && (SCIx->SCI_Tran_StateCB.Card_Type == 1))
+        {
+            SCIx->SCI_Tran_StateCB.T1_parity_flag = 1;
+            SCIx->SCIx7816->IS.bit.R_ERR = 1;
+        }
+        if (SCIx->SCIx7816->IS.bit.RFIFO_OVF == 1 )
+        {
+            #ifdef DEBUG_7816_FPGA
+            MyPrintf("sci isr %08x \r\n", SCIx->SCIx7816->IS.reg);
+            #endif
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_ERR_NUM_OVER;
+
+            SCIx->SCIx7816->IS.bit.RFIFO_OVF = 1;
+        }
+
+        if ((SCIx->SCIx7816->IS.bit.TFIFO_OVF == 1)  | (SCIx->SCIx7816->IS.bit.TFIFO_LA == 1 ) | (SCIx->SCIx7816->IS.bit.T_ERR== 1) | (SCIx->SCIx7816->IS.bit.T_DONE == 1))
+        {
+            #ifdef DEBUG_7816_FPGA
+            MyPrintf("irq_SCI_State %08x \r\n", SCIx->SCI_Tran_StateCB.SCI_State);
+            MyPrintf("irq_sci isr= %08x \r\n", SCIx->SCIx7816->IS.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IE.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IES.reg);
+            MyPrintf("irq_sci ctrl2= %08x \r\n", SCIx->SCIx7816->CTRL2.reg);
+            #endif
+            SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &=~0x0f;
+            SCIx->SCIx7816->IS.reg = 0XFFFFFFFF;
+        }
+
+        if (ISO7816_Detect_Io_State() == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+        {
+            //config sci
+            SCIx->SCIx7816->IE.reg = 0;
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+            SCIx->SCIx7816->CTRL2.bit.RX_EN &=~1;
+            delay_ms(2);    //至少1字节时间
+            SCIx->SCIx7816->CTRL.bit.RFIFO_CL = 1;//clear tx/rx fifo
+            SCIx->SCIx7816->CTRL.bit.TFIFO_CL = 1;//clear tx/rx fifo
+            delay_ms(1);    //至少大于100us
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+
+            return ISO7816_CARD_ABSENT;
+        }
+
+        if (SCIx->SCI_Tran_StateCB.SCI_RX_Result == 1)
+        {
+            for (i=0; i<RxLen; i++)
+            {
+                *RxBuf++ = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4+i];
+            }
+
+            RemainLen = RxLen;
+        }
+        else if (SCIx->SCI_Tran_StateCB.SCI_RX_Result > 1)
+        {
+            #ifdef DEBUG_7816
+            MyPrintf("T0 RX_Result= %02x \r\n",SCIx->SCI_Tran_StateCB.SCI_RX_Result);
+            MyPrintf("T0 recv time\r\n");
+            #endif
+            return SCIx->SCI_Tran_StateCB.SCI_RX_Result;
+        }
+    }
+    while (RemainLen < (RxLen));
+
+    return OK;
+}
+
+/**
+  * @method ISO7816_SendBytes_T0
+  * @brief  7816 T0 mode send data function
+  * @param  pBuff: Receiving data storage unit
+  * @param  Len:   Length of received data
+  * @retval OK:    0 on success
+  */
+uint16_t ISO7816_SendBytes_T0(SCI_Struct_Type *SCIx,uint8_t *pBuff, uint16_t Len)
+{
+    uint16_t i = 0;
+
+    if ((!Len) || (NULL == pBuff))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+#ifdef DEBUG_7816
+    MyPrintf("send:\n");
+#endif
+    //delay_ms(2);
+    //while ((SCI7816_STAT & 0x40) ==0);
+    for(i=0; i<Len; i++)
+    {
+        SCIx->SCI_Tran_StateCB.SCI_TX_Buf[4+i] = *pBuff++;
+    }
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[0] = Len/0x100;
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[1] = Len%0x100;
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[2] = 0;
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[3] = 0;
+
+    ISO7816_TX_APDU_Config(SCIx);
+    while (SCIx->SCI_Tran_StateCB.SCI_TX_Result == 0xff)
+    {
+#ifdef POLL_PROCESS
+        uint16_t len = 0;
+        uint16_t index = 0;
+        uint16_t val = 0;
+        uint8_t tx_fifo_level = 0;
+
+        tx_fifo_level = SCIx->SCIx7816->FIFO_CTRL.reg & 0x0f;
+        if (SCIx->SCIx7816->IS.bit.TFIFO_LA == 1)
+        {
+            len = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[0]*0x100 + SCIx->SCI_Tran_StateCB.SCI_TX_Buf[1];
+            index = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[2]*0x100 + SCIx->SCI_Tran_StateCB.SCI_TX_Buf[3];
+
+            if (len > index)
+            {
+                val = len - index;
+            }
+            else
+            {
+                SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &=~0x0f;
+                SCIx->SCIx7816->IS.bit.TFIFO_LA = 1;
+            }
+
+            if(val > (8-tx_fifo_level))
+            {
+                for (i = 0; i < (8-tx_fifo_level); i++)
+                {
+                    SCIx->SCIx7816->DATA.reg = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[4 + index++];
+                }
+            }
+
+            if (val <= (8-tx_fifo_level))
+            {
+                for (i = 0; i < val; i++)
+                {
+                    SCIx->SCIx7816->DATA.reg = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[4 + index++];
+                }
+                SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &=~0x0f;
+                SCIx->SCIx7816->IS.bit.TFIFO_LA = 1;
+            }
+
+            SCIx->SCIx7816->IS.bit.TFIFO_LA = 1;
+            SCIx->SCI_Tran_StateCB.SCI_TX_Buf[2] = index/0x100;
+            SCIx->SCI_Tran_StateCB.SCI_TX_Buf[3] = index%0x100;
+        }
+
+        //tx flag
+        if (SCIx->SCIx7816->IS.bit.T_DONE == 1)
+        {
+            SCIx->SCI_Tran_StateCB.SCI_TX_Result = 0;
+            SCIx->SCIx7816->IS.bit.T_DONE = 1;
+        }
+        if (SCIx->SCIx7816->IS.bit.T_ERR == 1)
+        {
+            SCIx->SCI_Tran_StateCB.SCI_TX_Result = ISO7816_ERR_NUM_OVER;
+
+            SCIx->SCIx7816->IS.bit.T_ERR = 1;
+        }
+        if (SCIx->SCIx7816->IS.bit.TFIFO_OVF == 1)
+        {
+            SCIx->SCI_Tran_StateCB.SCI_TX_Result = ISO7816_ERR_NUM_OVER;
+
+            SCIx->SCIx7816->IS.bit.TFIFO_OVF = 1;
+        }
+
+        if ((SCIx->SCIx7816->IS.bit.RFIFO_OVF == 1) | (SCIx->SCIx7816->IS.bit.RFIFO_HA == 1 ) | (SCIx->SCIx7816->IS.bit.R_ERR == 1) \
+            | (SCIx->SCIx7816->IS.bit.BWT_TO == 1) | (SCIx->SCIx7816->IS.bit.CWT_TO))
+        {
+            #ifdef DEBUG_7816_FPGA
+            MyPrintf("irq_SCI_State %08x \r\n", SCIx->SCI_Tran_StateCB.SCI_State);
+            MyPrintf("irq_sci isr= %08x \r\n", SCIx->SCIx7816->IS.reg);
+            MyPrintf("irq_sci ier= %08x \r\n", SCIx->SCIx7816->IE.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IES.reg);
+            MyPrintf("irq_sci ctrl2= %08x \r\n", SCIx->SCIx7816->CTRL2.reg);
+            #endif
+
+            SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &=~0x0f;
+            SCIx->SCIx7816->IS.reg = 0XFFFFFFFF;
+        }
+#endif
+        if (ISO7816_Detect_Io_State() == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+        {
+            //config sci
+            SCIx->SCIx7816->IE.reg = 0;
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+            SCIx->SCIx7816->CTRL2.bit.TX_EN &=~1;
+            delay_ms(2);    //至少1字节时间
+            SCIx->SCIx7816->CTRL.bit.RFIFO_CL = 1; //clear tx/rx fifo
+            SCIx->SCIx7816->CTRL.bit.TFIFO_CL = 1; //clear tx/rx fifo
+            delay_ms(1);    //至少大于100us
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+
+            return ISO7816_CARD_ABSENT;
+        }
+    }
+
+#ifdef DEBUG_7816
+    MyPrintf("\n");
+#endif
+
+    return SCIx->SCI_Tran_StateCB.SCI_TX_Result;
+}
+
+/**
+  * @method ISO7816_TPDU_T0
+  * @brief  7816 T0 Command transfer protocol data function
+  * @param  CmdLen: Length of data sent by command
+  * @retval OK:    0 on success
+  */
+uint16_t ISO7816_TPDU_T0_LOOP(SCI_Struct_Type *SCIx, uint8_t *pCommand, uint16_t CommandLength,
+                         uint8_t *pResponse, uint16_t *pResponseLength)
+
+{
+    uint8_t   sw1, Ins;
+    uint16_t  p3;
+    uint16_t  ret, tmpRecLen = 0, tmpSendOffset;
+
+    tmpRecLen = 0;
+
+    if ((NULL == pCommand) || (NULL == pResponse) ||
+            (CommandLength < 4) || (NULL == pResponseLength))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    if (CommandLength == 4)
+    {
+        pCommand[4] = 0;
+    }
+    Ins = pCommand[1];
+
+    SCIx->g_7816Para.bFlag &= (~BIT3);
+
+    ret = ISO7816_SendBytes_T0(SCIx, pCommand, 5);
+    COMPARE_RETURN(ret);
+
+    //接收过程字节
+    pResponse[tmpRecLen] = ISO7816_NULL_T0;
+    do
+    {
+        ret = ISO7816_RecBytes(SCIx, &pResponse[tmpRecLen], 1);
+        COMPARE_RETURN(ret);
+    }
+    while (pResponse[tmpRecLen] == ISO7816_NULL_T0);   //如果是60的话等待
+
+    sw1 = pResponse[0];
+    p3 = pCommand[4];
+    tmpSendOffset = 5;
+
+    //过程字节判断
+    do
+    {
+        //错误码或执行正确
+        if ((0x60 == (sw1 & 0xF0)) || (0x90 == (sw1 & 0xF0)))
+        {
+            tmpRecLen++;
+            ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen++], 1);
+            if (ret != OK)
+            {
+                return ret;
+            }
+
+            //错误码
+            SCIx->g_7816Para.bFlag |= BIT3;
+
+            *pResponseLength = tmpRecLen;
+            return  OK;
+        }
+
+        if (Ins == sw1)
+        {
+            if (5 == CommandLength)
+            {
+                ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen], p3 + 2 - tmpRecLen);
+                COMPARE_RETURN(ret);
+                *pResponseLength = p3 + 2;
+                return  OK;
+            }
+            else
+            {
+                ret = ISO7816_SendBytes_T0(SCIx, pCommand + tmpSendOffset, p3);
+                COMPARE_RETURN(ret);
+
+                pResponse[tmpRecLen] = ISO7816_NULL_T0;
+                //如果是60 则等待接收字节
+                do
+                {
+                    ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen], 1);
+                    COMPARE_RETURN(ret);
+                }
+                while (pResponse[tmpRecLen] == ISO7816_NULL_T0);
+                tmpRecLen++;
+
+                ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen++], 1);
+                COMPARE_RETURN(ret);
+                *pResponseLength = tmpRecLen;
+                return  OK;
+            }
+        }
+        else if (sw1 == (uint8_t)(~Ins)) //如果是INS的补码
+        {
+
+            if (5 == CommandLength)
+            {
+                ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen++], 1);
+                COMPARE_RETURN(ret);
+
+                if (tmpRecLen >= (p3 + 2))
+                {
+                    *pResponseLength = tmpRecLen;
+                    return  OK;
+                }
+
+                //再次接收过程字节
+                ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen], 1);
+                COMPARE_RETURN(ret);
+
+                sw1 = pResponse[tmpRecLen];
+
+            }
+            else
+            {
+                if (p3)
+                {
+                    //如果是INS的补码，一个字节一个字节传送
+                    ret = ISO7816_SendBytes_T0(SCIx, pCommand + tmpSendOffset, 1);
+                    COMPARE_RETURN(ret);
+                    tmpSendOffset++;
+                    p3--;
+
+                    //接收过程字节
+                    do
+                    {
+                        ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen], 1);
+                        COMPARE_RETURN(ret);
+                    }
+                    while (pResponse[tmpRecLen] == ISO7816_NULL_T0);
+
+                    sw1 = pResponse[tmpRecLen];
+
+                    continue;
+                }
+                else
+                {
+                    //接收过程字节
+                    do
+                    {
+                        ret = ISO7816_RecBytes(SCIx,&pResponse[tmpRecLen], 1);
+                        COMPARE_RETURN(ret);
+                    }
+                    while (pResponse[tmpRecLen] == ISO7816_NULL_T0);
+
+                    sw1 = pResponse[tmpRecLen++];
+
+                    ret = ISO7816_RecBytes(SCIx,pResponse + 1, 1);
+                    COMPARE_RETURN(ret);
+                    *pResponseLength = 2;
+                    return  OK;
+                }
+            }
+
+        }
+        else
+        {
+            return ISO7816_PROCEDURE_INS_ERROR;
+        }
+
+    }
+    while (1);
+}
+
Index: yc_7816_emv_L1/yc_7816_T1.h
===================================================================
--- /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T1.h	(nonexistent)
+++ /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T1.h	(working copy)
@@ -0,0 +1,16 @@
+
+uint16_t ISO7816_SendBytes_T1(SCI_Struct_Type* SCIx,uint8_t *pBuff, uint16_t Len);
+
+uint16_t ISO7816_TPDU_T1Send_IRQ(SCI_Struct_Type *SCIx , uint8_t *pCommand, uint16_t CommandLength, uint8_t Type);
+
+uint16_t ISO7816_TPDU_T1Send_LOOP(SCI_Struct_Type *SCIx , uint8_t *pCommand, uint16_t CommandLength, uint8_t Type);
+
+uint16_t ISO7816_TPDU_T1(SCI_Struct_Type *SCIx,uint8_t *pCommand, uint16_t CommandLength,uint8_t *pResponse,  uint16_t *pResponseLength);
+
+uint16_t ISO7816_TPDU_T1Rec_IRQ(SCI_Struct_Type *SCIx ,uint8_t *pRec, uint16_t *RecLen);
+
+uint16_t ISO7816_TPDU_T1Rec_LOOP(SCI_Struct_Type *SCIx,uint8_t *pRec, uint16_t *RecLen);
+
+uint16_t ISO7816_CalcLRC(uint8_t *pBuff, uint16_t I_Len, uint8_t *pLRC);
+
+
Index: yc_7816_emv_L1/yc_7816_T1.c
===================================================================
--- /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T1.c	(nonexistent)
+++ /public/yc3122/trunk/SDK/Libraries/sdk/yc_7816_emv_L1/yc_7816_T1.c	(working copy)
@@ -0,0 +1,1291 @@
+#include "string.h"
+#include "yc_7816.h"
+#include "yc_timer.h"
+
+/**
+  * @method ISO7816_CalcLRC
+  * @brief  Iso7816 Computational checksum
+  * @param  pBuff: data buff
+  * @param  I_Len: I-block length
+  * @param  pLRC:  pLRC
+  * @retval None
+  */
+uint16_t ISO7816_CalcLRC(uint8_t *pBuff, uint16_t I_Len, uint8_t *pLRC)
+{
+    uint16_t i;
+
+    if ((pBuff == NULL) || (pLRC == NULL))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+    *pLRC = 0;
+    for (i = 0; i < I_Len; i++)
+    {
+        *pLRC ^= pBuff[i];
+    }
+    return OK;
+}
+
+/**
+  * @method ISO7816_CheckLRC
+  * @brief  Iso7816  Check  checksum
+  * @param  pBuff: Data buff
+  * @param  I_Len: I-block length
+  * @param  LRC:   LRC
+  * @retval None
+  */
+uint16_t ISO7816_CheckLRC(uint8_t *pBuff, uint16_t I_Len, uint8_t LRC)
+{
+    uint8_t tmpLRC = 0;
+    if (OK != ISO7816_CalcLRC(pBuff, I_Len, &tmpLRC))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    if (LRC != tmpLRC)
+    {
+        return ISO7816_T1_LRC_ERROR;
+    }
+    return OK;
+}
+
+/**
+  * @method ISO7816_SendBytes_T1
+  * @brief  7816 T1 mode send byte function
+  * @param  pBuff:         Sending data storage unit
+  * @param  Len:           Sending data length
+  * @retval SCI_TX_Result: 0-send finsh
+  */
+uint16_t ISO7816_SendBytes_T1(SCI_Struct_Type* SCIx,uint8_t *pBuff, uint16_t Len)
+{
+    uint16_t   i;
+    uint16_t len = 0;
+    uint16_t index = 0;
+    uint16_t val = 0;
+    uint8_t tx_fifo_level = 0;
+
+    if ((!Len) || (NULL == pBuff))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+#ifdef DEBUG_7816
+    MyPrintf("send:\n");
+#endif
+    //delay_ms(2);
+    //while ((STATUS & 0x40) ==0);
+
+    for(i=0; i<Len; i++)
+    {
+        SCIx->SCI_Tran_StateCB.SCI_TX_Buf[4+i] = *pBuff++;
+    }
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[0] = Len/0x100;
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[1] = Len%0x100;
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[2] = 0;
+    SCIx->SCI_Tran_StateCB.SCI_TX_Buf[3] = 0;
+
+    ISO7816_TX_APDU_Config(SCIx);
+    while (SCIx->SCI_Tran_StateCB.SCI_TX_Result == 0xff)
+    {
+        tx_fifo_level = SCIx->SCIx7816->FIFO_CTRL.reg & 0x0f;
+        if (SCIx->SCIx7816->IS.bit.TFIFO_LA == 1)
+        {
+            len = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[0]*0x100 + SCIx->SCI_Tran_StateCB.SCI_TX_Buf[1];
+            index = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[2]*0x100 + SCIx->SCI_Tran_StateCB.SCI_TX_Buf[3];
+
+            if (len > index)
+            {
+                val = len - index;
+            }
+            else
+            {
+                SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &=~0x0f;
+                SCIx->SCIx7816->IS.bit.TFIFO_LA = 1;
+            }
+
+            if(val > (8-tx_fifo_level))
+            {
+                for (i = 0; i < (8-tx_fifo_level); i++)
+                {
+                    SCIx->SCIx7816->DATA.reg = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[4 + index++];
+                }
+            }
+
+            if (val <= (8-tx_fifo_level))
+            {
+                for (i = 0; i < val; i++)
+                {
+                    SCIx->SCIx7816->DATA.reg = SCIx->SCI_Tran_StateCB.SCI_TX_Buf[4 + index++];
+                }
+                SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &=~0x0f;
+                SCIx->SCIx7816->IS.bit.TFIFO_LA = 1;
+            }
+
+            SCIx->SCIx7816->IS.bit.TFIFO_LA = 1;
+            SCIx->SCI_Tran_StateCB.SCI_TX_Buf[2] = index/0x100;
+            SCIx->SCI_Tran_StateCB.SCI_TX_Buf[3] = index%0x100;
+        }
+
+        //tx flag
+        if (SCIx->SCIx7816->IS.bit.T_DONE == 1 )
+        {
+            SCIx->SCI_Tran_StateCB.SCI_TX_Result = 0;
+            SCIx->SCIx7816->IS.bit.T_DONE = 1;
+        }
+        if (SCIx->SCIx7816->IS.bit.T_ERR == 1 )
+        {
+            SCIx->SCI_Tran_StateCB.SCI_TX_Result = ISO7816_ERR_NUM_OVER;
+            SCIx->SCIx7816->IS.bit.T_ERR = 1;
+        }
+        if (SCIx->SCIx7816->IS.bit.TFIFO_OVF == 1 )
+        {
+            SCIx->SCI_Tran_StateCB.SCI_TX_Result = ISO7816_ERR_NUM_OVER;
+            SCIx->SCIx7816->IS.bit.TFIFO_OVF = 1;
+        }
+
+        if ((SCIx->SCIx7816->IS.bit.RFIFO_OVF == 1) | (SCIx->SCIx7816->IS.bit.RFIFO_HA)  \
+            | (SCIx->SCIx7816->IS.bit.R_ERR == 1) | (SCIx->SCIx7816->IS.bit.BWT_TO == 1) |(SCIx->SCIx7816->IS.bit.CWT_TO ==1))
+        {
+            #ifdef DEBUG_7816_FPGA
+            MyPrintf("irq_SCI_State %08x \r\n", SCIx->SCI_Tran_StateCB.SCI_State);
+            MyPrintf("irq_sci isr= %08x \r\n", SCIx->SCIx7816->IS.reg);
+            MyPrintf("irq_sci ier= %08x \r\n", SCIx->SCIx7816->IE.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IES.reg);
+            MyPrintf("irq_sci ctrl2= %08x \r\n", SCIx->SCIx7816->CTRL2.reg);
+            #endif
+
+            SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &=~0x0f;
+            SCIx->SCIx7816->IS.reg = 0XFFFFFFFF;
+        }
+
+        if (ISO7816_Detect_Io_State() == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+        {
+           //config sci
+            SCIx->SCIx7816->IE.reg = 0;
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+            SCIx->SCIx7816->CTRL2.bit.TX_EN &=~1;
+            delay_ms(2);    //至少1字节时间
+            SCIx->SCIx7816->CTRL.bit.RFIFO_CL = 1;//clear tx/rx fifo
+            SCIx->SCIx7816->CTRL.bit.TFIFO_CL = 1;//clear tx/rx fifo
+            delay_ms(1);    //至少大于100us
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+            return ISO7816_CARD_ABSENT;
+        }
+    }
+
+#ifdef DEBUG_7816
+    MyPrintf("\n");
+#endif
+    return SCIx->SCI_Tran_StateCB.SCI_TX_Result;
+}
+
+/**
+  * @method ISO7816_RecBlock_DATA
+  * @brief  7816 T1 mode receive block data
+  * @param  RxBuf:  Receive Data buff
+  * @param  RxLen:  Receive Data length
+  * @retval OK :    0 on success
+  */
+uint16_t ISO7816_RecBlock_DATA(SCI_Struct_Type *SCIx,uint8_t *RxBuf, uint16_t RxLen)
+{
+    uint16_t  RemainLen = 0;
+    uint8_t waterlevel = 0;
+    uint16_t i=0;
+    uint16_t len = 0;
+    uint16_t index = 0;
+    uint16_t val = 0;
+    uint8_t rx_num = 0;
+
+    if ((!(RxLen)) || (NULL == RxBuf))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[0] = RxLen/0x100;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[1] = RxLen%0x100;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2] = 0;
+    SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3] = 0;
+    if (RxLen >= 8)
+    {
+        waterlevel = 4;
+    }
+    else
+    {
+        waterlevel = RxLen;
+    }
+
+    SCIx->SCI_Tran_StateCB.T1_parity_flag =0;
+    SCIx->SCI_Tran_StateCB.Card_Type = 1;
+    ISO7816_RX_APDU_Config(SCIx,waterlevel);
+
+    do
+    {
+       if (SCIx->SCIx7816->IS.bit.RFIFO_HA == 1)
+        {
+            len = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[0]*0x100 + SCIx->SCI_Tran_StateCB.SCI_RX_Buf[1];
+            index = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2]*0x100 + SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3];
+
+            rx_num = SCIx->SCIx7816->FIFO_CTRL.bit.R_ITEMS;
+            if(len > index)
+            {
+                val = len - index;
+                if (val <= rx_num)
+                {
+                    for (i = 0; i <val; i++)
+                    {
+                        SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4 + index++] = SCIx->SCIx7816->DATA.reg;
+                    }
+                }
+                else
+                {
+                    for (i = 0; i < rx_num; i++)
+                    {
+                        SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4 + index++] = SCIx->SCIx7816->DATA.reg;
+                    }
+                }
+            }
+
+            if(index >= len)
+            {
+                SCIx->SCI_Tran_StateCB.SCI_RX_Result = 1;  //rec finsh
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &=~0x0f;
+                SCIx->SCIx7816->IS.bit.RFIFO_HA = 1;
+            }
+            else if (((len - index) > 0) && ((len - index) < 4))
+            {
+
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL &=~0x0f;
+                SCIx->SCIx7816->FIFO_CTRL.bit.RH_WTL = (len - index);
+            }
+
+            SCIx->SCIx7816->IS.bit.RFIFO_HA = 1;
+
+            SCIx->SCI_Tran_StateCB.SCI_RX_Buf[2] = index/0x100;
+            SCIx->SCI_Tran_StateCB.SCI_RX_Buf[3] = index%0x100;
+        }
+
+        //rx flag
+        if ((SCIx->SCIx7816->IS.bit.CWT_TO ==1) || (SCIx->SCIx7816->IS.bit.BWT_TO == 1))
+        {
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_REC_TIMEOUT;
+            SCIx->SCIx7816->IS.bit.CWT_TO =1;
+            SCIx->SCIx7816->IS.bit.BWT_TO = 1;
+        }
+        if ((SCIx->SCIx7816->IS.bit.R_ERR == 1) && (SCIx->SCI_Tran_StateCB.Card_Type == 0))
+        {
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_ERR_NUM_OVER;
+            SCIx->SCIx7816->IS.bit.R_ERR = 1;
+        }
+        if ((SCIx->SCIx7816->IS.bit.R_ERR == 1) && (SCIx->SCI_Tran_StateCB.Card_Type == 1))
+        {
+            SCIx->SCI_Tran_StateCB.T1_parity_flag = 1;
+            SCIx->SCIx7816->IS.bit.R_ERR = 1;
+        }
+        if (SCIx->SCIx7816->IS.bit.RFIFO_OVF == 1)
+        {
+            #ifdef DEBUG_7816_FPGA
+            MyPrintf("sci isr %08x \r\n", SCIx->SCIx7816->IS.reg);
+            #endif
+            SCIx->SCI_Tran_StateCB.SCI_RX_Result = ISO7816_ERR_NUM_OVER;
+            SCIx->SCIx7816->IS.bit.RFIFO_OVF = 1;
+        }
+
+        if ((SCIx->SCIx7816->IS.bit.TFIFO_OVF == 1) | (SCIx->SCIx7816->IS.bit.TFIFO_LA)  | (SCIx->SCIx7816->IS.bit.T_ERR == 1) | (SCIx->SCIx7816->IS.bit.T_DONE == 1 ))
+        {
+            #ifdef DEBUG_7816_FPGA
+            MyPrintf("irq_SCI_State %08x \r\n", SCIx->SCI_Tran_StateCB.SCI_State);
+            MyPrintf("irq_sci isr= %08x \r\n", SCIx->SCIx7816->IS.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IE.reg);
+            MyPrintf("irq_sci iesr= %08x \r\n", SCIx->SCIx7816->IES.reg);
+            MyPrintf("irq_sci ctrl2= %08x \r\n", SCIx->SCIx7816->CTRL2.reg);
+            #endif
+
+            SCIx->SCIx7816->FIFO_CTRL.bit.TL_WTL &=~0x0f;
+            SCIx->SCIx7816->IS.reg = 0XFFFFFFFF;
+        }
+
+        if (ISO7816_Detect_Io_State() == SCIx->SCI_Tran_StateCB.Sci_Pin_Detect_State)
+        {
+            //config sci
+            SCIx->SCIx7816->IE.reg = 0;
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+            SCIx->SCIx7816->CTRL2.bit.RX_EN &=~1;
+            delay_ms(2);    //至少1字节时间
+            SCIx->SCIx7816->CTRL.bit.RFIFO_CL = 1;//clear tx/rx fifo
+            SCIx->SCIx7816->CTRL.bit.TFIFO_CL = 1;//clear tx/rx fifo
+            delay_ms(1);    //至少大于100us
+            SCIx->SCIx7816->IS.reg = 0xffffffff;
+            return ISO7816_CARD_ABSENT;
+        }
+
+        if (SCIx->SCI_Tran_StateCB.SCI_RX_Result == 1)
+        {
+            for (i=0; i<RxLen; i++)
+            {
+                *RxBuf++ = SCIx->SCI_Tran_StateCB.SCI_RX_Buf[4+i];
+            }
+
+            RemainLen = RxLen;
+        }
+        else if (SCIx->SCI_Tran_StateCB.SCI_RX_Result > 1)
+        {
+            return SCIx->SCI_Tran_StateCB.SCI_RX_Result;
+        }
+    }
+    while (RemainLen < (RxLen));
+
+    if (SCIx->SCI_Tran_StateCB.T1_parity_flag)
+    {
+        return ISO7816_PARITY_ERROR;
+    }
+    return OK;
+}
+
+/**
+  * @method ISO7816_SendBlock_Soft
+  * @brief  7816 T1 mode receive block data
+  * @param  RxBuf:  Receive Data buff
+  * @param  RxLen:  Receive Data length
+  * @retval OK :    0 on success
+  */
+uint16_t ISO7816_SendBlock_Soft(SCI_Struct_Type *SCIx,uint8_t *pBuff, uint16_t I_Len, uint8_t *pHead)
+{
+    uint16_t  ret;
+    uint8_t Lrc1, Lrc2;
+    uint8_t *pAddr;
+    uint16_t sendLen;
+    uint8_t DataBack = 0;
+    uint8_t sendData[SEND_SIZE_MAX];
+    uint16_t i = 0;
+
+    if ((NULL == pBuff) || (pHead == NULL))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    ISO7816_CalcLRC(pHead, 3, &Lrc1);
+
+    //发送数据
+    if (I_Len != 0)
+    {
+        ISO7816_CalcLRC(pBuff, I_Len, &Lrc2);
+        if (SCIx->g_T1.bLink != 0)
+        {
+            DataBack = pBuff[I_Len];
+        }
+        pBuff[I_Len] =  Lrc1 ^ Lrc2;
+        pAddr = pBuff;
+        sendLen = I_Len + 1;
+
+        for (i=0; i<3; i++)
+        {
+            sendData[i] = *pHead++;
+        }
+        for (i=0; i<sendLen; i++)
+        {
+            sendData[i+3] = *pAddr++;
+        }
+        ret = ISO7816_SendBytes_T1(SCIx,sendData, 3+sendLen);
+        COMPARE_RETURN(ret);
+    }
+    else
+    {
+        pHead[3] = Lrc1;
+        pAddr = pHead;
+        sendLen = 4;
+
+        ret = ISO7816_SendBytes_T1(SCIx,pAddr, sendLen);
+        COMPARE_RETURN(ret);
+    }
+
+    if ((SCIx->g_T1.bLink != 0) && (I_Len != 0))
+    {
+        pBuff[I_Len] = DataBack;
+    }
+    return OK;
+}
+
+void ISO7816_read_recfifo(SCI_Struct_Type *SCIx)
+{
+    uint16_t num = 0;
+
+    while (((SCIx->SCIx7816->STATUS.bit.RFIFO_N & 1) || (SCIx->SCIx7816->FIFO_CTRL.bit.R_ITEMS & 0xf)) && (num < 256))
+    {
+        SCIx->SCIx7816->DATA.bit.VAL;
+        num++;
+    }
+}
+
+uint16_t ISO7816_RecBlock_Soft(SCI_Struct_Type *SCIx,uint8_t *RxBuf, uint16_t *pRxLen)
+{
+    uint16_t  ret;
+    uint16_t tmpLen;
+    uint16_t RemainLen;
+    uint16_t RetBack;
+
+    if ((NULL == pRxLen) || (NULL == RxBuf))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    ret = ISO7816_RecBlock_DATA(SCIx,RxBuf, T1_HEAD_LEN);
+    if ((ret == ISO7816_REC_TIMEOUT) || (ret == ISO7816_PARA_ERROR))
+    {
+        return ret;
+    }
+
+    RetBack = ret;
+
+    if (RxBuf[T1_HEAD_LEN - 1] > SCIx->g_T1.bIFSD)
+    {
+        delay_ms(80);
+        ISO7816_read_recfifo(SCIx);
+        return ISO7816_DATALEN_ERR;
+    }
+
+    RemainLen = RxBuf[T1_HEAD_LEN - 1] + 1; //信息域 + LRC
+    ret = ISO7816_RecBlock_DATA(SCIx,RxBuf + T1_HEAD_LEN, RemainLen);
+    if (ret != OK)
+    {
+        return ret;
+    }
+
+    *pRxLen =  RemainLen + T1_HEAD_LEN;
+    tmpLen = *pRxLen - 1;
+
+    if (RetBack != OK)
+    {
+        return RetBack;
+    }
+
+    return ISO7816_CheckLRC(RxBuf, tmpLen, RxBuf[tmpLen]);
+}
+
+uint8_t ISO7816_T1_Is_Blk_Valid(SCI_Struct_Type *SCIx,uint8_t *pProlg, uint8_t dir)
+{
+    uint8_t Ret = 0;
+
+    if (pProlg[0] > 0)
+    {
+        Ret |= ERR_PCB;
+        return Ret;
+    }
+
+    if (0 == (pProlg[1] & 0x80))
+    {
+
+        if ((pProlg[1] & 0x1F) > 0)
+        {
+            Ret |= ERR_PCB;
+            return Ret;
+        }
+        if ((pProlg[1] & NS_BIT) != SCIx->g_T1.bNumCard)
+        {
+            Ret |= ERR_PCB;
+            return Ret;
+        }
+
+        //判断长度
+        if ((pProlg[2] > SCIx->g_T1.bIFSD) || (pProlg[2] == 0))
+        {
+            if (pProlg[2] == 0xff)
+            {
+                Ret |= ERR_FF;
+            }
+            else
+            {
+                Ret |= ERR_LEN;
+            }
+
+            return Ret;
+        }
+
+        if (SCIx->g_T1.bFlagSendChain)
+        {
+            Ret |= ERR_PCB;
+            return Ret;
+        }
+    }
+    else if (R_BLK == (pProlg[1] & 0xC0))
+    {
+        if ((pProlg[1] & 0x20) != 0)
+        {
+            Ret |= ERR_PCB;
+            return Ret;
+        }
+
+        if ((pProlg[1] & 0x0F) > 2)
+        {
+            Ret |= ERR_PCB;
+            return Ret;
+        }
+
+        if (pProlg[2] > 0)
+        {
+            Ret |= ERR_LEN;
+            return Ret;
+        }
+
+        if (dir == RECV)
+        {
+            if (((pProlg[1] & NR_BIT) << 2) == SCIx->g_T1.bNum)
+            {
+                if (0 == SCIx->g_T1.bLink)
+                {
+                    SCIx->g_T1.bErrNotify = 1;
+                    Ret |= ERR_PCB;
+                    return Ret;
+                }
+            }
+        }
+        else
+        {
+            if (((pProlg[1] & NR_BIT) << 2) != SCIx->g_T1.bNum)
+            {
+                SCIx->g_T1.bErrNotify = 1;
+                Ret |= ERR_PCB;
+                return Ret;
+            }
+        }
+
+    }
+    else if (S_BLK == (pProlg[1] & 0xC0))
+    {
+        if ((pProlg[1] & 0x1C) > 0)
+        {
+            Ret |= ERR_PCB;
+            return Ret;
+        }
+        if (((pProlg[1] & 0x20) > 0) && (0 == SCIx->g_T1.bFlgSBSnd))
+        {
+            Ret |= ERR_PCB;
+            return Ret;
+        }
+
+        //判断长度
+        if (0 == (pProlg[1] & 0x1))
+        {
+            if (pProlg[2] > 0)
+            {
+                Ret |= ERR_LEN;
+                return Ret;
+            }
+        }
+        else
+        {
+            if (pProlg[2] != 1)
+            {
+                Ret |= ERR_LEN;
+                return Ret;
+            }
+
+            if ((1 == (pProlg[1] & 0x03)) && ((pProlg[3] == 0xff) || (pProlg[3] < 0x10)))
+            {
+                Ret |= ERR_LEN;
+                return Ret;
+            }
+        }
+    }
+    else
+    {
+
+    }
+
+    if (SCIx->g_T1.bFlgSBSnd != 0)
+    {
+        if (0 == (pProlg[1] & 0x80))
+        {
+            Ret |= ERR_RELVNT_S;
+            return Ret;
+        }
+    }
+
+    return Ret;
+}
+
+/**
+  * @method ISO7816_TPDU_T1Rec_LOOP
+  * @brief  7816 T1 mode TPDU data receiving function
+  * @param  *pRec:         Receiving data storage unit
+  * @param  *RecLen:        Receiving data length
+  * @retval OK:            0 on success
+  */
+uint16_t ISO7816_TPDU_T1Rec_LOOP(SCI_Struct_Type *SCIx,uint8_t *pRec, uint16_t *RecLen)
+{
+    uint16_t Ret;
+    uint8_t r_cnt = 0;
+    uint8_t ifs_cnt = 0;
+    uint8_t s_blk[5];
+    uint16_t tmpRecLen;
+    uint8_t SWTXFlag = 0;
+
+    if (SCIx->g_T1.bFlgIRec == 1)
+    {
+        SCIx->g_T1.bFlgIRec = 0;
+
+        memcpy(pRec, &SCIx->g_7816Para.aRecBuff[3],  SCIx->g_7816Para.aRecBuff[2]);
+        *RecLen = SCIx->g_7816Para.aRecBuff[2];
+    }
+    else
+    {
+        while (1)
+        {
+            if (SCIx->g_T1.bFlgSRec == 1)
+            {
+                SCIx->g_T1.bFlgSRec = 0;
+            }
+            else
+            {
+                //接收数据
+                Ret = ISO7816_RecBlock_Soft(SCIx , SCIx->g_7816Para.aRecBuff, &tmpRecLen);
+                //如果校验错误，则直接跳过检查
+                if (Ret == OK)
+                {
+                    Ret = ISO7816_T1_Is_Blk_Valid(SCIx , SCIx->g_7816Para.aRecBuff, RECV);
+                }
+                else if ((Ret == ISO7816_T1_LRC_ERROR) || (Ret == ISO7816_PARITY_ERROR))
+                {
+                    Ret = ERR_CHKSUM;
+                }
+                else if (Ret == ISO7816_DATALEN_ERR)
+                {
+                    Ret = ERR_FF;//ERR_LEN;;
+                }
+                else
+                {
+                    return Ret;
+                }
+
+                //恢复WTX
+                if (SWTXFlag == 1)
+                {
+                    SCIx->SCI_Tran_StateCB.terminal_rec_bwt = SCIx->SCI_Tran_StateCB.terminal_rec_bwt_atr;
+                    SWTXFlag = 0;
+                    ISO7816_TXRX_TIME_Init(SCIx);
+                }
+
+                /*无效则发R/S*/
+                if (Ret != 0)
+                {
+                    SCIx->g_T1.bErrCnt++;
+
+                    if ((ifs_cnt + SCIx->g_T1.bErrCnt) <= 1)
+                    {
+                        SCIx->g_T1.aRBlk[0] = 0;    //g_Nad;
+                        SCIx->g_T1.aRBlk[1] = 0x80 | (SCIx->g_T1.bNumCard >> 2);
+                        SCIx->g_T1.aRBlk[2] = 0;
+                        if (SCIx->g_T1.bRecRBLink == 0)
+                        {
+                            if (Ret & (ERR_PCB | ERR_LEN | ERR_RELVNT_S))
+                            {
+                                SCIx->g_T1.aRBlk[1] |= 2;
+                            }
+                            else if (Ret & (ERR_PARITY | ERR_CHKSUM))
+                            {
+                                SCIx->g_T1.aRBlk[1] |= 1;
+                            }
+                            else
+                            {
+                                return ISO7816_ERR_NUM_OVER;
+                            }
+                        }
+                        else
+                        {
+                            if ((Ret == ERR_FF) && (SCIx->g_7816Para.aRecBuff[2] == 0xff))
+                            {
+                                return ISO7816_ERR_NUM_OVER;
+                            }
+                        }
+                    }
+
+                    if (SCIx->g_T1.bErrCnt < ERR_SEND_CNT)
+                    {
+                        if (SCIx->g_7816Para.aRecBuff[1] & 0x80)
+                        {
+                            Ret = ISO7816_SendBlock_Soft(SCIx , &SCIx->g_T1.aRBlk[3], 0, SCIx->g_T1.aRBlk);
+                            COMPARE_RETURN(Ret);
+                        }
+                        else
+                        {
+                            if (SCIx->g_T1.bRecRBLink != 0)
+                            {
+                                if (SCIx->g_T1.bErrCnt < (ERR_SEND_CNT - 1))
+                                {
+                                    Ret = ISO7816_SendBlock_Soft(SCIx , &SCIx->g_T1.aRBlk[3], 0, SCIx->g_T1.aRBlk);
+                                    COMPARE_RETURN(Ret);
+                                }
+                                else
+                                {
+                                    return ISO7816_ERR_NUM_OVER;
+                                }
+                            }
+                            else
+                            {
+                                Ret = ISO7816_SendBlock_Soft(SCIx , &SCIx->g_T1.aRBlk[3], 0, SCIx->g_T1.aRBlk);
+                                COMPARE_RETURN(Ret);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        return ISO7816_ERR_NUM_OVER;
+                    }
+                    continue;
+                }
+                SCIx->g_T1.bErrCnt = 0;
+            }
+
+            if (R_BLK == (SCIx->g_7816Para.aRecBuff[1] & 0xC0))
+            {
+                SCIx->g_T1.aRBlk[0] = 0;
+                SCIx->g_T1.aRBlk[1] = 0x80 | (SCIx->g_T1.bNumCard >> 2);
+                SCIx->g_T1.aRBlk[2] = 0;
+                if (r_cnt < ERR_SEND_CNT)
+                {
+                    Ret = ISO7816_SendBlock_Soft(SCIx , &SCIx->g_T1.aRBlk[3], 0, SCIx->g_T1.aRBlk);
+                    COMPARE_RETURN(Ret);
+                    continue;
+                }
+                r_cnt++;
+                return ISO7816_ERR_NUM_OVER;
+            }
+            else if (S_BLK == (SCIx->g_7816Para.aRecBuff[1] & 0xC0))
+            {
+                s_blk[0] = 0;
+                s_blk[1] = 0xC0;
+                if (0 == (SCIx->g_7816Para.aRecBuff[1] & S_RQS_MSK))
+                {
+                    s_blk[1] |= 0x20;
+                    s_blk[2]  = 0;
+                    SCIx->g_T1.bLink = 0;
+                    SCIx->g_T1.bNum = 0;
+                    SCIx->g_T1.bNumCard = 0;
+                    SCIx->g_T1.bIFSC = IFSC;
+                    SCIx->g_T1.bIFSD = IFSC;
+
+                    Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], 0, s_blk);
+                    COMPARE_RETURN(Ret);
+                    continue;
+                }
+                else if (1 == (SCIx->g_7816Para.aRecBuff[1] & S_RQS_MSK))
+                {
+                    s_blk[1] |= 0x21;
+                    s_blk[2]  = 1;
+                    s_blk[3]  = SCIx->g_7816Para.aRecBuff[3];
+                    if ((0x10 > SCIx->g_7816Para.aRecBuff[3]) || (0xFF == SCIx->g_7816Para.aRecBuff[3]))
+                    {
+                        ifs_cnt++;
+
+                        if (SCIx->g_T1.bErrCnt < 1)
+                        {
+                            SCIx->g_T1.aRBlk[0] = 0;
+
+                            SCIx->g_T1.aRBlk[1] = 0x82 | (SCIx->g_T1.bNumCard >> 2);
+
+                            SCIx->g_T1.aRBlk[2] = 0;
+                        }
+
+                        if ((ifs_cnt + SCIx->g_T1.bErrCnt) < ERR_SEND_CNT)
+                        {
+                            Ret = ISO7816_SendBlock_Soft(SCIx , &SCIx->g_T1.aRBlk[3], 0, SCIx->g_T1.aRBlk);
+                            COMPARE_RETURN(Ret);
+                            continue;
+                        }
+                        return ISO7816_ERR_NUM_OVER;
+                    }
+                    else
+                    {
+                        if (s_blk[3] != SCIx->g_7816Para.aRecBuff[3])
+                        {
+                            Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], 1, s_blk);
+                            COMPARE_RETURN(Ret);
+                            continue;
+                        }
+                        else
+                        {
+                            SCIx->g_T1.bIFSC = SCIx->g_7816Para.aRecBuff[3];
+                        }
+                    }
+
+                    if (ifs_cnt < ERR_SEND_CNT)
+                    {
+                        Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], 1, s_blk);
+                        COMPARE_RETURN(Ret);
+                    }
+                    continue;
+                }
+                else if (2 == (SCIx->g_7816Para.aRecBuff[1] & S_RQS_MSK))
+                {
+                    s_blk[1] |= 0x22;
+                    s_blk[2]  = 0;
+                    Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], 0, s_blk);
+                    COMPARE_RETURN(Ret);
+
+                    return ISO7816_RET_BROKEN_CHAIN;
+                }
+                else if ((SCIx->g_7816Para.aRecBuff[1] & 0x3F) == 3)
+                {
+                    SWTXFlag = 1;
+                    //设置等待时间
+                    SCIx->SCI_Tran_StateCB.terminal_change_rec_bwt_num = SCIx->SCI_Tran_StateCB.terminal_rec_bwt_atr * SCIx->g_7816Para.aRecBuff[3];
+                    SCIx->SCI_Tran_StateCB.terminal_rec_bwt = SCIx->SCI_Tran_StateCB.terminal_change_rec_bwt_num;
+                    ISO7816_TXRX_TIME_Init(SCIx);
+                    #ifdef DEBUG_7816
+                    MyPrintf("WTS\n");
+                    MyPrintf("%08x", SCIx->SCI_Tran_StateCB.terminal_rec_bwt);
+                    MyPrintf("\n");
+                    MyPrintf("%08x", SCIx->g_7816Para.aRecBuff[3]);
+                    MyPrintf("\n");
+                    MyPrintf("%08x", SCIx->SCI_Tran_StateCB.terminal_change_rec_bwt_num);
+                    MyPrintf("\n");
+                    #endif
+
+                    s_blk[1] |= 0x23;
+                    s_blk[2]  = 1;
+                    s_blk[3]  = SCIx->g_7816Para.aRecBuff[3];
+                    Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], 1, s_blk);
+                    COMPARE_RETURN(Ret);
+                    continue;
+                }
+                else
+                {
+                    continue;
+                }
+            }
+            else
+            {
+                memcpy(pRec, &SCIx->g_7816Para.aRecBuff[3],  SCIx->g_7816Para.aRecBuff[2]);
+                *RecLen = SCIx->g_7816Para.aRecBuff[2];
+            }
+            break;
+        }
+    }
+    r_cnt = 0;
+
+    if (R_BLK == (SCIx->g_7816Para.aRecBuff[1] & 0xC0))
+    {
+
+    }
+    else if (S_BLK == (SCIx->g_7816Para.aRecBuff[1] & 0xC0))
+    {
+
+    }
+    else
+    {
+        SCIx->g_T1.bNumCard ^= BIT6;
+        SCIx->g_T1.bErrCnt = 0;
+
+        if (M_BIT == (SCIx->g_7816Para.aRecBuff[1] & M_BIT))
+        {
+            SCIx->g_T1.bRecRBLink = 1;
+
+            SCIx->g_T1.aRBlk[0] = 0 ;
+            SCIx->g_T1.aRBlk[1] = 0x80;
+            if ((SCIx->g_7816Para.aRecBuff[1] & NS_BIT) == 0)
+            {
+                SCIx->g_T1.aRBlk[1] |= NR_BIT;
+            }
+            SCIx->g_T1.aRBlk[2] = 0;
+
+            Ret = ISO7816_SendBlock_Soft(SCIx , &SCIx->g_T1.aRBlk[3], 0, SCIx->g_T1.aRBlk);
+            COMPARE_RETURN(Ret);
+
+            return ISO7816_RET_CHAIN;
+        }
+        else
+        {
+            SCIx->g_T1.bRecRBLink = 0;
+        }
+
+    }
+    SCIx->g_T1.bErrCnt = 0;
+    return OK;
+}
+
+/**
+  * @method ISO7816_TPDU_T1Send_LOOP
+  * @brief  7816 T1 mode TPDU data sending function
+  * @param  pCommand:      Sending data storage unit
+  * @param  CommandLength: Sending data length
+  * @param  Type:          Link block type
+  * @retval OK:            0 on success
+  */
+uint16_t ISO7816_TPDU_T1Send_LOOP(SCI_Struct_Type *SCIx , uint8_t *pCommand, uint16_t CommandLength, uint8_t Type)
+{
+    uint16_t Ret;
+    uint16_t SendLen = 0;
+    uint16_t RecLen;
+    uint16_t TmpLen = 0;
+    uint8_t  r_cnt = 0;
+    uint8_t  r_chain_cnt = 0;
+    uint8_t  *pSend = NULL;
+    uint8_t  prolHead[3];
+    uint8_t  s_blk[5];
+    uint8_t  resendflag = 0;
+    uint8_t SWTXFlag = 0;
+
+    uint8_t IFS_issued = 1;
+
+    uint16_t CmdLen = CommandLength;
+
+    SCIx->g_T1.bFlagSendChain = 0;
+
+    if ((NULL == pCommand) || (Type > 4))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    //初始化化
+    if (Type == I_BLOCK_C)
+    {
+        prolHead[0] = 0;  //nad
+        prolHead[1] = 0;  //pcd
+
+        //设置序号 bNum 为BIT6
+        prolHead[1] ^= SCIx->g_T1.bNum;
+
+        //计算I块长度
+        if (SCIx->g_T1.bIFSC < CmdLen)
+        {
+            //需要连接
+            prolHead[1] |= BIT5;
+            prolHead[2] = SCIx->g_T1.bIFSC;
+            CmdLen -= SCIx->g_T1.bIFSC;
+            SendLen = SCIx->g_T1.bIFSC;
+            SCIx->g_T1.bFlagSendChain = 1;
+            SCIx->g_T1.bLink = 1;
+        }
+        else
+        {
+            prolHead[2] = CmdLen;
+            SendLen = CmdLen;
+            CmdLen = 0;
+        }
+
+        pSend = pCommand;
+    }
+
+    SCIx->g_T1.bFlgSBSnd = 0;
+    //发送数据
+    while (1)
+    {
+        if (Type < S_BLOCK_C)
+        {
+            Ret = ISO7816_SendBlock_Soft(SCIx , pSend, SendLen, prolHead);
+            COMPARE_RETURN(Ret);
+
+            if (resendflag == 0)
+            {
+                SCIx->g_T1.bNum ^= BIT6;
+            }
+        }
+        else
+        {
+            s_blk[0] = 0;
+            s_blk[1] = 0xC0;
+            TmpLen = 0;
+            if (T_S_IFS == Type)
+            {
+                s_blk[1] |= 0x1;
+                s_blk[2]  = 1;
+                s_blk[3]  = pCommand[0];
+
+                SCIx->g_T1.bIFSD = pCommand[0];
+
+                TmpLen++;
+            }
+            else if (T_S_ABORT == Type)
+            {
+                s_blk[1] |= 0x2;
+                s_blk[2]  = 0;
+            }
+            else
+            {
+
+            }
+
+            Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], TmpLen, s_blk);
+            COMPARE_RETURN(Ret);
+
+            SCIx->g_T1.bFlgSBSnd = 1;
+        }
+        if (!resendflag)
+        {
+            SCIx->g_T1.bErrCnt = 0;
+        }
+
+        while (1)
+        {
+
+            Ret = ISO7816_RecBlock_Soft(SCIx , SCIx->g_7816Para.aRecBuff, &RecLen);
+
+            SCIx->g_T1.bErrNotify = 0;
+
+            if (Ret == OK)
+            {
+                Ret = ISO7816_T1_Is_Blk_Valid(SCIx , SCIx->g_7816Para.aRecBuff, RECV);
+            }
+            else if ((Ret == ISO7816_T1_LRC_ERROR) || (Ret == ISO7816_PARITY_ERROR))
+            {
+                Ret = ERR_CHKSUM;
+            }
+            else if (Ret == ISO7816_DATALEN_ERR)
+            {
+                Ret = ERR_FF;//ERR_LEN;
+            }
+            else if (Ret == ISO7816_NOTLRC_ERROR)
+            {
+                Ret = ERR_LEN;
+            }
+            else
+            {
+                return Ret;
+            }
+
+            //恢复WTX
+            if (SWTXFlag == 1)
+            {
+                SCIx->SCI_Tran_StateCB.terminal_rec_bwt = SCIx->SCI_Tran_StateCB.terminal_rec_bwt_atr;
+                SWTXFlag = 0;
+                ISO7816_TXRX_TIME_Init(SCIx);
+            }
+
+            if (Ret != 0)
+            {
+                if (!SCIx->g_T1.bErrNotify)
+                {
+                    SCIx->g_T1.bErrCnt++;
+                }
+                if (Type < S_BLOCK_C)
+                {
+                    if (((SCIx->g_T1.bErrCnt <= 1) && ((!SCIx->g_T1.bErrNotify)))
+                            || ((SCIx->g_T1.bErrCnt == 0) && ((SCIx->g_T1.bErrNotify))))
+                    {
+                        SCIx->g_T1.aRBlk[0] = 0;
+                        SCIx->g_T1.aRBlk[1] = 0x80 | (SCIx->g_T1.bNumCard >> 2);
+                        SCIx->g_T1.aRBlk[2] = 0;
+                        if (Ret & (ERR_PCB | ERR_LEN | ERR_RELVNT_S))
+                        {
+                            SCIx->g_T1.aRBlk[1] |= 2;
+                        }
+                        else if (Ret & (ERR_PARITY | ERR_CHKSUM))
+                        {
+                            SCIx->g_T1.aRBlk[1] |= 1;
+                        }
+                        else
+                        {
+                            return ISO7816_ERR_NUM_OVER;
+                        }
+                    }
+                    if (SCIx->g_T1.bErrCnt < ERR_SEND_CNT)
+                    {
+                        Ret = ISO7816_SendBlock_Soft(SCIx , &SCIx->g_T1.aRBlk[3], 0, SCIx->g_T1.aRBlk);
+                        COMPARE_RETURN(Ret);
+                    }
+                }
+                else
+                {
+                    if (SCIx->g_T1.bErrCnt < ERR_SEND_CNT)
+                    {
+                        Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], TmpLen, s_blk);
+                        COMPARE_RETURN(Ret);
+                    }
+                }
+
+                if (SCIx->g_T1.bErrCnt >= ERR_SEND_CNT)
+                {
+                    return ISO7816_ERR_NUM_OVER;
+                }
+                continue;
+            }
+
+            //if ((0xC2 == (SCIx->g_7816Para.aRecBuff[1] * 0x80)) && (g_T1.bFlagSendChain))
+            if ((0xC2 == SCIx->g_7816Para.aRecBuff[1]) && (SCIx->g_T1.bFlagSendChain))
+            {
+                s_blk[0] = 0;
+                s_blk[1] = 0xE2;
+                s_blk[2] = 0;
+                Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], 0, s_blk);
+                COMPARE_RETURN(Ret);
+                continue;
+            }
+
+            if ((SCIx->g_7816Para.aRecBuff[1] == 0xc3) && (SCIx->g_T1.bFlagSendChain != 0))
+            {
+                SWTXFlag = 1;
+
+                //设置等待时间
+                SCIx->SCI_Tran_StateCB.terminal_change_rec_bwt_num = SCIx->SCI_Tran_StateCB.terminal_rec_bwt_atr * SCIx->g_7816Para.aRecBuff[3];
+                SCIx->SCI_Tran_StateCB.terminal_rec_bwt = SCIx->SCI_Tran_StateCB.terminal_change_rec_bwt_num;
+                ISO7816_TXRX_TIME_Init(SCIx);
+                #ifdef DEBUG_7816
+                MyPrintf("WTS\n");
+                MyPrintf("%08x", SCIx->SCI_Tran_StateCB.terminal_rec_bwt);
+                MyPrintf("\n");
+                MyPrintf("%08x", SCIx->g_7816Para.aRecBuff[3]);
+                MyPrintf("\n");
+                MyPrintf("%08x", SCIx->SCI_Tran_StateCB.terminal_change_rec_bwt_num);
+                MyPrintf("\n");
+                #endif
+
+                s_blk[0] = 0x0;
+                s_blk[1] = 0xE3;
+                s_blk[2]  = 1;
+                s_blk[3]  = SCIx->g_7816Para.aRecBuff[3];
+                Ret = ISO7816_SendBlock_Soft(SCIx , &s_blk[3], 1, s_blk);
+                COMPARE_RETURN(Ret);
+
+                continue;
+            }
+            break;
+        }
+
+        if (R_BLK == (SCIx->g_7816Para.aRecBuff[1] & 0xC0))
+        {
+            r_cnt++;
+            if (SCIx->g_T1.bFlagSendChain)
+            {
+                r_cnt = 0;
+                r_chain_cnt++;
+                if ((SCIx->g_7816Para.aRecBuff[1] & NR_BIT) == (SCIx->g_T1.bNum >> 2)) /*nr!=ns, 对方请求下一个frame*/
+                {
+                    r_chain_cnt = 0;
+
+                    pSend += SendLen;
+                    prolHead[0]  = 0;
+                    prolHead[1]  = 0;
+                    prolHead[1] |= SCIx->g_T1.bNum;
+
+                    if (SCIx->g_T1.bIFSC < CmdLen)
+                    {
+                        prolHead[1] |= BIT5;
+                        prolHead[2] = SCIx->g_T1.bIFSC;
+                        CmdLen -= SCIx->g_T1.bIFSC;
+                        SendLen = SCIx->g_T1.bIFSC;
+                        SCIx->g_T1.bLink = 1;
+                    }
+                    else
+                    {
+                        prolHead[2] = CmdLen;
+                        SendLen = CmdLen;
+                        CmdLen = 0;
+                        SCIx->g_T1.bFlagSendChain = 0;
+                        SCIx->g_T1.bLink = 0;
+                    }
+                }
+                else
+                {
+                    SCIx->g_T1.bNum ^= BIT6;
+                }
+                resendflag = 0;
+            }
+            else
+            {
+                resendflag = 1;
+            }
+
+            if ((r_cnt >= ERR_SEND_CNT) || (r_chain_cnt >= ERR_SEND_CNT))
+            {
+                return ISO7816_ERR_NUM_OVER;
+            }
+        }
+        else if (S_BLK == (SCIx->g_7816Para.aRecBuff[1] & 0xC0))
+        {
+            if (Type < S_BLOCK_C)
+            {
+                SCIx->g_T1.bFlgSRec = 1;
+            }
+            else
+            {
+                if (IFS_issued)
+                {
+                    if ((0x21 != (SCIx->g_7816Para.aRecBuff[1] & S_RSP_MSK))
+                            || (SCIx->g_7816Para.aRecBuff[3] != pCommand[0]))
+                    {
+                        resendflag = 1;
+                        SCIx->g_T1.bErrCnt++;
+                        continue;
+                    }
+                    IFS_issued = 0;
+                }
+
+                if (0x21 == (SCIx->g_7816Para.aRecBuff[1] & S_RSP_MSK))
+                {
+                    if (SCIx->g_7816Para.aRecBuff[3] == pCommand[0])
+                    {
+                        SCIx->g_T1.bIFSD = pCommand[0];
+                    }
+                    else
+                    {
+                        resendflag = 1;
+                        continue;
+                    }
+                }
+                else if (0x22 == (SCIx->g_7816Para.aRecBuff[1] & S_RSP_MSK))
+                {
+
+                }
+
+                else if (0x23 == (SCIx->g_7816Para.aRecBuff[1] & S_RSP_MSK))
+                {
+                    if (SCIx->g_7816Para.aRecBuff[3] == pCommand[0])
+                    {
+                        return ISO7816_RET_RESPONSE_DIFFERENT;
+                    }
+                }
+                else
+                {
+
+                }
+            }
+            break;
+
+        }
+        else
+        {
+            SCIx->g_T1.bFlgIRec = 1;
+            break;
+        }
+    }
+
+    return OK;
+}
+
+uint16_t ISO7816_TPDU_T1(SCI_Struct_Type *SCIx,uint8_t *pCommand, uint16_t CommandLength,
+                         uint8_t *pResponse,  uint16_t *pResponseLength)
+{
+    uint16_t Ret;
+    uint16_t RecLen = 0;
+    uint8_t RecvBuf[REC_SIZE_MAX];
+    uint8_t *pRecBuf = RecvBuf;
+
+    if ((NULL == pCommand) || (NULL == pResponse) ||
+            (CommandLength < 1) || (NULL == pResponseLength))
+    {
+        return ISO7816_PARA_ERROR;
+    }
+
+    Ret = ISO7816_TPDU_T1Send_LOOP(SCIx , pCommand, CommandLength, I_BLOCK_C);
+    COMPARE_RETURN(Ret);
+
+    *pResponseLength = 0;
+    do
+    {
+        Ret = ISO7816_TPDU_T1Rec_LOOP(SCIx,pRecBuf, &RecLen);
+        if ((OK != Ret) && (ISO7816_RET_CHAIN != Ret))
+        {
+            return ISO7816_T1_TRANSFER_ERROR;
+        }
+        if (REC_SIZE_MAX < RecLen)
+        {
+            return ISO7816_T1_TRANSFER_ERROR;
+        }
+        pRecBuf += RecLen;
+        *pResponseLength += RecLen;
+    }
+    while (ISO7816_RET_CHAIN == Ret);
+
+    memcpy(pResponse, RecvBuf, *pResponseLength);
+
+    return OK;
+}
