/*****************************************************************************
* File Name          : ISO14443A_Function.c
* Author             : CrystalSu
* Version            : V1.0.0.0
* Date               : Feb 12, 2020
* Description        : 
*                         - ISO14443B_Transparent_Configure_CRC
*                         - ISO14443A_EMV_Load_Modulation
*                         - ISO14443A_Polling_Tags
*                         - ISO14443A_NFC_Type1_Read_UID
*                         - ISO14443A_NFC_Type1_Read_All_Byte
*                         - ISO14443A_NFC_Type1_Read_Single_Byte
*                         - ISO14443A_NFC_Type1_Write_With_Erase
*                         - ISO14443A_NFC_Type1_Write_No_Erase
*                         - ISO14443A_Write_Ultralight
*                         - ISO14443A_3DES_Authent_Ultralight
*                         - ISO14443A_3DES_Authent_Ultralight_LoadKey
*                         - ISO14443A_3DES_Authent_Ultralight_TxCMD
*                         - ISO14443A_3DES_Authent_Ultralight_TxEncipher
*                         - ISO14443A_Transparent_With_RxMultiple
******************************************************************************/                       

#include "BC45_Board_Define.h"
#include "ISO14443A_Category.h"
#include "BC45_Chip_Function.h"
#include "Delay.h"
#include "stdlib.h"	// use for function rand() in ISO14443A_3DES_Authent_Ultralight();
#include "ISO14443B_Category.h" 
	/* Refer to following functions in ISO14443A_Polling_Tags();
		- ISO14443B_Config
		- ISO14443B_WakeUp
		- ISO14443B_EMV_Load_Modulation
	*/
#include "ISO15693_Category.h"  
	/* Refer to following functions in ISO14443A_Polling_Tags();
		- ISO15693_Config
		- ISO15693_Inv_Req_1_Slot
	*/

// Global variable 
tISO14443A_Property  ISO14443A_Property ;
extern volatile uint8_t   BC_Chip_Type ;

//#define ISO14443A_EMV_LOAD_MOD_ENABLE;
//#define ISO14443A_DES_ENABLE
//#define ISO14443A_DES_LOADKEY_ENABLE

#ifdef ISO14443A_DES_ENABLE
#include "DES.h"
#endif

/*******************************************************************************
* Function Name : ISO14443A_Command
* Description   : Perform 
*				  	- air interface commands following ISO14443A and MIFARE
*					- setting up ISO14443A configuration
*					- setting and getting RF communication speed
*					- loading MIFARE key to Master key buffer
*			
* Input         : 	- Command : Commands associated to ISO14443A and MIFARE as shown in source below 
*					- Param	: Parameters associated to command as shown in source below (after CMD_TYPE)
*					- LenParam : Length of input parameters
* Output        : 
*					- Data_Resp	: Reponse from operation the command
*					- LenData_Resp : Length of output response
* Return        : 
*				   - Response : Result from operating the function
*				 	 	- _SUCCESS_ 
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Command( uint8_t Command, uint8_t *Param, uint16_t LenParam, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t  i ;
	uint8_t  Resp ;
	uint8_t  temp_NumColl, temp_CollPos[64] ;
	uint8_t  temp_UID[10] ;
	uint8_t  temp_Value[4] ;

	switch(Command)
	{
		case A_Config_ISO14443A :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				ISO14443A_Property.Speed = 0x00 ;
				Resp = ISO14443A_Config( 0x00 ) ;
				*(LenData_Resp) = 0 ; 
				break ;

		case A_Config_Speed_Reader :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Speed_Sel + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 1 )
				{	
					// Param = Speed ( 1 Byte ) 
					ISO14443A_Property.Speed = *( Param ) ;
					BC45_Speed_14443A( ISO14443A_Property.Speed ) ;
					Resp = _SUCCESS_ ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
				*(LenData_Resp) = 0 ; 
				break ;
		
		case A_Get_Speed_Reader : // Speed at Reader
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + Speed + LRC									
				Resp = ISO14443A_Get_Speed_Reader( Data_Resp, LenData_Resp ) ;
		break ;

		//-----------------------------------------------------------------------------------------------------------------//

		case A_Request :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				Resp = ISO14443A_Request( Data_Resp, LenData_Resp ) ;
				break ;

		case A_WakeUp :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				Resp = ISO14443A_WakeUp( Data_Resp, LenData_Resp ) ;
				break ;
		
		case A_Anticoll :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Level + CollMaskVal + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 2 )
				{ 
					// Param = Level( 1 Byte ) + CollMaskVal ( 1 Byte ) = 2 Bytes
					Resp = ISO14443A_Anticoll( *( Param ), *( Param + 1 ), &temp_NumColl, temp_CollPos, Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;

		case A_Anticoll_Check :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Level + CollMaskVal + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 2 )
				{ 
					// Param = Level( 1 Byte ) + CollMaskVal ( 1 Byte ) = 2 Bytes
					Resp = ISO14443A_Anticoll( *( Param ), *( Param + 1 ), Data_Resp, (Data_Resp + 1), temp_UID, LenData_Resp ) ;
					for( i = 0 ; i < *( LenData_Resp ) ; i++ )
					{
						*( Data_Resp + *(Data_Resp) + i + 1 ) =  temp_UID[i]  ;  	
					}
					*( LenData_Resp ) = *(Data_Resp) + *(LenData_Resp) + 1 ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;

		case A_Select :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Level + UID[0] + ... + UID[3] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 5 )  // Level + UID[0] + ... + UID[3] -- > 5 Byte
				{ 
					// Param = Level( 1 Byte ) + UID ( 4 Bytes ) = 5 Bytes
					Resp = ISO14443A_Select( *( Param ), (Param + 1), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Halt :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				Resp = ISO14443A_Halt( Data_Resp, LenData_Resp ) ;
				break ;

		case A_RATS :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Parameter_Byte + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 1 )  // Parameter_Byte -- > 1 Byte
				{ 
					// Param = Parameter_Byte( 1 Byte ) = 1 Bytes
					Resp = ISO14443A_RATS( *( Param ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_PPS :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + CID + PPS0 + PPS1 + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 1 )  // Parameter_Byte -- > 3 Byte
				{ 
					// Param = CID( 1 Byte ) + PPS0( 1 Byte ) + PPS1( 1 Byte ) = 3 Bytes
					Resp = ISO14443A_PPS( *( Param ), *( Param + 1 ), *( Param + 2 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;
				
// -------------------------------------------------- Mifare Classic Cmd -----------------------------------------------------------------------------------------//

		case A_Loadkey :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Key[0] + ... + Key[5] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 6 )  // Key 6 Bytes
				{ 
					// Param = Key( 6 Bytes ) = 6 Bytes
					Resp = ISO14443A_Load_Key( Param ) ;
					*(LenData_Resp) = 0 ; 
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;
	
		case A_LoadkeyE2 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Start_Addr + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 1 )
				{ 
					Resp = BC45_LoadKeyE2( *( Param ) ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
				*( LenData_Resp ) = 0 ; 
				break ;

		case A_Authentication :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Sel_Key + Block_Num + UID[0] + ... + UID[3] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 6 )  // Sel_Key + Block_Num + UID( 4 bytes ) = 6 Bytes
				{ 
					// Param = Sel_Key( 1 Byte ) + Block_Num( 1 Byte ) + UID( 4 Bytes ) = 6 Bytes
					Resp = ISO14443A_Authentication( *( Param ), *( Param + 1 ), ( Param + 2 ), (uint8_t)( LenParam - 2 ) ) ;
					*(LenData_Resp) = 0 ; 
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Read_Block :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 1 )  // Block Addr = 1 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) = 1 Byte
					Resp = ISO14443A_Read_Mifare_Block( *( Param ), Data_Resp, LenData_Resp, CHECK_ENABLE ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Write_Block :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Data_Wr[0] + ... +  Data_Wr[15] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 17 )  // Block Addr + Data_Wr ( 16 Bytes ) = 17 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Data_Wr( 16 Bytes ) = 17 Bytes
					Resp = ISO14443A_Write_Mifare_Block( *(Param), (Param + 1) , Data_Resp, LenData_Resp , CHECK_ENABLE) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Increment :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Increment_Value[0] + ... +  Increment_Value[3] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 5 )  // Block Num + Increment_Value ( 4 Bytes ) = 5 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Increment_Value( 4 Bytes ) = 5 Bytes
					Resp = ISO14443A_Increment( *(Param), (Param + 1) , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Decrement :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Decrement_Value[0] + ... +  Decrement_Value[3] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 5 )  // Block Num + Decrement_Value ( 4 Bytes ) = 5 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Decrement_Value( 4 Bytes ) = 5 Bytes
					Resp = ISO14443A_Decrement( *(Param), (Param + 1) , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Restore :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 1 )  // Block Num = 1 Byte
				{ 
					// Param = Block_Num( 1 Byte ) = 1 Byte
					for ( i = 0 ; i < 4 ; i++ )
					{
						temp_Value[ i ] = 0x00 ;
					}
					Resp = ISO14443A_Restore( *(Param), temp_Value , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;


		case A_Transfer :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 1 )  // Block Num  = 1 Byte
				{ 
					// Param = Block_Num( 1 Byte ) = 1 Byte
					Resp = ISO14443A_Transfer( *(Param), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

// -------------------------------------------------- Mifare Ultralight Cmd ---------------------------------------------------------------------//
                
		case A_Read_Ultralight :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 1 )  // Block Addr = 1 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) = 1 Byte
					Resp = ISO14443A_Read_Mifare_Block( *( Param ), Data_Resp, LenData_Resp, CHECK_DISABLE ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;
                
		case A_Write_Compat_Ultralight :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Data_Wr[0] + ... +  Data_Wr[15] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 17 )  // Block Addr + Data_Wr ( 16 Bytes ) = 17 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Data_Wr( 16 Bytes ) = 17 Bytes
					Resp = ISO14443A_Write_Mifare_Block( *(Param), (Param + 1) , Data_Resp, LenData_Resp , CHECK_DISABLE) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;
                
		case A_Write_Ultralight :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Data_Wr[0] + ... +  Data_Wr[3] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 5 )  // Block Addr + Data_Wr ( 16 Bytes ) = 17 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Data_Wr( 16 Bytes ) = 17 Bytes
					Resp = ISO14443A_Write_Ultralight ( *(Param), (Param + 1) , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;
                
#ifdef ISO14443A_DES_LOADKEY_ENABLE
		case A_3DES_Auth_Load_Key_Ultralight : // 0x43
																												// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Key1[0] + .... + Key1[7] + Key2[0] + .... + Key2 [7] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 16 )  // Block Addr + Data_Wr ( 16 Bytes ) = 17 Bytes
				{ 
					Resp = ISO14443A_3DES_Authent_Ultralight_LoadKey ( Param  ) ;
																																*(LenData_Resp) = 0 ; 
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break;
#endif								
		case A_3DES_Auth_TxCMD_Ultralight : // 0x44
                  
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				Resp = ISO14443A_3DES_Authent_Ultralight_TxCMD ( Data_Resp, LenData_Resp ) ;
					
				break;             
            
		case A_3DES_Auth_TxEncipher_Ultralight : // 0x45
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Data[0] + ... + Data[15] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + + Data[0] + ... + Data[N-1]  + LRC									
				if ( LenParam >= 16 )  // Block Addr + Data_Wr ( 16 Bytes ) = 17 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Data_Wr( 16 Bytes ) = 17 Bytes
					Resp = ISO14443A_3DES_Authent_Ultralight_TxEncipher ( Param , Data_Resp, LenData_Resp ) ;
																																*(LenData_Resp) = 0 ; 
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}	
				break;
                
#ifdef ISO14443A_DES_ENABLE  
		case A_3DES_Auth_Ultralight : // 0x46
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Key1[0] + .... + Key1[7] + Key2[0] + .... + Key2 [7] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 16 )  // Block Addr + Data_Wr ( 16 Bytes ) = 17 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Data_Wr( 16 Bytes ) = 17 Bytes
					Resp = ISO14443A_3DES_Authent_Ultralight ( Param  ) ;
																																*(LenData_Resp) = 0 ; 
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}	
				break;
#endif
		
// -------------------------------------------------- NFC Type1 Cmd ---------------------------------------------------------------------------//
                
		case A_NFC_Type1_Read_UID :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									

				Resp = ISO14443A_NFC_Type1_Read_UID( Data_Resp, LenData_Resp ) ;
				break ;
                                
		case A_NFC_Type1_Read_All_Byte :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + UID[1] + UID[2] + UID[3] + UID[4] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				
				if ( LenParam >= 4 )  
				{ 
					Resp = ISO14443A_NFC_Type1_Read_All_Byte ( Param , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
                                                                                  
				break ;

		case A_NFC_Type1_Read_Single_Byte :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + ADRRESS + UID[1] + UID[2] + UID[3] + UID[4] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				
																												if ( LenParam >= 5 )  
				{ 
					Resp = ISO14443A_NFC_Type1_Read_Single_Byte ( *Param , Param + 1 , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;
                
		case A_NFC_Type1_Write_With_Erase :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				
																												if ( LenParam >= 6 )  
				{ 
					Resp = ISO14443A_NFC_Type1_Write_With_Erase ( *Param , *(Param + 1) , Param + 2 , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}	
				break ;

		case A_NFC_Type1_Write_No_Erase :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									

				
				if ( LenParam >= 6 )  
				{ 
					Resp = ISO14443A_NFC_Type1_Write_No_Erase ( *Param , *(Param + 1) , Param + 2 , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}	
		break ;

// --------------------------------------------------  Combo Cmd -------------------------------------------------------------------------------------	

		case A_Req_Anti_Sel :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Request_Mode + CollMask_Value + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC
				if(LenParam >= 2)
				{ 
					// Param = Request_Mode( 1 Byte ) + CollMask_Value( 1 Byte ) = 2 Bytes
					Resp = ISO14443A_Req_Anti_Select(1, *(Param), *(Param + 1), Data_Resp, LenData_Resp);
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT;
					*(LenData_Resp) = 0; 
				}
				break;
                
		case A_Req_Anti_Sel_RATS :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Request_Mode + CollMask_Value + Param_Byte + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 3 )
				{ 
					Resp = ISO14443A_Req_Anti_Select_RATS ( *( Param ), *( Param + 1 ), *( Param + 2 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;
                
		case A_Req_Anti_Sel_Loadkey_Authen :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Req_Mode + CollMask_Value + Select_Key + Key[0] + ... + Key[5] + Block_Num + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 10 )  // Req_Mode + CollMask_Value + Select_Key + Key( 6 Bytes ) + Block_Num = 10 Bytes
				{ 
					// Param = Req_Mode( 1 Byte ) + CollMask_Value( 1 Byte ) + Select_Key( 1 Byte ) + Key( 6 Bytes ) + Block_Num( 1 Byte ) = 10 Bytes
					Resp = ISO14443A_Req_Anti_Select_LoadKey_Authent( *( Param ) , *( Param + 1 ), *( Param + 2 ), ( Param + 3 ), *( Param + 9 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;
		
		case A_Req_Anti_Sel_Loadkey_Authen_Read :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Req_Mode + CollMask_Value + Select_Key + Key[0] + ... + Key[5] + Block_Num + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 10 )  // Req_Mode + CollMask_Value + Select_Key + Key( 6 Bytes ) + Block_Num = 10 Bytes
				{ 
					// Param = Req_Mode( 1 Byte ) + CollMask_Value( 1 Byte ) + Select_Key( 1 Byte ) + Key( 6 Bytes ) + Block_Num( 1 Byte ) = 10 Bytes
					Resp = ISO14443A_Req_Anti_Select_LoadKey_Authent_Read( *( Param ) , *( Param + 1 ), *( Param + 2 ), ( Param + 3 ), *( Param + 9 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;

		case A_Req_Anti_Sel_Loadkey_Authen_Write :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Req_Mode + CollMask_Value + Select_Key + Key[0] + ... + Key[5] + Block_Num + Data_Wr[0] ... + Data_Wr[15] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 26 ) // Req_Mode + CollMask_Value + Select_Key + Key( 6 Bytes ) + Block_Num + Data_Wr ( 16 Bytes ) = 26 Bytes
				{ 
					// Param = Req_Mode( 1 Byte ) + CollMask_Value( 1 Byte ) + Select_Key( 1 Byte ) + Key( 6 Bytes ) + Block_Num( 1 Byte ) + Data_Wr ( 16 Bytes ) = 26 Bytes
					Resp = ISO14443A_Req_Anti_Select_LoadKey_Authent_Write( *( Param ) , *( Param + 1 ), *( Param + 2 ), ( Param + 3 ), *( Param + 9 ), ( Param + 10 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;
		
		case A_Increment_Transfer :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Increment_Value[0] + ... +  Increment_Value[3] + Transfer_Block + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 6 )  // Block_Num + Increment_Value ( 4 Bytes ) + Transfer_Block = 6 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Increment_Value( 4 Bytes ) + Transfer_Block( 1 Byte ) = 6 Bytes
					Resp = ISO14443A_Increment_Transfer( *( Param ), ( Param + 1 ), *( Param + 5 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Decrement_Transfer :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Decrement_Value[0] + ... +  Decrement_Value[3] + Transfer_Block + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 6 )  // Block Num + Decrement_Value ( 4 Bytes ) + Transfer_Block = 6 Bytes
				{ 
					// Param = Block_Num( 1 Byte ) + Decrement_Value( 4 Bytes ) + Transfer_Block( 1 Byte ) = 6 Bytes
					Resp = ISO14443A_Decrement_Transfer( *( Param ), ( Param + 1 ), *( Param + 5 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;

		case A_Restore_Transfer :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Block_Num + Transfer_Block + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 2 )  // Block Num + Transfer_Block = 1 Byte
				{ 
					// Param = Block_Num( 1 Byte ) + Transfer_Block( 1 Byte ) = 2 Bytes
					for ( i = 0 ; i < 4 ; i++ )
					{
						temp_Value[ i ] = 0x00 ;
					}
					Resp = ISO14443A_Restore_Transfer( *( Param ), temp_Value, *( Param + 1 ), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}		
				break ;
                
//--------------------------------------------------  EMV & Polling Cmd ---------------------------------------------------------------------------	  
#ifdef ISO14443A_EMV_LOAD_MOD_ENABLE              
		case A_EMV_Load_Modulation : 
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Reset_Field_En + Run_All_Step + CMD_Category + First_Step + No_Of_Step + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + + CMD_TYPE + FBP_CMD + Last_Step + FF FF + 01 + Len[1] + Resp_Index[1] + Data_Index[1][0 - Len[1]]
																												// + FF FF + 02 + Len[2] + Resp_Index[2] + Data_Index[2][0 - Len[2]] + ... 
				// ... + FF FF + Step_Index[N] + Len[N] + Resp_Index[N] + Data_Index[N][0 - Len[N]] +  LRC                  
				if ( LenParam >= 5 )
				{ 
					Resp = ISO14443A_EMV_Load_Modulation (*(Param ), *(Param + 1), *(Param + 2) , *(Param + 3) , *(Param + 4) , Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;  
				
				case A_Polling_Tags : 
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD +  Polling_Option  + Reset_Field_En + Run_All_Step + CMD_Category + No_Of_Step + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + Last_Step + FF FF + 01 + Len[1] + Resp_Index[1] + Data_Index[1][0 - Len[1]]
																												// + FF FF + 02 + Len[2] + Resp_Index[2] + Data_Index[2][0 - Len[2]] + ... 
				// ... + FF FF + Step_Index[N] + Len[N] + Resp_Index[N] + Data_Index[N][0 - Len[N]] +  LRC                  
				if ( LenParam >= 6 )
				{ 
					Resp = ISO14443A_Polling_Tags (*(Param ), *(Param + 1), *(Param + 2) , *(Param + 3) , *(Param + 4), *(Param + 5), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;  
#endif
                  

// --------------------------------------------------  Transparent Cmd -------------------------------------------------------------------------------------	
		case A_Transparent_With_CRC :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD  + TimeOut + Data_Tx[0] + ... + Data_Tx[n + 1] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
				if ( LenParam >= 2 ) 
				{ 
					Resp = Transparent_With_CRC( (Param + 1), (LenParam - 1), *(Param), Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*(LenData_Resp) = 0 ; 
				}
				break ;

		case A_Transparent_Without_CRC :
								// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + TimeOut + Data_Tx[0] + ... + Data_Tx[n + 1] + LRC
								// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
								if ( LenParam >= 2 ) 
								{ 
									Resp = Transparent_Without_CRC( (Param + 1), (LenParam - 1), *(Param), Data_Resp, LenData_Resp ) ;
								}
								else
								{
									Resp = PARAMETER_NOT_CORRECT ;
									*(LenData_Resp) = 0 ; 
								}
		break ;

                case  A_Transparent_Config_CRC :                
                                                                // SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + TimeOut + TxCRCEn + RxCRCEn + Data_Tx[0] + ... + Data_Tx[n + 1] + LRC
								// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
								if ( LenParam >= 4 ) 
								{ 
									Resp = Transparent_Configure_CRC( *(Param + 1), *(Param + 2), (Param + 3), (LenParam - 3), *(Param), Data_Resp, LenData_Resp ) ;
								}
								else
								{
									Resp = PARAMETER_NOT_CORRECT ;
									*(LenData_Resp) = 0 ; 
								}
                
                break;  
                
                case  A_Transparent_NFC_Type1_With_CRC :                
                                                                // SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + TimeOut + Data_Tx[0] + ... + Data_Tx[n + 1] + LRC
								// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
								if ( LenParam >= 4 ) 
								{ 
									Resp = Transparent_NFC_Type1_With_CRC( (Param + 1), (LenParam - 1), *(Param), Data_Resp, LenData_Resp ) ;
								}
								else
								{
									Resp = PARAMETER_NOT_CORRECT ;
									*(LenData_Resp) = 0 ; 
								}
                
                break;  
                
                case  A_Transparent_NFC_Type1_Without_CRC :                
                                                                // SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + TimeOut + Data_Tx[0] + ... + Data_Tx[n + 1] + LRC
								// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
								if ( LenParam >= 4 ) 
								{ 
									Resp = Transparent_NFC_Type1_Without_CRC( (Param + 1), (LenParam - 1), *(Param), Data_Resp, LenData_Resp ) ;
								}
								else
								{
									Resp = PARAMETER_NOT_CORRECT ;
									*(LenData_Resp) = 0 ; 
								}
                
                break;  
                
                case  A_Transparent_NFC_Type1_Config_CRC :                
                                                                // SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + TimeOut + TxCRCEn + RxCRCEn + Data_Tx[0] + ... + Data_Tx[n + 1] + LRC
								// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + DATA[0] + ... + DATA[N-1] + LRC									
								if ( LenParam >= 4 ) 
								{ 
									Resp = Transparent_NFC_Type1_Config_CRC( *(Param + 1), *(Param + 2), (Param + 3), (LenParam - 3), *(Param), Data_Resp, LenData_Resp ) ;
								}
								else
								{
									Resp = PARAMETER_NOT_CORRECT ;
									*(LenData_Resp) = 0 ; 
								}
                
                break;  
                
		case  A_Transparent_With_RxMultiple :                
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + TimeOut + Data_Tx[0] + ... + Data_Tx[n + 1] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RxSolt[0] + Resp[0] + Len[0] + Data[0][0] + ... + Data[0][N-1] + ... + RxSlot[m] + Resp[m] + Len[m] + Data[m][0] + ... + Data[m][N-1] +  LRC									


				if ( LenParam >= 2 ) 
				{ 
							Resp = Transparent_With_RxMultiple( (Param + 1),  (LenParam - 1), *(Param), Data_Resp, LenData_Resp ) ;
				}
				else
				{
								Resp = PARAMETER_NOT_CORRECT ;
								*(LenData_Resp) = 0 ; 
				}
				break;  
                
                
                  
		default :
								Resp = UNKNOWN_CMD ;
								*(LenData_Resp) = 0 ; 
		break ;
	} ;

	return Resp ;
}

/*******************************************************************************
* Function Name : ISO14443A_Config
* Description   : Configure Registers and RF-Communication speed for ISO14443A Operation
* Input         : 
*				  - Speed : Tx_Speed(4 bits) + RxSpeed(4 bits)	
*						High Nibble = Tx_Speed(Bit7:4)
*							- 0000b = 106 kbps
*							- 0001b = 212 kbps		
*							- 0010b = 424 kbps		
*							- 0011b = 848 kbps		
*							- Other = 106 kbps		
*						Low Nibble = Rx_Speed(Bit3:0)
*							- 0000b = 106 kbps
*							- 0001b = 212 kbps		
*							- 0010b = 424 kbps		
*							- 0011b = 848 kbps		
*							- Other = 106 kbps		
* Output        : None
* Return        : 
*				  - Response
*				 		- _SUCCESS_ 
*******************************************************************************/
uint8_t ISO14443A_Config( uint8_t Speed ) 
{
	BC45_Config_14443A() ;
	BC45_Speed_14443A( Speed ) ;
	
	// ON Field
	BC45_ON_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
	Delay_ms ( 5 ) ;
	
	return _SUCCESS_ ;
} 

/*******************************************************************************
* Function Name	: ISO14443A_Get_Speed_Reader
* Description 	: Return current RF-Speed setting
* Input         : None
* Output        : 
*				  - Speed : Tx_Speed(4 bits) + RxSpeed(4 bits)	
*						High Nibble = Tx_Speed(Bit7:4)
*							- 0000b = 106 kbps
*							- 0001b = 212 kbps		
*							- 0010b = 424 kbps		
*							- 0011b = 848 kbps		
*							- Other = 106 kbps		
*						Low Nibble = Rx_Speed(Bit3:0)
*							- 0000b = 106 kbps
*							- 0001b = 212 kbps		
*							- 0010b = 424 kbps		
*							- 0011b = 848 kbps		
*							- Other = 106 kbps		
*				: - LenSpeed : Length of output, always = 1
* Return        : 
*				  - Response
*						- _SUCCESS_ 
*******************************************************************************/
uint8_t ISO14443A_Get_Speed_Reader( uint8_t *Speed, uint16_t *LenSpeed )
{	 
	*( Speed )    = ISO14443A_Property.Speed ;
	*( LenSpeed ) = 1 ;

	return _SUCCESS_ ;	
}

/*******************************************************************************
* Function Name	: ISO14443A_Request
* Description 	: Perform Request command in ISO14443A standard
* Input         : None
* Output		: 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st to Last byte : Response data from Request command
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_ 		
*						- NO_RESPONSE   	
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Request( uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint16_t  i;
	uint8_t   Resp;
	
	BC45_Clear_Crypto1On_Bit();

	// Request Cmd
	Data_TxRF[0] = ISO14443A_REQUEST_RF_CMD; 
	
	// Tx Send 7 bit  
	BC45_Set_BitFraming(0, 7);		

	BC45_CRC_Setting(TxCRC_Disable, RxCRC_Disable);

	Resp = BC45_Transceive(&Data_TxRF[0], 1, &Data_RxRF[0], &LenData_RxRF);	
	
	// Check Len resp data
	if(Resp == _SUCCESS_)
	{	
		if(LenData_RxRF != LEN_ISO14443A_REQUEST_RF_RESP)
		{
			Resp = INVALID_RESP;
		}
	}
	
	*( LenData_Resp ) = LenData_RxRF;
	for(i=0; i<LenData_RxRF; i++)
	{
		*(Data_Resp+i) = Data_RxRF[i];		
	}

	return Resp;
}

/*******************************************************************************
* Function Name	: ISO14443A_WakeUp
* Description 	: Perform Wake up command in ISO14443A standard
* Input         : None
* Output		: 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st to Last byte : Response data from Wake up command
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exist)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_WakeUp(uint8_t *Data_Resp, uint16_t *LenData_Resp)
{	
	uint16_t  i;
	uint8_t   Resp;

	BC45_Clear_Crypto1On_Bit();

	// WakeUp Cmd
	Data_TxRF[0] = ISO14443A_WAKE_UP_RF_CMD; 
	
	// Tx Send 7 bit  
	BC45_Set_BitFraming(0, 7);		

	BC45_CRC_Setting(TxCRC_Disable, RxCRC_Disable);

	Resp = BC45_Transceive(&Data_TxRF[0], 1, &Data_RxRF[0], &LenData_RxRF);	
	
	// Check Len resp data
	if(Resp == _SUCCESS_)
	{	// Check Len resp data
		if(LenData_RxRF != LEN_ISO14443A_WAKEUP_RF_RESP)
		{
			Resp = INVALID_RESP;
		}
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for(i = 0; i<LenData_RxRF; i++)
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;		
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Anticoll
* Description 	: Perform Anticollision command in ISO14443A standard.
*				   This command choose only 1 Card in field.
* Input         : 
*				  - Level
*						- 0x01h : Cascade Level 1
*						- 0x02h : Cascade Level 2
*						- 0x03h : Cascade Level 3
*						- Other : Cascade Level 1
*				  - CollMask_Value : Value for collided bit is either 0 or 1.
*									 Direction in searching UID is also defined from this bit.
*									 this option has no effect in operating single card 
* Output        : 
*				  - NumColl : Number of Collision occurred
*				  - Coll_Pos : Bit position at collision occurred
*				  - UID
*				  - LenUID : Length of receive UID in anticollision
* Return        : 
*				  - Response
*				  		- _SUCCESS_  
*						- NO_RESPONSE
*				  		- FRAMING_ERR
*				  		- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Anticoll( uint8_t Level, uint8_t CollMask_Value, uint8_t *NumColl, uint8_t *Coll_Pos, uint8_t *UID, uint16_t *LenUID )
{	
	uint16_t  i;
	uint8_t   Resp;
	uint8_t	  Flg_Complete  = 0;

	uint8_t   SEL;
	uint8_t   CheckSum_UID  = 0;
	uint16_t  temp_LenUID   = 0;
	uint8_t   temp_UID[10];
	uint8_t   temp_NumColl  = 0;
	uint8_t   temp_Coll_Pos = 0;
	uint8_t   Total_UID_Bit = 0;

	uint8_t   LenData_Rx_Byte = 0, LenData_Rx_Bit = 0;
	uint8_t   RxData_BytePos  = 0, RxData_BitPos  = 0;

	uint8_t   LenData_Tx_Byte = 0;
	uint8_t   TxData_BytePos  = 0, TxData_BitPos = 0;
	
	BC45_CRC_Setting(TxCRC_Disable, RxCRC_Disable);
	
	// Initial Variable
	for(i=0; i<=9; i++)
	{	
		temp_UID[i] = 0;
	}

	// Check Collision mask bit 
	if(CollMask_Value == 1)
	{	
		BC45_Set_CollMaskVal_Bit();
	}
	else
	{	
		BC45_Clear_CollMaskVal_Bit();
	}

	if(Level == A_CASCADE_LEVEL_2)	// Cascade Level 2
	{	
		SEL	= ISO14443A_CASCADE_LEVEL_2_RF_CMD;
	}
	else if(Level == A_CASCADE_LEVEL_3)	// Cascade Level 3
	{	
		SEL	= ISO14443A_CASCADE_LEVEL_3_RF_CMD;
	}
	else // Cascade Level 1
	{	
		SEL	= ISO14443A_CASCADE_LEVEL_1_RF_CMD;
	}

	Data_TxRF[0] = SEL;	  // Select Code
	Data_TxRF[1] = 0x20;	// NVB Cmd

	do
	{
		BC45_Set_BitFraming( TxData_BitPos, TxData_BitPos ) ;		

		Resp = BC45_Transceive( &Data_TxRF[0], LenData_Tx_Byte + 2, &Data_RxRF[0], &LenData_RxRF ) ;	

		if ( Resp == COLLISION_ERR )
		{
			temp_Coll_Pos = BC45_Read_CollPos() ; // Read Collpos 

			if ( temp_Coll_Pos > 0 ) // Collision
			{
				Total_UID_Bit = Total_UID_Bit + temp_Coll_Pos ;
				*( Coll_Pos + temp_NumColl ) = Total_UID_Bit ;
				temp_NumColl ++ ;
	
				//----------------------- Rx ---------------------------------//
				LenData_Rx_Byte = ( RxData_BitPos + temp_Coll_Pos ) / 8 ;
				LenData_Rx_Bit  = ( RxData_BitPos + temp_Coll_Pos ) % 8 ;
	
				if ( LenData_Rx_Bit != 0 )
				{	
					LenData_Rx_Byte = LenData_Rx_Byte + 1 ;
				}
				else
				{	
					LenData_Rx_Byte = LenData_Rx_Byte ;
				}
	
				temp_UID[ RxData_BytePos ] |= ( (0xFF << RxData_BitPos) & Data_RxRF[0] ) ; // Get data
				for( i = 1 ; i < LenData_Rx_Byte ; i++ ) 
				{
					temp_UID[ RxData_BytePos + i ] = Data_RxRF[i] ;
				}
			
				//----------------------- Tx ---------------------------------//
				TxData_BytePos = Total_UID_Bit / 8 ;
				TxData_BitPos  = Total_UID_Bit % 8 ;
	
				if ( TxData_BitPos != 0 )
				{	
					LenData_Tx_Byte = TxData_BytePos + 1 ;
				}
				else
				{	
					LenData_Tx_Byte = TxData_BytePos ;
				}				
	
				Data_TxRF[0] = SEL ;	// Select Code
				Data_TxRF[1] = ( (TxData_BytePos + 2) * 0x10 ) + ( (TxData_BitPos) * 0x1 ) ; // NVB Cmd																
				
				for ( i = 0 ; i < LenData_Tx_Byte ; i++ )// Prepare data before send Cmd
				{
					Data_TxRF[i + 2] = temp_UID[i] ; // Data																
				}
					
				RxData_BitPos  = TxData_BitPos ;
				RxData_BytePos = TxData_BytePos ;
				
				Delay_ms(1); // Delay --> Actual  ( (128*48 + 1172) / fc ) = 536 us
			}
			else // It collided at Header --> BC45 should report Framing Err and Collision Err in ErrorFlag register(0x0A)
				 // In this case it occur when BC45 only report Collision Err
			{
				Flg_Complete = 1 ;				
				Resp = FRAMING_ERR ;
				*(Coll_Pos) = 0 ; 
				temp_LenUID	= LenData_RxRF ;
				for( i = 0 ; i < LenData_RxRF ; i++ )
				{	
					temp_UID[i] = Data_RxRF[i] ;
				}
			}
		}
		else
		{
			Flg_Complete = 1 ;				
			if ( temp_NumColl != 0 )
			{	
				temp_LenUID	= RxData_BytePos + LenData_RxRF ;
				temp_UID[ RxData_BytePos ] |= ( (0xFF << RxData_BitPos) & Data_RxRF[0] ) ; // Get data
				for( i = 1 ; i < LenData_RxRF ; i++ ) 
				{
					temp_UID[ RxData_BytePos + i ] = Data_RxRF[i] ;
				}
			}
			else
			{
				*(Coll_Pos) = 0 ; 
				temp_LenUID	= LenData_RxRF ;
				for( i = 0 ; i < LenData_RxRF ; i++ )
				{	
					temp_UID[i] = Data_RxRF[i] ;
				}
			}										
		} 					
	} 
	while( (!Flg_Complete) && (temp_NumColl <= 32) ) ;	 // UID 4 Byte --> Max Coll Occur = 32 times

	if ( temp_NumColl > 32 )
	{	// UID 4 Byte --> Max Collision Occur = 32 times
		Resp = INVALID_RESP ;
	}

	if ( Resp == _SUCCESS_ )
	{
		if ( temp_LenUID == LEN_ISO14443A_ANTICOLL_RF_RESP )
		{	// 	Cal Check Sum
			for ( i = 0 ; i < 4 ; i++ ) // UID 4 Byte
			{
				CheckSum_UID ^= temp_UID[i] ;
			}
			if ( CheckSum_UID == temp_UID[4] ) // BCC = temp_UID[4]
			{
				temp_LenUID = 4 ;  // Send Only UID 4 Bytes
			}
			else
			{
				Resp = INVALID_RESP ; // Return UID 4 Bytes and BCC
			}
		}
		else
		{
			Resp = INVALID_RESP ;
		}	
	}

	*( NumColl ) = temp_NumColl ;
	*( LenUID ) = temp_LenUID ;
	for ( i = 0 ; i < temp_LenUID ; i++ ) 
	{
	   *( UID + i )	= temp_UID[i] ;
	}
	
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Select
* Description 	: Perform Select command in ISO14443A standard
* Input         : 
*				  - Level : Select cascade level
*						- 0x01h : Cascade Level 1
*						- 0x02h : Cascade Level 2
*						- 0x03h : Cascade Level 3
*						- Other : Cascade Level 1
*				  - UID : 4 Bytes
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st to Last byte : Response data from Select command
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Select( uint8_t Level, uint8_t *UID, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint16_t  i ;
	uint8_t   Resp ;
	uint8_t   SEL ;
	uint8_t   BCC ;


	if ( Level == A_CASCADE_LEVEL_2 )	// Cascade Level 2
	{	
		SEL	= ISO14443A_CASCADE_LEVEL_2_RF_CMD ;
	}
	else if ( Level == A_CASCADE_LEVEL_3 )	// Cascade Level 3
	{	
		SEL	= ISO14443A_CASCADE_LEVEL_3_RF_CMD ;
	}
	else // Cascade Level 1
	{	
		SEL	= ISO14443A_CASCADE_LEVEL_1_RF_CMD ;
	}

	Data_TxRF[0] = SEL ;	// Selection code
	Data_TxRF[1] = 0x70 ;	// NVB 
	BCC = 0 ;
	for ( i = 0 ; i < 4 ; i++ )	
	{
		Data_TxRF[i + 2] = *( UID + i ) ; // UID 4 Bytes	
		BCC ^= *( UID + i ) ;														
	}
	Data_TxRF[6] = BCC ;	// BCC

	BC45_CRC_Setting( TxCRC_Enable, RxCRC_Enable ) ;

	Resp = BC45_Transceive( &Data_TxRF[0], 7, &Data_RxRF[0], &LenData_RxRF ) ;	

	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
		if ( LenData_RxRF != LEN_ISO14443A_SELECT_RF_RESP )
		{
			Resp = INVALID_RESP	;
		}
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_RATS
* Description 	: Perform RATS command in ISO14443A-4 standard
* Input         : 
*				  - Parameter_Byte : FSDI(4 bits) + CID(4 bits)  
*						High Nibble = FSDI(Bit7:4) : It defines the maximum size of a frame the PCD is able to receive
*							- 1 : FSD 16 Bytes
*							- 2 : FSD 24 Bytes
*							- 3 : FSD 32 Bytes
*							- 4 : FSD 40 Bytes
*							- 5 : FSD 48 Bytes
*							- 6 : FSD 64 Bytes
*							- 7 : FSD 96 Bytes
*							- 8 : FSD 128 Bytes
*							- 9 : FSD 256 Bytes
*							- Other : FSD > 256 Bytes
*						Low Nibble = CID(Bit3:0) : It defines the logical number of the addressed PICC in the range from 0 to 14. The value 15 is RFU
*							The CID is specified by the Reader and shall be unique for all Cards, 
*							which are in the ACTIVE state at the same time. The CID is fixed for the time the Card is active and
*							the Card shall use the CID as its logical identifier, which is contained in the first error-free RATS received.
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st to Last byte : Response data from RATS command
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_RATS( uint8_t Parameter_Byte, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint16_t  i ;
	uint8_t   Resp ;
	uint8_t   LenResp_RATS ;
	
	Data_TxRF[0] = ISO14443A_RATS_RF_CMD ;	
	Data_TxRF[1] = Parameter_Byte ;	 

	BC45_CRC_Setting( TxCRC_Enable, RxCRC_Enable ) ;

	Resp = BC45_Transceive( &Data_TxRF[0], 2, &Data_RxRF[0], &LenData_RxRF ) ;	

	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
		if ( LenData_RxRF >= 1 )
		{
			LenResp_RATS = Data_RxRF[0] ;
			if ( LenData_RxRF != LenResp_RATS )
			{
				Resp = INVALID_RESP	;
			}
		}
		else
		{
			Resp = INVALID_RESP	;
		}
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_PPS
* Description 	: Perform PPS command in ISO14443A-4 standard
* Input         : 
*				  - CID : It defines the logical number of the addressed Card in the range from 0 to 14. The value 15 is RFU
*				  - PPS0 : PPS0 indicates the presence of the optional byte PPS1
*				  - PPS1 : "0000" + DRI(2 bits) + DSI(2 bits)
*						- DSI( Bit3:2 ) : code the selected divisor integer from Card to Reader.
*						- DRI( Bit1:0 ) : code the selected divisor integer from Reader to Card.
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st to Last byte : Response data from PPS command
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_PPS( uint8_t CID, uint8_t PPS0, uint8_t PPS1, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint16_t  i ;
	uint8_t   Resp ;
	
	Data_TxRF[0] = ISO14443A_PPS_RF_CMD | ( 0x0F & CID ) ;	
	Data_TxRF[1] = PPS0 ;	 
	Data_TxRF[2] = PPS1 ;	 

	BC45_CRC_Setting( TxCRC_Enable, RxCRC_Enable ) ;

	Resp = BC45_Transceive( &Data_TxRF[0], 3, &Data_RxRF[0], &LenData_RxRF ) ;	

	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
		if ( LenData_RxRF != LEN_ISO14443A_PPS_RF_RESP )
		{
			Resp = INVALID_RESP	;
		}
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Halt
* Description 	: Perform Halt command in ISO14443A standard
* Input         : None
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = A_HALT_ERR
*							- 1st to Last byte : Response from Halt command (if there is response)
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- A_HALT_ERR
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Halt( uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint16_t  i ;
	uint8_t   Resp ;

	Data_TxRF[0] = ISO14443A_HALT1_RF_CMD ; // HLTA Cmd	
	Data_TxRF[1] = ISO14443A_HALT2_RF_CMD ; // HLTA Cmd
	
	BC45_CRC_Setting( TxCRC_Enable, RxCRC_Enable ) ;

	Resp = BC45_Transceive( &Data_TxRF[0], 2, &Data_RxRF[0], &LenData_RxRF ) ;	

	if ( Resp == NO_RESPONSE )
	{
		*( LenData_Resp ) = 0 ;
		Resp = _SUCCESS_ ;		
	}
	else
	{
		Resp = A_HALT_ERR ;		
		*( LenData_Resp ) = LenData_RxRF ;
		for ( i = 0; i < LenData_RxRF ; i++ )
		{
			*( Data_Resp + i ) = Data_RxRF[i] ;
		}
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Load_Key
* Description 	: Perform Load Key into BC45 master key buffer 
* Input         : 
*				  - Key : 6 Bytes 
* Output        : None
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- KEY_ERR  
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Load_Key( uint8_t * Key )
{	
	uint8_t   i ;
	uint8_t   Resp ;
	uint8_t   MSB_Nibble, LSB_Nibble ;
	uint8_t   temp_Key ;
	uint8_t   Key_Convert[12] ;

	BC45_CRC_Setting( TxCRC_Disable, RxCRC_Disable ) ;
	// convert key from key 6 bytes to 12 bytes
	for ( i = 0 ; i < 6 ; i++ )
	{
		temp_Key = *( Key + i ) ;
		MSB_Nibble = ( temp_Key >> 4 ) & 0x0F ;
		LSB_Nibble = temp_Key & 0x0F  ;
		Key_Convert[2 * i] =  ( ((~MSB_Nibble) << 4) & 0xF0 ) | MSB_Nibble ;
		Key_Convert[(2 * i) + 1] = ( ((~LSB_Nibble) << 4) & 0xF0 ) | LSB_Nibble ;		 
	}
	
	Resp = BC45_LoadKey( Key_Convert, 12 ) ;	

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Authentication
* Description 	: Perform Authentication command in mifare
* Input         : 
*				  - Select_Key : 
*				  		- USE_KEY_A(0x00)  : Use Key A
*				  		- USE_KEY_B(0x01)  : Use Key B
*				  		- Other : Use Key A
*				  - Block_Num : The Address of data block to be authentication
*				  - UID       : 
*				  - LenUID    : Length of UID (usually equal to 4 for Mifare) 
* Output        : None
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- AUTHENT_ERR 
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Authentication( uint8_t Select_Key, uint8_t Block_Num, uint8_t *UID, uint8_t LenUID )
{
	uint8_t   i ;
	uint8_t   Resp ;
	
	Resp = BC45_Check_KeyErr() ;
	if ( Resp == _SUCCESS_ )
	{
		if ( Select_Key == USE_KEY_B )
		{
			Data_TxRF[0] = MIFARE_AUTHENT_WITH_KEY_B_RF_CMD ;
		}
		else
		{
			Data_TxRF[0] = MIFARE_AUTHENT_WITH_KEY_A_RF_CMD ;
		}
		
		Data_TxRF[1] = Block_Num ; 
		for ( i = 0 ; i < LenUID ; i++ )	
		{
			Data_TxRF[i + 2] = *( UID + i ) ; // UID N Bytes	
		}
	
		Resp = BC45_Authent( Data_TxRF, ( 2 + LenUID ) ) ;	
	}
		
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Write_Mifare_Block
* Description 	: Perform Write Block command in mifare
* Input         : 
*				  - Block_Num :  The Address of data block to be written
*				  - Data_Wr  : 16 bytes data to be written
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NOT_AUTHENT, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
*         - Check_Crypto : Enable Crypto_On Checking before execution  
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT
*						- MIFARE_ERR  : if MIFARE_ERR occur, Data_Resp is error report to indicate the cause of error 
*								   		( The error byte is detailed in Mifare ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Write_Mifare_Block( uint8_t Block_Num, uint8_t *Data_Wr, uint8_t *Data_Resp, uint16_t *LenData_Resp, uint8_t Check_Crypto )
{	
	uint8_t   i ;
	volatile uint8_t   Resp ;
	volatile uint8_t   RxLastBit ;

	if ( Check_Crypto == CHECK_DISABLE )
        {
          Resp = CRYPTO_ON ;
        }
        else
        {
          Resp = BC45_Check_Crypto_Bit() ;
        }
	if ( Resp == CRYPTO_ON ) // Crypto ON
	{
		BC45_CRC_Setting( TxCRC_Enable, RxCRC_Disable ) ;
	
		Data_TxRF[0] = MIFARE_WRITE_BLOCK_RF_CMD ;	// Write Mifare Command
		Data_TxRF[1] = Block_Num ;
	
		Resp = BC45_Transceive( &Data_TxRF[0], 2, &Data_RxRF[0], &LenData_RxRF ) ;	
	
		if ( Resp == _SUCCESS_ )
		{
			RxLastBit = BC45_Read_RxLastBit() ;
			if ( ((LenData_RxRF) == 1) && (RxLastBit == 4) && (Data_RxRF[0] == MIFARE_ACK) )
			{	// Data 16 Bytes
				for ( i = 0 ; i < 16 ; i++ )
				{	
					Data_TxRF[i] = *(Data_Wr + i) ;
				}
			
				Resp = BC45_Transceive( &Data_TxRF[0], 16, &Data_RxRF[0], &LenData_RxRF ) ;	
	
				if ( Resp == _SUCCESS_ )
				{
					RxLastBit = BC45_Read_RxLastBit() ;
					if ( ((LenData_RxRF) == 1) && (RxLastBit == 4) && (Data_RxRF[0] == MIFARE_ACK) )
					{	// Resp = Resp( SUCCESS )
						LenData_RxRF = 0 ;
					}
					else if ( (LenData_RxRF == 1) && (RxLastBit == 4) ) // Mifare Err
					{
						Resp = MIFARE_ERR ;
					}
					else // Error
					{
						Resp = INVALID_RESP ;
					}
				}
				else
				{	// Resp = RF Err
					;
				}
			}
			else if ( (LenData_RxRF == 1) && (RxLastBit == 4) ) // Mifare Err
			{
				Resp = MIFARE_ERR ;
			}
			else // Error
			{
				Resp = INVALID_RESP ;
			}
		}
		else // RF Err
		{	// Resp = RF Err
			;
		}
	}
	else
	{	// Not Authent
		Resp = NOT_AUTHENT ;
		LenData_RxRF = 0 ;
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0 ; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Read_Mifare_Block
* Description 	: Perform Read Block command in mifare
* Input         : 
*				  - Block_Num :  The Address of data block to be read
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st to Last byte : Data in block
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NOT_AUTHENT, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
*                                 - Check_Crypto : Enable Crypto_On Checking before execution    
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT : Tag is not authentication before Read block command 
*						- MIFARE_ERR  : if MIFARE_ERR occur, Data_Resp is error report to indicate the cause of error 
*								   		( The error byte is detailed in Mifare ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Read_Mifare_Block( uint8_t Block_Num, uint8_t *Data_Resp, uint16_t *LenData_Resp, uint8_t Check_Crypto )
{	
	uint8_t   i ;
	uint8_t   Resp ;
	uint8_t   RxLastBit ;

	if ( Check_Crypto == CHECK_DISABLE )
        {
          Resp = CRYPTO_ON ;
        }
        else
        {
          Resp = BC45_Check_Crypto_Bit() ;
        }
	if ( Resp == CRYPTO_ON ) 
	{
		BC45_CRC_Setting( TxCRC_Enable, RxCRC_Enable ) ;

		Data_TxRF[0] = MIFARE_READ_BLOCK_RF_CMD ; // Read Mifare Command
		Data_TxRF[1] = Block_Num ;
	
		Resp = BC45_Transceive( &Data_TxRF[0], 2, &Data_RxRF[0], &LenData_RxRF ) ;	

		// Check Len resp data
		if ( Resp == _SUCCESS_ )
		{	
			if ( LenData_RxRF != LEN_ISO14443A_READ_BLOCK_RF_RESP )
			{
				Resp = INVALID_RESP	;
			}
		}
		else if ( Resp == CRC_ERR ) // Mifare error
		{
			RxLastBit = BC45_Read_RxLastBit() ;
			if ( (LenData_RxRF == 1) && (RxLastBit == 4) ) // Mifare Err
			{
				Resp = MIFARE_ERR ;
			}
		}
	}
	else
	{	// Not Authent
		Resp = NOT_AUTHENT ;
		LenData_RxRF = 0 ;
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Mifare_CMD_On_Value_Block
* Description 	: Base function for Increment Decrement Restore in Mifare
* Input         : 
*				  - Mifare_Cmd :
*						- MIFARE_DECREMENT_RF_CMD(0xC0)
*						- MIFARE_INCREMENT_RF_CMD(0xC1)
*						- MIFARE_RESTORE_RF_CMD(0xC2)
*				  - Block_Num :  The Address of data block to be operate
*				  - Value : 4 bytes amount for Increment or Decrement (LSB byte first)
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT : Tag is not authentication
*						- MIFARE_ERR  : if MIFARE_ERR occur, Data_Resp is error report to indicate the cause of error 
*								   		( The error byte is detailed in Mifare ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
// For Increment Decrement Restore
uint8_t ISO14443A_Mifare_CMD_On_Value_Block( uint8_t Mifare_Cmd, uint8_t Block_Num, uint8_t *Value, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t  i ;
	uint8_t  Resp ;
	uint8_t  RxLastBit ;

	Resp = BC45_Check_Crypto_Bit() ;
	if ( Resp == CRYPTO_ON ) 
	{
		BC45_CRC_Setting( TxCRC_Enable, RxCRC_Disable ) ;
	
		Data_TxRF[0] = Mifare_Cmd ;		// Mifare Command
		Data_TxRF[1] = Block_Num ;
	
		Resp = BC45_Transceive( &Data_TxRF[0], 2, &Data_RxRF[0], &LenData_RxRF ) ;	
	
		if ( Resp == _SUCCESS_ )
		{
			RxLastBit = BC45_Read_RxLastBit() ;
			if ( (LenData_RxRF == 1) && (RxLastBit == 4) && (Data_RxRF[0] == MIFARE_ACK) )
			{			
				for ( i = 0 ; i < 4 ; i++ )
				{	
					Data_TxRF[i] = *(Value + i) ;
				}
	
				Resp = BC45_Transceive( &Data_TxRF[0], 4, &Data_RxRF[0], &LenData_RxRF ) ;	
	
				if ( Resp == NO_RESPONSE ) // Success ( Card No Response )
				{
					Resp = _SUCCESS_ ;
					LenData_RxRF = 0 ;
				}
				else if ( Resp == _SUCCESS_ )
				{
					RxLastBit = BC45_Read_RxLastBit() ;
					if ( (LenData_RxRF == 1) && (RxLastBit == 4) ) // Mifare Err
					{
						Resp = MIFARE_ERR ;
					}
					else // Error
					{
						Resp = INVALID_RESP ;
					}
				}
				else // RF Err 
				{	// Resp = RF Err
					;
				}
			}
			else if ( (LenData_RxRF == 1) && (RxLastBit == 4) ) // Mifare Err
			{
				Resp = MIFARE_ERR ;
			}
			else // Error
			{
				Resp = INVALID_RESP ;
			}
		}
		else // RF Err
		{	// Resp = RF Err
			;
		}
	}
	else
	{	// Not Authen
		Resp = NOT_AUTHENT ;
		LenData_RxRF = 0 ;
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0 ; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Decrement
* Description 	: Perform Decrement command in Mifare
* Input         : 
*				  - Block_Num :  The Address of data block to be Decrement
*				  - Decrement_Value : 4 bytes amount for Decrement (LSB byte first)
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT : Tag is not authentication before Decrement command 
*						- MIFARE_ERR  : if MIFARE_ERR occur, Data_Resp is error report to indicate the cause of error 
*								   		( The error byte is detailed in Mifare ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Decrement( uint8_t Block_Num, uint8_t *Decrement_Value, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t  Resp ;
	
	Resp = ISO14443A_Mifare_CMD_On_Value_Block( MIFARE_DECREMENT_RF_CMD, Block_Num, Decrement_Value, Data_Resp, LenData_Resp ) ;
		
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Increment
* Description 	: Perform Increment command in Mifare
* Input         : 
*				  - Block_Num :  The Address of data block to be Increment
*				  - Increment_Value : 4 bytes amount for Increment (LSB byte first)
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT : Tag is not authentication before Increment command 
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Increment( uint8_t Block_Num, uint8_t *Increment_Value, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t  Resp ;
	
	Resp = ISO14443A_Mifare_CMD_On_Value_Block( MIFARE_INCREMENT_RF_CMD, Block_Num, Increment_Value, Data_Resp, LenData_Resp ) ;
		
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Restore
* Description 	: Perform Restore command in Mifare
* Input         : 
*				  - Block_Num :  The Address of data block to be Restore
*				  - Restore_Value : 4 bytes amount for Restore (LSB byte first)
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT : Tag is not authentication before Restore command 
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Restore( uint8_t Block_Num, uint8_t *Restore_Value, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t  Resp ;
	
	Resp = ISO14443A_Mifare_CMD_On_Value_Block( MIFARE_RESTORE_RF_CMD, Block_Num, Restore_Value, Data_Resp, LenData_Resp ) ;
		
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Transfer
* Description 	: Perform Transfer command in Mifare
* Input         : 
*				  - Block_Num :  The Address of data block to be Transfer
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT : Tag is not authentication before Transfer command 
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Transfer( uint8_t Block_Num, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t  i ;
	uint8_t  Resp ;
	uint8_t  RxLastBit ;

	Resp = BC45_Check_Crypto_Bit() ;
	if ( Resp == CRYPTO_ON ) 
	{
		BC45_CRC_Setting( TxCRC_Enable, RxCRC_Disable ) ;
	
		Data_TxRF[0] = MIFARE_TRANSFER_RF_CMD ; // Transfer Mifare Command
		Data_TxRF[1] = Block_Num ;
	
		Resp = BC45_Transceive( &Data_TxRF[0], 2, &Data_RxRF[0], &LenData_RxRF ) ;	
		if ( Resp == _SUCCESS_ )
		{
			RxLastBit = BC45_Read_RxLastBit() ;
			if ( (LenData_RxRF == 1) && (RxLastBit == 4) && (Data_RxRF[0] == MIFARE_ACK) )
			{	// Resp = SUCCESS
				LenData_RxRF = 0 ;
			}
			else if ( (LenData_RxRF == 1) && (RxLastBit == 4) ) // Mifare Err
			{
				Resp = MIFARE_ERR ;
			}
			else // Error
			{
				Resp = INVALID_RESP ;
			}
		}
		else // RF Err
		{	// Resp = RF Err
			;
		}
	}
	else 
	{	// Not Authen
		Resp = NOT_AUTHENT ;
		LenData_RxRF = 0 ;
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0 ; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Write_Ultralight
* Description 	: Perform Transfer command in Mifare
* Input         : 
*				  - Block_Num :  The Address of data block to be Transfer
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Write_Ultralight( uint8_t Block_Num, uint8_t *Data_Wr, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t  i ;
	uint8_t  Resp ;
	uint8_t  RxLastBit ;
	
	BC45_CRC_Setting( TxCRC_Enable, RxCRC_Disable ) ;
	
	Data_TxRF[0] = MIFARE_WRITE_ULTRALIGHT_RF_CMD ; // Transfer Mifare Command
	Data_TxRF[1] = Block_Num ;
        Data_TxRF[2] = *( Data_Wr );
        Data_TxRF[3] = *( Data_Wr + 1 ) ;
        Data_TxRF[4] = *( Data_Wr + 2 ) ;
        Data_TxRF[5] = *( Data_Wr + 3 ) ;
	
	Resp = BC45_Transceive( &Data_TxRF[0], 6, &Data_RxRF[0], &LenData_RxRF ) ;	
	if ( Resp == _SUCCESS_ )
	{
		RxLastBit = BC45_Read_RxLastBit() ;
		if ( (LenData_RxRF == 1) && (RxLastBit == 4) && (Data_RxRF[0] == MIFARE_ACK) )
		{	// Resp = SUCCESS
			LenData_RxRF = 0 ;
		}
		else if ( (LenData_RxRF == 1) && (RxLastBit == 4) ) // Mifare Err
		{
			Resp = MIFARE_ERR ;
		}
		else // Error
		{
			Resp = INVALID_RESP ;
		}
	}
	else // RF Err
	{	// Resp = RF Err
		
	}
	
	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0 ; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}


/*******************************************************************************
* Function Name	: ISO14443A_NFC_Type1_Read_UID
* Description 	: Perform Read Block command in mifare
* Input         : None
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st & 2nd byte : HR0 & HR1
*							- 3rd to 6th byte : UID
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NOT_AUTHENT, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
*                                 - Check_Crypto : Enable Crypto_On Checking before execution    
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_NFC_Type1_Read_UID( uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t   i ;
	uint8_t   Resp ;

	Data_TxRF[0] = NFC_TYPE1_READ_UID_RF_CMD ; // Read Mifare Command
	Data_TxRF[1] = 0x00 ;
       	Data_TxRF[2] = 0x00 ;
        Data_TxRF[3] = 0x00 ;
        Data_TxRF[4] = 0x00 ;
        Data_TxRF[5] = 0x00 ;
        Data_TxRF[6] = 0x00 ;                                
	
        Resp = Transparent_NFC_Type1_With_CRC (&Data_TxRF[0] , 7 , 2 , &Data_RxRF[0], &LenData_RxRF ) ; // Set Time out 2 ms
        
	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
    	    if ( LenData_RxRF != LEN_NFC_TYPE1_READ_UID_RF_RESP )
	    {
		Resp = INVALID_RESP	;
	    }
	}
	
	
	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_NFC_Type1_Read_All_Byte
* Description 	: Perform Read Block command in mifare
* Input         :
*                                 - UID       : 4 Bytes
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st & 2nd byte : HR0 & HR1
*							- 3rd to 6th byte : UID
*							- 7rd to 133th byte : Memory Data
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NOT_AUTHENT, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
*                                 - Check_Crypto : Enable Crypto_On Checking before execution    
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_NFC_Type1_Read_All_Byte   ( uint8_t *UID, uint8_t *Data_Resp, uint16_t *LenData_Resp ) 
{
        uint8_t   i ;
	uint8_t   Resp ;

	
	Data_TxRF[0] = NFC_TYPE1_READ_ALL_BYTE_RF_CMD ; // Read Mifare Command
	Data_TxRF[1] = 0x00 ;
       	Data_TxRF[2] = 0x00 ;
        for ( i = 0 ; i < 4 ; i++ )
        {
          Data_TxRF[3 + i] = * ( UID + i ) ;
        }
	
        Resp = Transparent_NFC_Type1_With_CRC (&Data_TxRF[0] , 7 , 2 , &Data_RxRF[0], &LenData_RxRF ) ; // Set Time out 2 ms
        
	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
    	    if ( LenData_RxRF != LEN_NFC_TYPE1_READ_ALL_BYTE_RF_RESP )
	    {
		Resp = INVALID_RESP	;
	    }
	}
	
	
	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}


/*******************************************************************************
* Function Name	: ISO14443A_NFC_Type1_Read_Single_Byte
* Description 	: Perform Read Block command in mifare
* Input         :
*                                 - Address 
*                                 - UID       : 4 Bytes
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st ADDRESS
*							- 2nd DATA
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NOT_AUTHENT, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
*                                 - Check_Crypto : Enable Crypto_On Checking before execution    
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/

uint8_t ISO14443A_NFC_Type1_Read_Single_Byte( uint8_t Address, uint8_t *UID, uint8_t *Data_Resp, uint16_t *LenData_Resp ) 
{
        uint8_t   i ;
	uint8_t   Resp ;

	
	Data_TxRF[0] = NFC_TYPE1_READ_SINGLE_BYTE_RF_CMD ; // Read Mifare Command
	Data_TxRF[1] = Address ;
       	Data_TxRF[2] = 0x00 ;
        for ( i = 0 ; i < 4 ; i++ )
        {
          Data_TxRF[3 + i] = * ( UID + i ) ;
        }
	
        Resp = Transparent_NFC_Type1_With_CRC (&Data_TxRF[0] , 7 , 2 , &Data_RxRF[0], &LenData_RxRF ) ; // Set Time out 2 ms
        
	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
    	    if ( LenData_RxRF != LEN_NFC_TYPE1_READ_SINGLE_BYTE_RF_RESP )
	    {
		Resp = INVALID_RESP	;
	    }
	}
	
	
	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_NFC_Type1_Write_With_Erase
* Description 	: Perform Read Block command in mifare
* Input         :
*                                 - Address 
*                                 - Data
*                                 - UID       : 4 Bytes
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st ADDRESS
*							- 2nd DATA
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NOT_AUTHENT, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
*                                 - Check_Crypto : Enable Crypto_On Checking before execution    
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/

uint8_t ISO14443A_NFC_Type1_Write_With_Erase( uint8_t Address, uint8_t Data, uint8_t *UID, uint8_t *Data_Resp, uint16_t *LenData_Resp ) 
{
        uint8_t   i ;
	uint8_t   Resp ;

	
	Data_TxRF[0] = NFC_TYPE1_WRITE_WITH_ERASE_RF_CMD ; // Read Mifare Command
	Data_TxRF[1] = Address ;
       	Data_TxRF[2] = Data ;
        for ( i = 0 ; i < 4 ; i++ )
        {
          Data_TxRF[3 + i] = * ( UID + i ) ;
        }
	
        Resp = Transparent_NFC_Type1_With_CRC (&Data_TxRF[0] , 7 , 5 , &Data_RxRF[0], &LenData_RxRF ) ; // Set Time out 16 ms
        
	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
    	    if ( LenData_RxRF != LEN_NFC_TYPE1_WRITE_WITH_ERASE_RF_RESP )
	    {
		Resp = INVALID_RESP	;
	    }
	}
	
	
	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
}


/*******************************************************************************
* Function Name	: ISO14443A_NFC_Type1_Write_No_Erase
* Description 	: Perform Read Block command in mifare
* Input         :
*                                 - Address 
*                                 - Data
*                                 - UID       : 4 Bytes
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- 1st ADDRESS
*							- 2nd DATA
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NOT_AUTHENT, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
*                                 - Check_Crypto : Enable Crypto_On Checking before execution    
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/

uint8_t ISO14443A_NFC_Type1_Write_No_Erase( uint8_t Address, uint8_t Data, uint8_t *UID, uint8_t *Data_Resp, uint16_t *LenData_Resp ) 
{
        uint8_t   i ;
	uint8_t   Resp ;

	
	Data_TxRF[0] = NFC_TYPE1_WRITE_NO_ERASE_RF_CMD ; // Read Mifare Command
	Data_TxRF[1] = Address ;
       	Data_TxRF[2] = Data ;
        for ( i = 0 ; i < 4 ; i++ )
        {
          Data_TxRF[3 + i] = * ( UID + i ) ;
        }
	
        Resp = Transparent_NFC_Type1_With_CRC (&Data_TxRF[0] , 7 , 5 , &Data_RxRF[0], &LenData_RxRF ) ; // Set Time out 16 ms
        
	// Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
    	    if ( LenData_RxRF != LEN_NFC_TYPE1_WRITE_NO_ERASE_RF_RESP )
	    {
		Resp = INVALID_RESP	;
	    }
	}
	
	
	*( LenData_Resp ) = LenData_RxRF ;
	for ( i = 0; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;
	}

	return Resp ;
} 

/*******************************************************************************
* Function Name	: ISO14443A_Req_Anti_Select
* Description 	: Combinational command of Request or Wakeup + Anticoll + Select (Cascade level UID is supported)
* Input         : 
*				  - Index_Cmd : index of first sub command for referening error location
*								For example. if Index_Cmd = X and there is error in 'Select' command(3rd command). 
*								error location of X + 2 is reported in data response
*				  - Req_Mode 
*						- REQ_MODE_REQA(0x00h) : Request A 
*						- REQ_MODE_WUPA(0x01h) : Wake Up A 
*						- Other : Request A
*				  - CollMask_Value : Value for collided bit is either 0 or 1.
* Output        : 
*				  - Data_Resp : 
*						- if Response = _SUCCESS_
*							- 1st byte : Report total cascade Level of ISO14443A UID. For example, 2 indicates two cascading level in UID
*							- 2nd byte : SAK
*							- 3rd byte to Last byte : UID(Length of UID byte is depend on Cascade Level)
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- 1st byte : Error location. For example, 4 represents error occurred in authentication 
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*				  	- FRAMING_ERR
*				  	- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Req_Anti_Select( uint8_t Index_Cmd, uint8_t Req_Mode, uint8_t CollMask_Value, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t   i;
	volatile uint8_t   Resp;
	uint8_t   Flg_Complete = 0;
	uint8_t   Level, Num_Coll, Coll_Pos[64], temp_UID[10], UID[10], Len_UID = 0;
	uint8_t   Err_Index;
	uint8_t   temp_SAK;
	uint8_t   temp_Data_Resp[64];
	uint16_t  temp_LenData_Resp;
	
	Level = A_CASCADE_LEVEL_1;

	if(Req_Mode == REQ_MODE_WUPA)
	{
		Resp = ISO14443A_WakeUp(temp_Data_Resp, &temp_LenData_Resp);
	}
	else
	{
		Resp = ISO14443A_Request(temp_Data_Resp, &temp_LenData_Resp);
	}
	
	if((Resp != NO_RESPONSE) && (Resp != ASIC_EXE_TIMEOUT))
	{
		do
		{
			// Anticoll
			Resp = ISO14443A_Anticoll(Level, CollMask_Value, &Num_Coll, Coll_Pos, temp_Data_Resp, &temp_LenData_Resp);
			if(Resp == _SUCCESS_)
			{	
				// Store UID in temp_UID
				for(i=0; i<4; i++) 
				{	
					temp_UID[i] = temp_Data_Resp[i];
				}
				
				// ---------------------------  Select ----------------------------
				Resp = ISO14443A_Select(Level, temp_UID, temp_Data_Resp, &temp_LenData_Resp);
				if(Resp == _SUCCESS_)
				{
					temp_SAK = temp_Data_Resp[0];
					if((temp_SAK & SAK_UID_COMPLETE_MASK) != SAK_UID_COMPLETE_MASK)
					{	// UID Complete
						for(i=0; i<4; i++)
						{	
							UID[Len_UID++] = temp_UID[i];
						}
						Flg_Complete = 1;
					}
					else // UID Not Complete
					{
						for(i=1; i<4; i++)
						{	
							UID[Len_UID++] = temp_UID[i];
						}
						Level++;
					}					
				}
				else // Select Err 
				{
					Flg_Complete = 1;
					Err_Index = Index_Cmd + 2; // Err Location
				}
			}
			else // Anticoll Err
			{
				Flg_Complete = 1;
				Err_Index = Index_Cmd + 1; // Err Location
			}
		} while((Flg_Complete == 0) && (Level <= A_CASCADE_LEVEL_3));
		
		if(Level > A_CASCADE_LEVEL_3)
		{	// Select Err (UID not Complete) -- > may be response data from select command is error 
			Resp = INVALID_RESP;
			Err_Index = Index_Cmd + 2; // Err Location
		}
	}
	else  // Request A Err ( No Response or ASIC_EXE_TIMEOUT )
	{
		Err_Index = Index_Cmd; // Err Location
		temp_LenData_Resp = 0; 
	}
	
	if(Resp == _SUCCESS_)
	{	
		*(Data_Resp)   = Level;    // Level
		*(Data_Resp+1) = temp_SAK; // SAK
		for(i=0; i<Len_UID; i++) 
		{
			*(Data_Resp+i+2) = UID[i]; // UID
		}
		*(LenData_Resp) = Len_UID + 2; // Len Response	
	}
	else
	{
		*(Data_Resp) = Err_Index; // Err Location
		for(i=0; i<temp_LenData_Resp; i++)
		{
			*(Data_Resp+i+1) = temp_Data_Resp[i];	
		}
		*(LenData_Resp) = temp_LenData_Resp + 1; // Index + Err data in BC45 FIFO
	}
	
	return Resp;
}

/*******************************************************************************
* Function Name	: ISO14443A_LoadKey_Authent
* Description 	: Combinational command of LoadKey + Authent
* Input         : 
*				  - Index_Cmd : index of first sub command for referening error location
*				  - Select_Key : 
*				  		- USE_KEY_A(0x00) : Use Key A
*				  		- USE_KEY_B(0x01) : Use Key B
*				  		- Other : Use Key A
*				  - Block_Num :  The Address of block to be Authent
*				  - Key : 6 Bytes
*				  - UID 
*				  - LenUID 
* Output        : 
*				  - Data_Resp 
*						- if Response = _SUCCESS_
*							- No Response data  
*						- Other
*							- 1st byte error location
*				  - LenData_Resp 
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- KEY_ERR 
*						- AUTHENT_ERR 
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_LoadKey_Authent( uint8_t Index_Cmd, uint8_t Select_Key, uint8_t *Key, uint8_t Block_Num, uint8_t *UID, uint8_t LenUID, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t  Resp ;

	Resp = ISO14443A_Load_Key( Key ) ;
	if ( Resp == _SUCCESS_ )
	{
		Resp = ISO14443A_Authentication( Select_Key, Block_Num, UID, LenUID ) ;
		if ( Resp == _SUCCESS_ )
		{
			*( LenData_Resp ) = 0 ;
		}
		else
		{
			*( Data_Resp ) = Index_Cmd + 1 ;
			*( LenData_Resp ) = 1 ;
		}
	}
	else
	{
		*( Data_Resp ) = Index_Cmd ;	
		*( LenData_Resp ) = 1 ;
	}
	
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Req_Anti_Select_Authent
* Description 	: Combinational command of Request or Wake up + Anticollision + Select + Authentication
* Input         : 
*				  - Req_Mode 
*						- REQ_MODE_REQA(0x00h) : Request A 
*						- REQ_MODE_WUPA(0x01h) : Wake Up A 
*						- Other : Request A
*				  - CollMask_Value : Value for collided bit is either 0 or 1.
*				  - Select_Key : 
*				  		- USE_KEY_A(0x00) : Use Key A
*				  		- USE_KEY_B(0x01) : Use Key B
*				  		- Other : Use Key A
*				  - Block_Num :  The Address of block to be Authent
* Output        : 
*				  - Data_Resp : 
*						- if Response = _SUCCESS_
*							- 1st byte to Last byte : UID
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, KEY_ERR, AUTHENT_ERR, ASIC_EXE_TIMEOUT)
*							- 1st byte : Error location
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*				  		- FRAMING_ERR
*				  		- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- KEY_ERR 
*						- AUTHENT_ERR 
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Req_Anti_Select_Authent( uint8_t Req_Mode, uint8_t CollMask_Value, uint8_t Select_Key, uint8_t Block_Num, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint16_t  i ;
	uint8_t   Resp ;
	uint8_t   temp_UID[10] ;
	uint8_t   temp_Cascade_Level, temp_UID_Size ;
	uint8_t   temp_Data_Resp[64] ;
	uint16_t  temp_LenData_Resp ;
	
	Resp = ISO14443A_Req_Anti_Select( 1, Req_Mode, CollMask_Value, temp_Data_Resp, &temp_LenData_Resp ) ;
	if ( Resp == _SUCCESS_ )
	{
		// UID 4 Bytes
		temp_Cascade_Level = temp_Data_Resp[0] ; 
		//temp_SAK = temp_Data_Resp[1] ;
		if ( temp_Cascade_Level == A_CASCADE_LEVEL_1 )
		{
			temp_UID_Size = A_UID_SINGLE_SIZE ;	
		}
		else if ( temp_Cascade_Level == A_CASCADE_LEVEL_2 )
		{
			temp_UID_Size = A_UID_DOUBLE_SIZE ;	
		}
		else
		{
			temp_UID_Size = A_UID_TRIPLE_SIZE ;	
		}
		
		for ( i = 0 ; i < temp_UID_Size ; i++ )
		{
			temp_UID[i] = temp_Data_Resp[i + 2] ;			
		}
		
		Resp = ISO14443A_Authentication( Select_Key, Block_Num, temp_UID, temp_UID_Size ) ;
		if ( Resp == _SUCCESS_ )
		{	// UID 4 Bytes
			; // Resp = SUCCESS
		}
		else // Authent Err
		{
			temp_Data_Resp[0] = 0x04 ; // Cmd index = 4
			temp_LenData_Resp = 1 ; // Err location
		}
	}
	else  // Combo 1 Err 
	{
		;
	}
	
	if ( Resp == _SUCCESS_ )
	{	// Return UID
		for ( i = 0 ; i < temp_UID_Size ; i++ )
		{
			*( Data_Resp + i ) = temp_UID[i] ;
		}
		*( LenData_Resp ) = temp_UID_Size ;
	}
	else
	{	// Return Error Location and Error Data 
		for ( i = 0 ; i < temp_LenData_Resp ; i++ )
		{
			*( Data_Resp + i ) = temp_Data_Resp[i] ;	
		}
		*( LenData_Resp ) = temp_LenData_Resp ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Req_Anti_Select_LoadKey_Authent
* Description 	: Combinational command of Request or Wake up + Anticollision + Select + LoadKey + Authentication
* Input         : 
*				  - Req_Mode 
*						- REQ_MODE_REQA(0x00h) : Request A 
*						- REQ_MODE_WUPA(0x01h) : Wake Up A 
*						- Other : Request A
*				  - CollMask_Value : Value for collided bit is either 0 or 1.
*				  - Select_Key : 
*				  		- USE_KEY_A(0x00) : Use Key A
*				  		- USE_KEY_B(0x01) : Use Key B
*				  		- Other : Use Key A
*				  - Key 
*				  - Block_Num :  The Address of block to be Authent
* Output        : 
*				  - Data_Resp : 
*						- if Response = _SUCCESS_
*							- 1st byte to Last byte : UID
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, KEY_ERR, AUTHENT_ERR, ASIC_EXE_TIMEOUT)
*							- 1st byte : Error location
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*				  		- FRAMING_ERR
*				  		- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- KEY_ERR 
*						- AUTHENT_ERR 
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Req_Anti_Select_LoadKey_Authent( uint8_t Req_Mode, uint8_t CollMask_Value, uint8_t Select_Key, uint8_t *Key, uint8_t Block_Num, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint16_t  i ;
	uint8_t   Resp ;
	//uint8_t   temp_SAK;
        uint8_t   temp_UID[10];
	uint8_t   temp_Cascade_Level, temp_UID_Size ;
	uint8_t   temp_UID_Index;
	uint8_t   temp_Data_Resp[64] ;
	uint16_t  temp_LenData_Resp ;
	
	Resp = ISO14443A_Req_Anti_Select( 1, Req_Mode, CollMask_Value, temp_Data_Resp, &temp_LenData_Resp ) ;
	if ( Resp == _SUCCESS_ )
	{
		// UID X Bytes
		temp_Cascade_Level = temp_Data_Resp[0] ; 
		//temp_SAK = temp_Data_Resp[1] ;
		if ( temp_Cascade_Level == A_CASCADE_LEVEL_1 )
		{
			temp_UID_Size = A_UID_SINGLE_SIZE ;	
			temp_UID_Index = 0 ;	
		}
		else if ( temp_Cascade_Level == A_CASCADE_LEVEL_2 )
		{
			temp_UID_Size = A_UID_DOUBLE_SIZE ;	
			temp_UID_Index = 3 ;	
		}
		else
		{
			temp_UID_Size = A_UID_TRIPLE_SIZE ;	
			temp_UID_Index = 7 ;	
		}
		
		for ( i = 0 ; i < temp_UID_Size ; i++ )
		{
			temp_UID[i] = temp_Data_Resp[i + 2] ;			
		}
		
		Resp = ISO14443A_LoadKey_Authent( 4, Select_Key, Key, Block_Num, (temp_UID + temp_UID_Index), 4, temp_Data_Resp, &temp_LenData_Resp ) ;	
	}
	else  
	{	// Combo 1 Err 
		;
	}
	
	if ( Resp == _SUCCESS_ )
	{	// return UID
		for ( i = 0 ; i < temp_UID_Size ; i++ )
		{
			*( Data_Resp + i ) = temp_UID[i] ;
		}
		*( LenData_Resp ) = temp_UID_Size ;
	}
	else
	{	// Return Error Location and Error Data 
		for ( i = 0 ; i < temp_LenData_Resp ; i++ )
		{
			*( Data_Resp + i ) = temp_Data_Resp[i] ;	
		}
		*( LenData_Resp ) = temp_LenData_Resp ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Req_Anti_Select_LoadKey_Authent_Read
* Description 	: Combinational command of Request or Wake up + Anticollision + Select + LoadKey + Authentication + Read Block
* Input         : 
*				  - Req_Mode 
*						- REQ_MODE_REQA(0x00h) : Request A 
*						- REQ_MODE_WUPA(0x01h) : Wake Up A 
*						- Other : Request A
*				  - CollMask_Value : Value for collided bit is either 0 or 1.
*				  - Select_Key : 
*				  		- USE_KEY_A(0x00) : Use Key A
*				  		- USE_KEY_B(0x01) : Use Key B
*				  		- Other : Use Key A
*				  - Key : 6 bytes
*				  - Block_Num :  The Address of block to be Authent and Read
* Output        : 
*				  - Data_Resp : 
*						- if Response = _SUCCESS_
*							- 1st byte to Last UID byte : UID
*							- 16 byte Last : Data in Block
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, KEY_ERR, AUTHENT_ERR, ASIC_EXE_TIMEOUT)
*							- 1st byte : Error location
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*				  		- FRAMING_ERR
*				  		- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- KEY_ERR 
*						- AUTHENT_ERR 
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Req_Anti_Select_LoadKey_Authent_Read( uint8_t Req_Mode, uint8_t CollMask_Value, uint8_t Select_Key, uint8_t *Key, uint8_t Block_Num, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint16_t  i ;
	uint8_t   Resp ;
	uint8_t   temp_Data_Resp[64] ;
	uint8_t   temp_UID[10] ;
	uint8_t   temp_UID_Size ;
	uint16_t  temp_LenData_Resp ;
	
	Resp = ISO14443A_Req_Anti_Select_LoadKey_Authent( Req_Mode, CollMask_Value, Select_Key, Key, Block_Num, temp_Data_Resp, &temp_LenData_Resp ) ;
	if ( Resp == _SUCCESS_ )
	{
		temp_UID_Size = temp_LenData_Resp ;
		for ( i = 0 ; i < temp_UID_Size ; i ++ )
		{
			temp_UID[i] = temp_Data_Resp[i] ;
		}
		Resp = ISO14443A_Read_Mifare_Block( Block_Num, temp_Data_Resp, &temp_LenData_Resp, CHECK_ENABLE ) ;
		if ( Resp == _SUCCESS_ )
		{	// UID N Bytes
			for ( i = 0 ; i < temp_UID_Size ; i++ )
			{
				*( Data_Resp + i ) = temp_UID[i] ;
			}
			for ( i = 0 ; i < temp_LenData_Resp ; i++ )
			{
				*( Data_Resp + i + temp_UID_Size ) = temp_Data_Resp[i] ;
			}
			*( LenData_Resp ) = temp_LenData_Resp + temp_UID_Size ;
		}
		else // Read_Err
		{
			*( Data_Resp ) = 0x06 ; // Cmd index = 6
			for ( i = 0 ; i < temp_LenData_Resp ; i++ )
			{
				*( Data_Resp + i + 1 ) = temp_Data_Resp[i] ;	
			}
			*( LenData_Resp ) = temp_LenData_Resp + 1 ;
		}
	}
	else
	{
		for ( i = 0 ; i < temp_LenData_Resp ; i++ )
		{
			*( Data_Resp + i ) = temp_Data_Resp[i] ;	
		}
		*( LenData_Resp ) = temp_LenData_Resp ;
	}
	
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Req_Anti_Select_LoadKey_Authent_Write
* Description 	: Combinational command of Request or Wake up + Anticollision + Select + LoadKey + Authentication + Write Block
* Input         : 
*				  - Req_Mode 
*						- REQ_MODE_REQA(0x00h) : Request A 
*						- REQ_MODE_WUPA(0x01h) : Wake Up A 
*						- Other : Request A
*				  - CollMask_Value : Value for collided bit is either 0 or 1.
*				  - Select_Key : 
*				  		- USE_KEY_A(0x00) : Use Key A
*				  		- USE_KEY_B(0x01) : Use Key B
*				  		- Other : Use Key A
*				  - Key : 6 bytes
*				  - Block_Num :  The Address of block to be Authent and Write
*				  - Data_Wr : 16 bytes 
* Output        : 
*				  - Data_Resp 
*						- if Response = _SUCCESS_
*							- 1st byte to Last UID byte : UID
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- Other (NO_RESPONSE, KEY_ERR, AUTHENT_ERR, ASIC_EXE_TIMEOUT)
*							- 1st byte : Error location
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*				  		- FRAMING_ERR
*				  		- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- KEY_ERR 
*						- AUTHENT_ERR 
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Req_Anti_Select_LoadKey_Authent_Write( uint8_t Req_Mode, uint8_t CollMask_Value, uint8_t Select_Key, uint8_t *Key, uint8_t Block_Num, uint8_t *Data_Wr, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint16_t  i ;
	uint8_t   Resp ;
	uint8_t   temp_UID[10] ;
	uint8_t   temp_Data_Resp[64] ;
	uint8_t   temp_UID_Size ;
	uint16_t  temp_LenData_Resp ;
	
	Resp = ISO14443A_Req_Anti_Select_LoadKey_Authent( Req_Mode, CollMask_Value, Select_Key, Key, Block_Num, temp_Data_Resp, &temp_LenData_Resp ) ;
	if ( Resp == _SUCCESS_ )
	{
		temp_UID_Size = temp_LenData_Resp ;
		for ( i = 0 ; i < temp_UID_Size ; i ++ )
		{
			temp_UID[i] = temp_Data_Resp[i] ;
		}
		
		Resp = ISO14443A_Write_Mifare_Block( Block_Num, Data_Wr, temp_Data_Resp, &temp_LenData_Resp , CHECK_ENABLE) ;
		if ( Resp == _SUCCESS_ )
		{	// UID N Bytes
			Resp = _SUCCESS_ ;
			for ( i = 0 ; i < temp_UID_Size ; i++ )
			{
				*( Data_Resp + i ) = temp_UID[i] ;
			}
			for ( i = 0 ; i < temp_LenData_Resp ; i++ )
			{
				*( Data_Resp + i + temp_UID_Size ) = temp_Data_Resp[i] ;
			}
			*( LenData_Resp ) = temp_LenData_Resp + temp_UID_Size ;
		}
		else // Write_Err
		{
			*( Data_Resp ) = 0x06 ; // Cmd index = 6
			for ( i = 0 ; i < temp_LenData_Resp ; i++ )
			{
				*( Data_Resp + i + 1 ) = temp_Data_Resp[i] ;	
			}
			*( LenData_Resp ) = temp_LenData_Resp + 1 ;
		}
	}
	else
	{
		for ( i = 0 ; i < temp_LenData_Resp ; i++ )
		{
			*( Data_Resp + i ) = temp_Data_Resp[i] ;	
		}
		*( LenData_Resp ) = temp_LenData_Resp ;
	}
	
	return Resp ;
}


/*******************************************************************************
* Function Name	: ISO14443A_Mifare_Combo_Inc_Dec_Res__Transfer
* Description 	: Perform Increase or Decrease or Restore command and follow by Transfer command
* Input         : 
*				  - Mifare_Cmd 
*						- MIFARE_DECREMENT_RF_CMD(0xC0)
*						- MIFARE_INCREMENT_RF_CMD(0xC1)
*						- MIFARE_RESTORE_RF_CMD(0xC2)
*				  - Block_Num : The address of block that value is initially used in execution 
*				  - Value : 4 bytes amount for Increment or Decrement (LSB byte first)
*				  - Transfer_Block : Destination block to be transfered 
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : Error location
*							- 2nd byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT 
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Mifare_Combo_Inc_Dec_Res__Transfer( uint8_t Mifare_Cmd, uint8_t Block_Num, uint8_t *Value, uint8_t Transfer_Block, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint16_t  i ;
	uint8_t   Resp ;
	uint8_t   Err_Index ;
	uint8_t   temp_Data_Resp[64] ;
	uint16_t  temp_LenData_Resp ;
	
	Resp = ISO14443A_Mifare_CMD_On_Value_Block( Mifare_Cmd, Block_Num, Value, temp_Data_Resp, &temp_LenData_Resp ) ;
	if ( Resp == _SUCCESS_ )
	{
		Resp = ISO14443A_Transfer( Transfer_Block, temp_Data_Resp, &temp_LenData_Resp ) ;
		if ( Resp == _SUCCESS_ )
		{
			*( LenData_Resp ) = 0 ;
		}
		else  // Transfer Err
		{
			Err_Index = 0x02 ; // Cmd index Err = 2
		}		
	}
	else  // Increment Err
	{
		Err_Index = 0x01 ; // Cmd index Err = 1
	}
	
	if ( Resp != _SUCCESS_ ) // Err
	{
		*( Data_Resp ) = Err_Index ;
		for ( i = 0 ; i < temp_LenData_Resp ; i++ )
		{
			*( Data_Resp + i + 1 ) = temp_Data_Resp[i] ;	
		}
		*( LenData_Resp ) = temp_LenData_Resp + 1 ;
	}
	
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Decrement_Transfer
* Description 	: Perform Decrement and Transfer command in Mifare
* Input         : 
*				  - Block_Num : The address of block that value is initially used in execution 
*				  - Decrement_Value : 4 bytes amount for Decrement (LSB byte first)
*				  - Transfer_Block : Destination block to be transfered 
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : Error location
*							- 2nd byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT 
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Decrement_Transfer( uint8_t Block_Num, uint8_t *Decrement_Value, uint8_t Transfer_Block, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t   Resp ;
	
	Resp = ISO14443A_Mifare_Combo_Inc_Dec_Res__Transfer( MIFARE_DECREMENT_RF_CMD, Block_Num, Decrement_Value, Transfer_Block, Data_Resp, LenData_Resp ) ;
		
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Increment_Transfer
* Description 	: Perform Increment and Transfer command in Mifare
* Input         : 
*				  - Block_Num : The address of block that value is initially used in execution 
*				  - Increment_Value : 4 bytes amount for Increment (LSB byte first)
*				  - Transfer_Block : Destination block to be transfered 
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : Error location
*							- 2nd byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT 
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Increment_Transfer( uint8_t Block_Num, uint8_t *Increment_Value, uint8_t Transfer_Block, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t   Resp ;
	
	Resp = ISO14443A_Mifare_Combo_Inc_Dec_Res__Transfer( MIFARE_INCREMENT_RF_CMD, Block_Num, Increment_Value, Transfer_Block, Data_Resp, LenData_Resp ) ;
		
	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_Restore_Transfer
* Description 	: 
* Input         : 
*				  - Block_Num : The address of block that value is initially used in execution 
*				  - Restore_Value : 4 bytes amount for Restore (LSB byte first)
*				  - Transfer_Block : Destination block to be transfered 
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- No Response data  
*						- if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st byte : Error location
*							- 2nd byte to Last byte : Error data in BC45 FIFO (if it exists)
*						- if Response = MIFARE_ERR
*							- 1st byte : 0x04 : NACK, not allowed or 
*										 0x05 : NACK, transmission error 
*						- Other (NOT_AUTHENT, NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*						- NOT_AUTHENT : Tag is not authentication
*						- MIFARE_ERR  : if MIFARE_ERR occur it will send following data 1 byte to indicate the cause of error 
*								   		( The error byte is detailed in Mifare standard ) 
*										- 0x04 : NACK, not allowed
*										- 0x05 : NACK, transmission error 						
*						- FRAMING_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Restore_Transfer( uint8_t Block_Num, uint8_t *Restore_Value, uint8_t Transfer_Block, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t   Resp ;
	
	Resp = ISO14443A_Mifare_Combo_Inc_Dec_Res__Transfer( MIFARE_RESTORE_RF_CMD, Block_Num, Restore_Value, Transfer_Block, Data_Resp, LenData_Resp ) ;
		
	return Resp ;
}



/*******************************************************************************
* Function Name	: ISO14443A_Req_Anti_Select_RATS
* Description 	: Combinational command of Request or Wake up + Anticollision + Select + Authentication
* Input         : 
*				  - Req_Mode 
*						- REQ_MODE_REQA(0x00h) : Request A 
*						- REQ_MODE_WUPA(0x01h) : Wake Up A 
*						- Other : Request A
*				  - CollMask_Value : Value for collided bit is either 0 or 1.
*                                 - Param_Byte  - See Detail in ISO14443A_RATS function
* Output        : 
*				  - Data_Resp : 
*						- if Response = _SUCCESS_
*							- 1st byte : UID Size
*							- 2nd byte : SAK
*							- 3rd byte to HH byte : UID ( Vary depend on UID Side )
*							- > HH bye : RATS Response
*						- Other (CRC_ERR, PARITY_ERR, FRAMING_ERR, NO_RESPONSE, KEY_ERR, AUTHENT_ERR, ASIC_EXE_TIMEOUT)
*							- 1st byte : Error location
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- NO_RESPONSE
*				  		- FRAMING_ERR
*				  		- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- KEY_ERR 
*						- AUTHENT_ERR 
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_Req_Anti_Select_RATS( uint8_t Req_Mode, uint8_t CollMask_Value, uint8_t Param_Byte,  uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint16_t  i ;
	uint8_t   Resp ;
	uint8_t   temp_Data_Resp[64] ;
	uint16_t  temp_LenData_Resp, temp_LenData ;
	
	Resp = ISO14443A_Req_Anti_Select( 1, Req_Mode, CollMask_Value, temp_Data_Resp, &temp_LenData_Resp ) ;
	if ( Resp == _SUCCESS_ )
	{
            for ( i = 0 ; i < temp_LenData_Resp  ; i++ )
	    {
		*( Data_Resp + i ) = temp_Data_Resp[i] ;
	    }
            temp_LenData = temp_LenData_Resp ;
		
	    Resp = ISO14443A_RATS( Param_Byte , temp_Data_Resp, &temp_LenData_Resp ) ; 
	    if ( Resp == _SUCCESS_ )
	    {	
                for ( i = 0 ; i < temp_LenData_Resp ; i++ )
                {
                    *( Data_Resp + i + temp_LenData ) = temp_Data_Resp[i] ;  
                }
                temp_LenData_Resp = temp_LenData_Resp + temp_LenData ;
	    }
	    else  //
	    {
		temp_Data_Resp[0] = 0x04 ; // Cmd index = 4
		temp_LenData_Resp = 1 ; // Err location
	    }
	}
	else  // Combo 1 Err 
	{
		;
	}
	
        
        
	if ( Resp == _SUCCESS_ )
	{   // Return UID Size, SAK , UID , RATS response
	    
	}
	else
	{ 
          // Return Error Location and Error Data 
	    for ( i = 0 ; i < temp_LenData_Resp ; i++ )
	    {
	      *( Data_Resp + i ) = temp_Data_Resp[i] ;	
	    }
	}

        *( LenData_Resp ) = temp_LenData_Resp ;
        
	return Resp ;
}



/*******************************************************************************
* Function Name	: ISO14443A_3DES_Authent_Ultralight_LoadKey
* Description 	: Load Key to FW internal Buffer
* Input         : None
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- - 1st to Last byte : Response data from 3DES_Authent command 
*                                               - if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exist)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- A_HALT_ERR
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
#ifdef ISO14443A_DES_LOADKEY_ENABLE
uint8_t ISO14443A_3DES_Authent_Ultralight_LoadKey ( uint8_t *Key_in ) 
{
    uint8_t   i;
    uint8_t   Resp ;
    uint8_t   key_temp[24];
    
    for (i = 0; i < 8; i++)
    {
       key_temp[i]      = *(Key_in + i);
       key_temp[i + 8]  = *(Key_in + i + 8);
       key_temp[i + 16] = *(Key_in + i);
    }
        
    Resp = DES_Load_Key ( &key_temp[0]) ;
        
    return Resp ;
    
}
#endif

/*******************************************************************************
* Function Name	: ISO14443A_3DES_Authent_Ultralight_TxCMD
* Description 	: Perform 3DES_Authent command in ISO14443A standard
* Input         : None
* Output        : 
*				  - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- - 1st to Last byte : Response data from 3DES_Authent command 
*                                               - if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exist)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- A_HALT_ERR
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t ISO14443A_3DES_Authent_Ultralight_TxCMD ( uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint16_t  i ;
	uint8_t   Resp ;

	Data_TxRF[0] = MIFARE_ULTRALIGHT_3DES_AUTHEN1_RF_CMD ; // 0x1A
	Data_TxRF[1] = MIFARE_ULTRALIGHT_3DES_AUTHEN2_RF_CMD ; // 0x00
	
	BC45_CRC_Setting( TxCRC_Enable, RxCRC_Enable ) ;

	Resp = BC45_Transceive( &Data_TxRF[0], 2, &Data_RxRF[0], &LenData_RxRF ) ;	
        
        /******************************************************/
        // Check Len resp data
	if ( Resp == _SUCCESS_ )
	{	
          if (( LenData_RxRF != LEN_ISO14443A_3DES_Authent_RF_RESP ) || (Data_RxRF[0] != MIFARE_UL_3DES_AUTH_HEADER_1 )) // 9 bytes
	  {
	     Resp = INVALID_RESP ;
          }
	}

	*( LenData_Resp ) = LenData_RxRF ;
	for( i = 0 ; i < LenData_RxRF ; i++ )
	{
		*( Data_Resp + i ) = Data_RxRF[i] ;		
	}

	return Resp ;
}

/*******************************************************************************
* Function Name	: ISO14443A_3DES_Authent_Ultralight_TxEncipher
* Description 	: Transmit 16 encipher data to RF 
* Input         : 16 bytes Data
* Output        : 
*				   - Data_Resp : Response data
*						- if Response = _SUCCESS_
*							- - 1st to Last byte : Response data from FIFO
*                                               - if Response = FRAMING_ERR or COLLISION_ERR or PARITY_ERR or CRC_ERR or INVALID_RESP (RF_COMMU_ERR_CATEGORY)
*							- 1st to Last byte : Error data in BC45 FIFO (if it exist)
*						- Other (NO_RESPONSE, ASIC_EXE_TIMEOUT)
*							- No Response data  
*				  - LenData_Resp : Length of Response data
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- A_HALT_ERR
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- ASIC_EXE_TIMEOUT  
*				  
*******************************************************************************/

uint8_t ISO14443A_3DES_Authent_Ultralight_TxEncipher ( uint8_t *Data , uint8_t *Data_Resp, uint16_t *LenData_Resp )
{	
	uint8_t  i ;
	uint8_t   Resp ;


	BC45_CRC_Setting( TxCRC_Enable, RxCRC_Enable );
        
        Data_TxRF[0] = MIFARE_UL_3DES_AUTH_HEADER_1 ;
        for ( i = 0 ; i < 16 ; i++ )
        {	
          Data_TxRF[i + 1] = *(Data + i) ;
        }
        
        Resp = BC45_Transceive( &Data_TxRF[0], 17, &Data_RxRF[0], &LenData_RxRF ) ;	
     
	if ( Resp == _SUCCESS_ )
	{	
	  if (( LenData_RxRF != LEN_ISO14443A_3DES_Authent_RF_RESP ) || (Data_RxRF[0] != MIFARE_UL_3DES_AUTH_HEADER_2 ))
	  {
	    Resp = INVALID_RESP	;
	  }
	}
	
	*( LenData_Resp ) = LenData_RxRF ;
	for( i = 0 ; i < LenData_RxRF ; i++ )
	{
	    *( Data_Resp + i ) = Data_RxRF[i] ;		
	}

	return Resp ;
}


/*******************************************************************************
* Function Name	: ISO14443A_3DES_Authent_Ultralight
* Description 	: Porfirm all 3DES_Authet process
* Input         : 
* Output        : 
*				   - Data_Resp : 
*						 
*				  - LenData_Resp : 
* Return        : 
*				  - Response
*						- _SUCCESS_  
*						- A_HALT_ERR
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- ASIC_EXE_TIMEOUT  
*				  
*******************************************************************************/
#ifdef ISO14443A_DES_ENABLE
uint8_t ISO14443A_3DES_Authent_Ultralight ( uint8_t *Key_in  ) 
{
        uint8_t   Resp;
        uint8_t   i;
        uint8_t   temp_Data_Resp[8];
        uint16_t  temp_LenData_Resp;
        uint8_t   RndA  [8];
        uint8_t   EkA   [8];
        uint8_t   RndAA [8];
        uint8_t   RndB  [8];                        //Rotate 8 bits
        uint8_t   temp_sv[8];
        uint8_t   temp_input[16];
        
        Resp = ISO14443A_3DES_Authent_Ultralight_LoadKey ( Key_in );
        Resp = ISO14443A_3DES_Authent_Ultralight_TxCMD   ( &Data_RxRF[0] , &temp_LenData_Resp );
        if (Resp == _SUCCESS_)
        {
	    for (i=0; i<8; i++)
	    {
		temp_sv[i]      = Data_RxRF[i+1];
		temp_input[i]   = Data_RxRF[i+1];
                temp_input[i+8] = 0;
	    }
	
	    Resp = DES_Deciphered( &temp_input[0] , temp_Data_Resp , &temp_LenData_Resp);
	    if (Resp == _SUCCESS_)
	    {
		RndB[7] = temp_Data_Resp [0];
		for (i=0 ; i<7 ; i++)
		{
                  RndB[i]= temp_Data_Resp [i+1];
                }
				
                for (i=0 ; i<8 ; i++)
		{
		  RndA[i]         = (uint8_t)(rand() & 0xFF); 
		  temp_input[i]   = RndA[i];
                  temp_input[i+8] = temp_sv[i];
		}
				  
		Resp = DES_Enciphered ( &temp_input[0] , temp_Data_Resp, &temp_LenData_Resp);
			  
		if (Resp == _SUCCESS_)
		{
                    for (i=0 ; i<8 ; i++)
                    {
                        temp_input[i]   = RndB[i];
                        temp_input[i+8] = temp_Data_Resp[i];
                        EkA[i]          = temp_Data_Resp[i];
                    }
				
		    Resp = DES_Enciphered ( &temp_input[0] , temp_Data_Resp , &temp_LenData_Resp);
				  
		    if (Resp == _SUCCESS_) 
		    {
			for (i=0; i<8; i++)
                        {
                            temp_input [i]    = EkA[i];
                            temp_input [i+8]  = temp_Data_Resp[i];
                        }
					
			Resp = ISO14443A_3DES_Authent_Ultralight_TxEncipher ( &temp_input[0] , &Data_RxRF[0], &temp_LenData_Resp);
					   
			if (Resp == _SUCCESS_)
			{
			    for (i=0; i<8; i++)
                            {
                                temp_input [i]   = Data_RxRF[i+1];
                                temp_input [i+8] = temp_Data_Resp[i];
                            }
							 
                            Resp = DES_Deciphered( &temp_input[0] , temp_Data_Resp , &temp_LenData_Resp);

			    RndAA[7] = RndA [0];
			    for (i=0 ; i<7; i++)
                            {
		                RndAA[i]= RndA [i+1];
                            }
			
                            for (i=0; i <8; i++)
			    {
				if (temp_Data_Resp[i] != RndAA[i]) 
                                {
                                    Resp = AUTHENT_ERR;	
                                    i = 8;
                                }
    	                    }                 
			}
                        else
                        {
                            Resp = AUTHENT_ERR;	
                        }
		    }                          
		}
	    }                           
        }        
        return Resp;
        
}
#endif


/*******************************************************************************
* Function Name	: ISO14443A_EMV_Load_Modulation
* Description 	: 
* Input         : 
*				  - Reset_Field_En : Enable Field Reset before starting sequence command
*				  - Run_All_Step   : 1 - Run All command following Number of Steps
*                                                  : 0 - Run until Error occur
*                                 - CMD_Category   : CMD Sequence
*                                             00   : 1 - WUPA // 2 - HLTA // 3 - WUPB 
*                                                  : 4 - WUPA // 5 - ANTI // 6 - SELECT // 7 - RATS
*                                                  : 8 - PPSE // 9 - LOOPBACK // 10 - Reset Field 
*                                                  : > 10 - Repitative WUPA 
*                                             01   : 1 - WUPA // 2 - HLTA // 3 - WUPB 
*                                                  : 4 - WUPA // 5 - ANTI // 6 - SELECT // 7 - RATS
*                                                  : 8 - PPS  // 9 - APDU1 // 10 - APDU1  // 11 - Reset Field 
*                                                  : > 11 - Repitative WUPA 
*				  - First_Step     : defines the first command to be executed
*				  - No_Of_Step     : Number of Steps , defines the number of command to be executed

*                                                 
* Output        : 
*				  - All Transaction result are output , Each transcation is separted by FFh FFh
*                                 - The argument following FFh FFh : Index + Len_Index + Resp_Index + Resp_Data[0] + ... + Resp_Data[n]  
*                                 - Each Resp_Index has the same meaning as typical transaction
* Return        : 
*				  - Last Step that Executed
*						
*******************************************************************************/
#ifdef ISO14443A_EMV_LOAD_MOD_ENABLE
uint8_t ISO14443A_EMV_Load_Modulation ( uint8_t Reset_Field_En , uint8_t Run_All_Step , uint8_t CMD_Category ,  uint8_t First_Step,  uint8_t No_Of_Step, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
        uint16_t  i;
	uint8_t   Resp ;
	uint8_t   index;
	uint8_t   temp_Data_Resp[256] ;
	uint16_t  temp_LenData_Resp, LenData_Resp_LoopBack ;
        uint16_t  temp_Len_Old;
        uint8_t   Level;
	        
        if (Reset_Field_En == CHECK_ENABLE) 
        {   BC45_OFF_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
            Delay_ms(2);
        }
        
        Level         = 1;
        
        if (First_Step == 0 )
        { 
            First_Step = 1 ;
        }
       
        index = First_Step ;
       
               
        temp_Data_Resp[0]   = 0xFF; // Separate Charactor
        temp_Data_Resp[1]   = 0xFF; // Separate Charactor
        temp_Len_Old  = 2;
      
        Resp = ISO14443A_Config( 0x00 ) ;
 
        while ((index < First_Step + No_Of_Step) && ((Run_All_Step == 1) || (Resp == _SUCCESS_)))        
        {     
              if (index == 1) // WUPA
             {
                Resp = ISO14443A_WakeUp( &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ) ;
             }
             else if (index == 2) // HLTA
             {
               	Data_TxRF[0] = ISO14443A_HALT1_RF_CMD ; // HLTA Cmd	
	        Data_TxRF[1] = ISO14443A_HALT2_RF_CMD ; // HLTA Cmd
               
                Resp = Transparent_With_CRC( &Data_TxRF[0], 2, 1 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 1 ms
             }
             else if  (index == 3) // WUPB
             {
                 Resp = ISO14443B_Config( 0x00 ) ;
                 Resp = ISO14443B_WakeUp( 0, 0 , &Data_TxRF[0], &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ) ;
             }
             else if (index == 4) // WUPA
             {
                 Resp = ISO14443A_Config( 0x00 ) ;
                 Resp = ISO14443A_WakeUp( &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ) ;
             }
             else if (index == 5) // AntiColl
             {  
                if (Level == 1) 
                {  Data_TxRF[0] = 0x93;
                }
                else if (Level == 2)
                {  Data_TxRF[0] = 0x95;
                }
                else if (Level == 3)
                {  Data_TxRF[0] = 0x97;  
                }
                  
                Data_TxRF[1] = 0x20;
                Resp = Transparent_Without_CRC( &Data_TxRF[0], 2, 2 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 2 ms
                if ((temp_LenData_Resp != 5) && (Resp == _SUCCESS_))
                { 
                    Resp = INVALID_RESP;
                }
             }  
             else if (index == 6) // Select
             {  
                if (Level == 1) 
                {  Data_TxRF[0] = 0x93;
                }
                else if (Level == 2)
                {  Data_TxRF[0] = 0x95;
                }
                else if (Level == 3)
                {  Data_TxRF[0] = 0x97;  
                }
                
                Data_TxRF[1] = 0x70;
                for (i=0 ; i < temp_LenData_Resp ;  i++)
                { 
                  Data_TxRF[ 2 + i ] = temp_Data_Resp[temp_Len_Old - temp_LenData_Resp - 2 + i ];
                }
                
                Resp = Transparent_With_CRC( &Data_TxRF[0], temp_LenData_Resp + 2, 2 , &temp_Data_Resp[ temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 2 ms
                
                if ( (temp_Data_Resp[temp_Len_Old + 3] & SAK_UID_COMPLETE_MASK) == SAK_UID_COMPLETE_MASK )
                {  
                   Level = Level + 1;
                }
                else
                {
                   Level =  1;
                }
                
             }
             else if (index == 7) // RATS
             {  
                Data_TxRF[0] = 0xE0;
                Data_TxRF[1] = 0x80;
               
                Resp = Transparent_With_CRC( &Data_TxRF[0], 2, 3 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 4 ms
                Delay_ms (2);
             }  
             else if (index == 8) // PPSE
             {  
                if (CMD_Category == 0)
                {
                   Data_TxRF[0] = 0x02;
                   Data_TxRF[1] = 0x00; 
                   Data_TxRF[2] = 0xA4;
                   Data_TxRF[3] = 0x04;
                   Data_TxRF[4] = 0x00;
                   Data_TxRF[5] = 0x0E;
                   Data_TxRF[6] = 0x32;  // '2'
                   Data_TxRF[7] = 0x50;  // 'P'
                   Data_TxRF[8] = 0x41;  // 'A'
                   Data_TxRF[9] = 0x59;  // 'Y'
                   Data_TxRF[10] = 0x2E;  // '.'
                   Data_TxRF[11] = 0x53; // 'S'
                   Data_TxRF[12] = 0x59; // 'Y'
                   Data_TxRF[13] = 0x53; // 'S'
                   Data_TxRF[14] = 0x2E; // '.'
                   Data_TxRF[15] = 0x44; // 'D'
                   Data_TxRF[16] = 0x44; // 'D'
                   Data_TxRF[17] = 0x46; // 'F'
                   Data_TxRF[18] = 0x30; // '0'
                   Data_TxRF[19] = 0x31; // '1'
                   Data_TxRF[20] = 0x00;
                   
                   Resp = Transparent_With_CRC( &Data_TxRF[0], 21, 5 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 16 ms
                   LenData_Resp_LoopBack = temp_LenData_Resp;
                }
                else
                {
                   Resp = ISO14443A_PPS(0x00, 0x11, 0x00, &temp_Data_Resp[temp_Len_Old + 3] , &temp_LenData_Resp );
                }
                Delay_ms (2);
             }
             else if (index == 9) // LoopBack Command
             { 
                if (CMD_Category == 0)
                { 
                   /*
                   Data_TxRF[0] = 0x03;                  
                   Data_TxRF[1] = 0x00; 
                   Data_TxRF[2] = 0xA4;
                   Data_TxRF[3] = 0x04;
                   Data_TxRF[4] = 0x00;
                   Data_TxRF[5] = 0x0C;
                   Data_TxRF[6] = 0x01;  
                   Data_TxRF[7] = 0x02;  
                   Data_TxRF[8] = 0x03;  
                   Data_TxRF[9] = 0x04; 
                   Data_TxRF[10] = 0x05; 
                   Data_TxRF[11] = 0x06; 
                   Data_TxRF[12] = 0x07; 
                   Data_TxRF[13] = 0x08; 
                   Data_TxRF[14] = 0x09; 
                   Data_TxRF[15] = 0x0A; 
                   Data_TxRF[16] = 0x0B; 
                   Data_TxRF[17] = 0x0C; 
                   Data_TxRF[18] = 0x00; 
                   Resp = Transparent_With_CRC( &Data_TxRF[0], 19, 5 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 8 ms
                   */
                  
                   Data_TxRF[0] = 0x03;  
                   for (i = 1; i < (LenData_Resp_LoopBack) ; i++)
                   {  
                      Data_TxRF [i] = temp_Data_Resp[temp_Len_Old + i - temp_LenData_Resp - 2 ]; 
                   }
                   
                   if ( LenData_Resp_LoopBack < 3 )
                   {
                      LenData_Resp_LoopBack = 1 ;
                   }
                   else
                   {
                      LenData_Resp_LoopBack = LenData_Resp_LoopBack - 2 ;
                   }
                   
                   Resp = Transparent_With_CRC( &Data_TxRF[0], LenData_Resp_LoopBack  , 4 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 8 ms
                   //Resp = Transparent_With_CRC( &Data_TxRF[0], (LenData_Resp_LoopBack - 2) , 4 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 8 ms
                   
                   /*
                   Data_TxRF[0] = 0x03;  
                   for (i = 1; i < (LenData_Resp_LoopBack) ; i++)
                   {  
                      Data_TxRF [i] = temp_Data_Resp[temp_Len_Old + i - temp_LenData_Resp - 2 ]; 
                   }
                   Resp = Transparent_With_CRC( &Data_TxRF[0], (LenData_Resp_LoopBack - 2) , 4 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 8 ms
                  */
                }
                else
                {
                   Data_TxRF[0] = 0x02;                  
                   Data_TxRF[1] = 0x00; 
                   Data_TxRF[2] = 0xA4;
                   Data_TxRF[3] = 0x04;
                   Data_TxRF[4] = 0x00;
                   Resp = Transparent_With_CRC( &Data_TxRF[0], 5, 5 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 8 ms 
                }
                Delay_ms (2);
             }

             else if (index == 10) // Reset Field
             {
                 if (CMD_Category == 0)
                 {               
                   BC45_OFF_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
                   Delay_ms(2);
                 
                   BC45_ON_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
                   Delay_ms(5);
                   Resp = _SUCCESS_;
                   temp_LenData_Resp = 0 ;
                 }
                 else
                 {
                   Data_TxRF[0] = 0x03;                  
                   Data_TxRF[1] = 0x00; 
                   Data_TxRF[2] = 0xA4;
                   Data_TxRF[3] = 0x04;
                   Data_TxRF[4] = 0x00;
                   Resp = Transparent_With_CRC( &Data_TxRF[0], 5, 5 , &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ); // timeout 8 ms 
                 }
             }
             else 
             {  
                 if ((CMD_Category == 1) && (index == 11))
                 {               
                   BC45_OFF_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
                   Delay_ms(2);
                 
                   BC45_ON_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
                   Delay_ms(5);
                   Resp = _SUCCESS_;
                   temp_LenData_Resp = 0 ;
                 }
                 else
                 {
                   BC45_Timer_Set_Resp_Waiting_Time( 2 ) ; // Timeout 2 ms;
                   Resp = ISO14443A_WakeUp( &temp_Data_Resp[temp_Len_Old + 3], &temp_LenData_Resp ) ;
                 }     
             }
             
             temp_Data_Resp[temp_Len_Old]   = index;
             temp_Data_Resp[temp_Len_Old + 1]   = ((uint8_t)temp_LenData_Resp ) + 1 ;
             temp_Data_Resp[temp_Len_Old + 2]   = Resp;
             temp_Len_Old                   = temp_Len_Old + temp_LenData_Resp + 3 ;
             
             
             temp_Data_Resp[temp_Len_Old]   = 0xFF; // Separate Charactor
             temp_Data_Resp[temp_Len_Old+1] = 0xFF; // Separate Charactor
             temp_Len_Old                   = temp_Len_Old + 2;
             
             if ( (index == 2) || (index == 3) ) // HLTA || WUPB
             {
                if (Resp != NO_RESPONSE)
                {
                  Resp = INVALID_RESP ; 
                }
                else
                {
                  Resp = _SUCCESS_ ; 
                }
             }
             
             if ((Resp != NO_RESPONSE ) && (index == 6 ) && (Level > 1 )) // SELECT
             {
                index = index - 1;
             }
             else
             {
                index = index + 1; 
             }
             
        } ;

        
        
        
        temp_LenData_Resp              = temp_Len_Old - 2 ;
       // if (Resp != _SUCCESS_)
        index = index - 1;
        
      
        for ( i = 0 ; i < temp_LenData_Resp ; i++ )
	{
	   *( Data_Resp + i) = temp_Data_Resp[i] ; 
	}
	*( LenData_Resp ) = temp_LenData_Resp ; // Len Respnose	

	return (index) ;
}
#endif


/*******************************************************************************
* Function Name	: ISO14443A_Polling_Tags
* Description 	: 
* Input         : 
*				  - Polling_Option : 4-MSB = Polling_Protocol, Enabling protocol for polling 
*				                   : 4th - 14443B , 5th - 14443B, 6th - 15693
*				                   : 4-LSB = Polling_Loop
*				  - Reset_Field_En : Enable Field Reset before starting sequence command
*				  - Run_All_Step   : Execute following ISO14443AB_EMV_Load_Modulation routine
*                                                  : if tag is 15693, this input is neglected.
*                                 - CMD_Category   : CMD Sequence after polling complete 
*                                                  : Execute following ISO14443AB_EMV_Load_Modulation routine
*                                                  : if tag is 15693, this input is neglected.
*				  - First_Step     : Defines the 1st step of combo command for ISO14443A/B tags
*                                                  : if tag is 15693, this input is neglected.
*				  - No_Of_Step     : Number of Steps , defines the number of command to be executed
*                                                  : if tag is 15693, this input is neglected.
*                                                 
* Output        : 
*				  - if Tags = ISO14443 A / B :
*				                   : Last Index step + output from ISO14443AB_EMV_Load_Modulation routine
*                                 - if Tags = ISO15693
*				                   : UID
*                                 - if Tags = Multiple Tags
*				                   : Standard Found (1 byte) 
*                                                  : 1st - ISO14443A , 2nd - ISO14443B , 3rd - ISO15693 
* Return        : 
*				  - Tag_Type      : A0 - ISO14443A
*				                  : B0 - ISO14443B
*				                  : C0 - reserved
*				                  : D0 - ISO15693
*				                  : 00 - No Tags
*				                  : FF - Multiple Standard Tags found
*						
*******************************************************************************/
#ifdef ISO14443A_EMV_LOAD_MOD_ENABLE 
uint8_t ISO14443A_Polling_Tags ( uint8_t Polling_Option , uint8_t Reset_Field_En ,uint8_t Run_All_Step , uint8_t CMD_Category , uint8_t First_Step , uint8_t No_Of_Step, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
        uint16_t  i;
	uint8_t   Type_Found ;
        uint8_t   Tag_Type ;
        uint8_t   Polling_Standard ;
        uint8_t   Polling_Loop , Polling_Count ;
	uint8_t   Resp ;
	uint8_t   temp_Data_Resp[128] ;
	uint16_t  temp_LenData_Resp ;
        
	        
        //////////////// Polling Behavior /////////////////
        Type_Found    = 0 ;
        Polling_Count = 0 ;
        Polling_Loop  = 0x0F & Polling_Option ;
        
        while ( ( Polling_Count < Polling_Loop ) && ( Type_Found == 0 ) )
        {
           Polling_Standard  = 0xF0 & Polling_Option  ;
           if (Reset_Field_En == CHECK_ENABLE) 
           {   BC45_OFF_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
               Delay_ms(2);
           }
           BC45_ON_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
           Delay_ms(5);
            
           for ( i = 0 ; i < 4 ; i ++ )
           { 
              if (( Polling_Standard & 0x10 ) == 0x10 ) 
              { 
                if ( i == 0 ) 
                {
                   Resp = ISO14443A_Config( 0x00 ) ;
                   BC45_Timer_Set_Resp_Waiting_Time( 1 ) ;
                   Resp = ISO14443A_WakeUp( &temp_Data_Resp[0], &temp_LenData_Resp ) ;
                   if ( Resp == _SUCCESS_ )
                   {
                      BC45_Timer_Set_Resp_Waiting_Time( 1 ) ;  
                      Resp = ISO14443A_Halt( &temp_Data_Resp[0], &temp_LenData_Resp ) ;
                   }
                  
                }
                else if ( i == 1 )
                {
                   Resp = ISO14443B_Config( 0x00 ) ;
                   BC45_Timer_Set_Resp_Waiting_Time( 1 ) ;
                   Resp = ISO14443B_WakeUp( 0, 0 , &Data_TxRF[0], &temp_Data_Resp[0], &temp_LenData_Resp ) ;
                }
                else if ( i == 2 )
                {
                  Resp = ISO15693_Config( 0x11 ) ;  
                  BC45_Timer_Set_Resp_Waiting_Time( 1 ) ;
                  Resp = ISO15693_Inv_Req_1_Slot( 0x11, 0x01, 0x00 , 0x00 ,&Data_TxRF[0], &temp_Data_Resp[0], &temp_LenData_Resp  ) ;
                }
                
                if ( Resp == _SUCCESS_ )
                {
                   Type_Found |= ( 0x01 << i )   ; 
                }
              }
              Polling_Standard = Polling_Standard >> 1 ;
            }
            
            Polling_Count = Polling_Count + 1 ;
            if ( Type_Found == 0 ) 
            {   
                Delay_ms ( 100 );
            }
        }
        
        
        ////////////////// Combo Run Check //////////////////    
        
        if (Type_Found == 0x01 ) // ISO14443A Tag
        {
          Tag_Type = 0xA0 ;
          Resp = ISO14443A_EMV_Load_Modulation ( 1 , Run_All_Step , CMD_Category , First_Step , No_Of_Step , (Data_Resp + 1) , &temp_LenData_Resp ) ;
          * ( Data_Resp )     = Resp ;
        }
        else if ( Type_Found == 0x02 ) // ISO14443B Tag
        {
          Tag_Type = 0xB0 ;
          Resp = ISO14443B_EMV_Load_Modulation ( 1 , Run_All_Step , CMD_Category , First_Step , No_Of_Step , (Data_Resp + 1) , &temp_LenData_Resp ) ;
          * ( Data_Resp )     = Resp ;
        }
        else if ( Type_Found == 0x04 )
        {
          Tag_Type = 0xD0 ;
          BC45_OFF_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
          Delay_ms(2);
          Resp = ISO15693_Config( 0x11 ) ;  
          BC45_Timer_Set_Resp_Waiting_Time( 1 ) ;
          Resp = ISO15693_Inv_Req_1_Slot( 0x11, 0x01, 0x00 , 0x00 ,&Data_TxRF[0], (Data_Resp + 1), &temp_LenData_Resp  ) ;
          * ( Data_Resp )     = Resp ;
        }
        else if ( Type_Found == 0x00 ) // No Tag
        {
          Tag_Type = 0x00 ;
          temp_LenData_Resp = 0 ;
          * ( Data_Resp )     = 0x00 ;
        }
        else // Multiple Tag Detect
        {
          Tag_Type = 0xFF ;
          temp_LenData_Resp = 0 ;
          * ( Data_Resp )     = Type_Found ;
        }
  
        * ( LenData_Resp )  = ( temp_LenData_Resp + 1 ) ;
        
        return ( Tag_Type ) ;
}
#endif
