/*****************************************************************************
* File Name          : BC45_Chip_Function.c
* Author             : CrystalSu
* Version            : V1.0.0.0
* Date               : Feb 10, 2020
******************************************************************************/

#include "Delay.h"
#include "BC45_Chip_Function.h"
#include "Systick_For_Timeout.h"
#include "htk_spi.h"
#include "htk_uart.h"

//****************************************************************************//
uint8_t	 Data_Wr[65] ; // 0-64 = 65 Bytes
uint8_t  Data_Rd[65] ; // 0-64 = 65 Bytes
volatile uint8_t  BC_Chip_Type ;

tBC45_BOARD_PROPERTY  BC45_BOARD_PROPERTY ;

tStandard_Param   Param_14443A_106 ;
tStandard_Param   Param_14443A_212 ;
tStandard_Param   Param_14443A_424 ;
tStandard_Param   Param_14443A_848 ;
tStandard_Param   Param_14443B_106 ;
tStandard_Param   Param_14443B_212 ;
tStandard_Param   Param_14443B_424 ;
tStandard_Param   Param_14443B_848 ;
tStandard_Param   Param_15693_1sub_lo ;
tStandard_Param   Param_15693_1sub_hi ;
tStandard_Param   Param_15693_1sub_uhi ;
tStandard_Param   Param_15693_2sub_lo ;
tStandard_Param   Param_15693_2sub_hi ;

uint8_t	  Data_TxRF[DATA_RF_BUFFER_SIZE] ;
uint8_t   Data_RxRF[DATA_RF_BUFFER_SIZE] ;
uint16_t  LenData_TxRF ;
uint16_t  LenData_RxRF ;

/*******************************************************************************
* Function Name  : Set RSTPD pin
* Description    : None
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void BC45_RSTPD_SET(void)
{
	// Fill GPIO port and PIN which will be use for RSTPD
	//RSTPD_SET(NULL, NULL);
	RSTPD_SET(BC45_RSTPD_GPIO_Port, BC45_RSTPD_Pin);	
}


/*******************************************************************************
* Function Name  : Clear RSTPD pin
* Description    : None
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void BC45_RSTPD_CLR(void)
{
	// Fill GPIO port and PIN which will be use for RSTPD
	//RSTPD_CLR(NULL, NULL);
	RSTPD_CLR(BC45_RSTPD_GPIO_Port, BC45_RSTPD_Pin);	
}


/*******************************************************************************
* Function Name  : BC45 IRQ PIN
* Description    : Check BC45 IRQ Pin which connected to BC45 IRQ pin
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8_t BC45_IRQ_PIN(void)
{
	return IRQ_PIN(BC45_IRQ_GPIO_Port, BC45_IRQ_Pin);
}


/*******************************************************************************
* Function Name  : BC45_Chip_Reset
* Description    : Reset BC45 and check Chip version
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void BC45_Chip_Reset( void ) 
{
	BC45_RSTPD_SET() ;
	Delay_ms( 10 ) ;
	BC45_RSTPD_CLR() ;
	Delay_ms( 10 ) ;
	BC_Chip_Type = BC45_Get_Chip_Version();
}


/*******************************************************************************
* Function Name : BC45_Read_CollPos
* Description   : Read Collision Position Register(Reg 0x0B)
* Input         : None
* Output        : None
* Return        : Data in register 
*******************************************************************************/
uint8_t BC45_Read_CollPos( void )
{
	htk_SPI_readSingleRegister(CollPosReg, &Data_Rd[CollPosReg]);

	return Data_Rd[CollPosReg] ;	
} 

/*******************************************************************************
* Function Name : BC45_Read_RxLastBit
* Description   : Read Secondary status Register(Reg 0x05), bit2:0 (RxLastBit bits)
* Input         : None
* Output        : None
* Return        : Data in register (Bit2:0)
*******************************************************************************/
uint8_t BC45_Read_RxLastBit( void )
{
	htk_SPI_readSingleRegister(SecondStatus, &Data_Rd[SecondStatus]);

	Data_Rd[SecondStatus] = Data_Rd[SecondStatus] & 0x07 ;
	
	return Data_Rd[SecondStatus] ;		
}

/*******************************************************************************
* Function Name : BC45_Read_FIFOLength
* Description   : Read FIFOLength Register(Reg 0x04)
* Input         : None
* Output        : None
* Return        : Data in register
*******************************************************************************/
uint8_t BC45_Read_FIFOLength( void )
{
	htk_SPI_readSingleRegister(FIFOLength, &Data_Rd[FIFOLength]);

	return Data_Rd[FIFOLength] ;	
}

/*******************************************************************************
* Function Name : BC45_ReadErrReg
* Description   : Read Error Flag Register(Reg 0x0A)
* Input         : None
* Output        : None
* Return        : Data in register
*******************************************************************************/
uint8_t BC45_ReadErrReg( void )
{
	htk_SPI_readSingleRegister(ErrorReg, &Data_Rd[ErrorReg]);

	return Data_Rd[ErrorReg] ;	
}

/*******************************************************************************
* Function Name : BC45_Check_RFErr
* Description   : Return error in Error Flag Resgister(Reg 0x0A) ralated to RF communication if error exists. Key Err is excluded.
*				  If More than one error occur, BC45_Check_RFErr reports only one error having the highest priority. 
*				  The priority of errors are listed as follows (The top most is the highest priority)
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*				  If there is no error, _SUCCESS_ is returned.
* Input         : None
* Output        : None
* Return        : 
*				  - Err_Status
*						- _SUCCESS_
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*******************************************************************************/
uint8_t BC45_Check_RFErr( void )
{
	uint8_t  Err_Status ;

	htk_SPI_readSingleRegister(ErrorReg, &Data_Rd[ErrorReg]);
	
	if ( (Data_Rd[ErrorReg] & FramingErr_Mask) == FramingErr_Mask )											  
	{	// Highest priority																	  						  
		Err_Status = FRAMING_ERR ; 
	}																								  
	else if ( (Data_Rd[ErrorReg] & CollErr_Mask) == CollErr_Mask )									  
	{																		  						  
		Err_Status = COLLISION_ERR ; 
	}																		  						  
	else if ( (Data_Rd[ErrorReg] & ParityErr_Mask) == ParityErr_Mask )								  
	{																		  						  
		Err_Status = PARITY_ERR ; 
	}																								  
	else if ( (Data_Rd[ErrorReg] & CRCErr_Mask) == CRCErr_Mask )
	{	
		Err_Status = CRC_ERR ; 
	}
	else if ( (Data_Rd[ErrorReg] & FIFOOvfl_Mask) == FIFOOvfl_Mask )
	{	
		Err_Status = BUFFER_OVERFLOW_ERR ; 
	}
	else
	{	// No Err
		Err_Status = _SUCCESS_ ; 
	}
	
	return Err_Status ;
} 

/*******************************************************************************
* Function Name : BC45_Check_E2Err
* Description   : Return error in Error Flag Resgister(Reg 0x0A) related to EEPROM operation if error exists. Key Err is excluded.
*				  If More than one error occur, BC45_Check_E2Err reports only one error having the highest priority. 
*				  The priority of errors are listed as follows (The top most is the highest priority)
*						- BUFFER_OVERFLOW_ERR
*						- ACCESS_E2_ERR
*						- WRITE_E2_ERR
*				  If there is no error, _SUCCESS_ is returned.
* Input         : None
* Output        : None
* Return        : 
*				  - Err_Status
*						- _SUCCESS_
*						- BUFFER_OVERFLOW_ERR
*						- ACCESS_E2_ERR
*						- WRITE_E2_ERR
*******************************************************************************/
uint8_t BC45_Check_E2Err( void )
{
	uint8_t  Err_Status ;
	// Read Error Flag Register (0x0A)
	htk_SPI_readSingleRegister(ErrorReg, &Data_Rd[ErrorReg]);
	
     if ( (Data_Rd[ErrorReg] & FIFOOvfl_Mask) == FIFOOvfl_Mask )
	{	
		Err_Status = BUFFER_OVERFLOW_ERR ; 
	}
	else if ( (Data_Rd[ErrorReg] & AccessErr_Mask) == AccessErr_Mask )
	{	
		Err_Status = ACCESS_E2_ERR ; 
	}
	else if ( (Data_Rd[ErrorReg] & E2Err_Mask) == E2Err_Mask )
	{	
		Err_Status = WRITE_E2_ERR ; 
	}
	else
	{	// No Err
		Err_Status = _SUCCESS_ ; 
	}
	
	return Err_Status ;
}

/*******************************************************************************
* Function Name : BC45_Check_KeyErr
* Description   : Check the Key format in Master Key buffer by reading Err flag register(Reg 0x0A), bit6 (KeyErr bit)
* Input         : None
* Output        : None
* Return        : 
*				  - Err_Status
*						- KEY_ERR  
*						- _SUCCESS_ 
*******************************************************************************/
uint8_t BC45_Check_KeyErr( void )
{
	uint8_t  Err_Status ;

	// Read Error Flag Register(0x0A)
	htk_SPI_readSingleRegister(ErrorReg, &Data_Rd[ErrorReg]);
	if ( (Data_Rd[ErrorReg] & KeyErr_Mask) == KeyErr_Mask )											  
	{																		  						  
		Err_Status = KEY_ERR ; 
	}																								  
	else if ( (Data_Rd[ErrorReg] & AccessErr_Mask) == AccessErr_Mask )
	{	
		Err_Status = ACCESS_E2_ERR ; 
	}
	else
	{
		Err_Status = _SUCCESS_ ; 
	}

	return Err_Status ;
} 

/*******************************************************************************
* Function Name : BC45_Check_Crypto_Bit
* Description   : Check if Crypto1-Hardware is active by reading the control register, bit3 (Crypto_On bit) 
* Input         : None
* Output        : None
* Return        :  
*				  - Bit Status
*						- CRYPTO_NOT_ON
*						- CRYPTO_ON
*******************************************************************************/
uint8_t BC45_Check_Crypto_Bit( void )
{
	uint8_t  Bit_Status ;

	// Read Control Register (0x09) 
	htk_SPI_readSingleRegister(ControlReg, &Data_Rd[ControlReg]);
	if ( (Data_Rd[ControlReg] & Crypto1On_Mask) == Crypto1On_Mask )											  
	{																		  						  
		Bit_Status = CRYPTO_ON ;	
	}																								  
	else
	{
		Bit_Status = CRYPTO_NOT_ON ;	
	}

	return  Bit_Status ;
}


/*******************************************************************************
* Function Name : BC45_WriteFIFO
* Description   : Write data into FIFO register(Reg 0x02)
* Input         :  
*				  - Data_Wr
*				  - LenData_Wr
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_WriteFIFO( uint8_t *Data_Wr, uint16_t LenData_Wr ) 
{ 	
	htk_SPI_writeMultiData(FIFOData, Data_Wr, LenData_Wr);
}

/*******************************************************************************
* Function Name : BC45_WriteCMD
* Description   : Execute command by Writing command into Command Register(Reg 0x01)
* Input         : 
*				  - Command
*				   		- CMDIdle
*				   		- CMDTransmit
*				   		- CMDReceive
*				   		- CMDTranceive
*				   		- CMDWriteE2
*				   		- CMDReadE2
*				   		- CMDLoadConfig
*				   		- CMDCalCRC
*				   		- CMDLoadKey
*				   		- CMDLoadKeyE2
*				   		- CMDAuthent
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_WriteCMD( uint8_t CMD )
{ 	
	htk_SPI_writeSingleRegister(CommandReg, CMD);
}

/*******************************************************************************
* Function Name : BC45_Set_BitFraming
* Description   : Set BitFraming Tx, Rx by configure BitFraming Resgister(Reg 0x0F)
* Input         : 
*				  - RxAling
*				  - TxLastBit
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Set_BitFraming( uint8_t RxAlign, uint8_t TxLastBit )
{

	Data_Wr[BitFramingReg] = ( RxAlign << 4 ) | TxLastBit ;
	htk_SPI_writeSingleRegister(BitFramingReg, Data_Wr[BitFramingReg]);
}

/*******************************************************************************
* Function Name : BC45_Set_CollMaskVal_Bit
* Description   : Set CollMaskVal Bit in Decoder Control Register(Reg 0x1A), bit6 (CollMaskVal bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Set_CollMaskVal_Bit( void )
{
	htk_SPI_readSingleRegister(DecoderControl, &Data_Rd[DecoderControl]);
	Data_Wr[DecoderControl] = Data_Rd[DecoderControl] | CollMaskVal_Set_Mask ; // Set CollMaskValue Bit = '1'
	htk_SPI_writeSingleRegister(DecoderControl, Data_Wr[DecoderControl]);
}

/*******************************************************************************
* Function Name : BC45_Clear_CollMaskVal_Bit
* Description   : Clear CollMaskVal Bit in Decoder Control Register(Reg 0x1A), bit6 (CollMaskVal bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Clear_CollMaskVal_Bit( void )
{
	htk_SPI_readSingleRegister(DecoderControl, &Data_Rd[DecoderControl]);
	Data_Wr[DecoderControl] = Data_Rd[DecoderControl] & CollMaskVal_Clear_Mask ; // Clear CollMaskValue Bit = '0'  		
	htk_SPI_writeSingleRegister(DecoderControl, Data_Wr[DecoderControl]);
}

/*******************************************************************************
* Function Name : BC45_CRC_Setting
* Description   : Enable or Disable appending Tx CRC bytes and checking Rx CRC bytes, by setting or clearing TxCRC and RxCRC bit
* Input         : 
*				  - TxCRC :
*						- TxCRC_Disable
*						- TxCRC_Enable
*				  - RxCRC :
*						- RxCRC_Disable
*						- RxCRC_Enable
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_CRC_Setting( uint8_t TxCRC, uint8_t RxCRC )
{
	htk_SPI_readSingleRegister(CRCSetting,  &Data_Rd[CRCSetting]);
	if ( TxCRC == TxCRC_Enable )
	{
		Data_Rd[CRCSetting] |= TxCRCEn_Set_Mask ; 		
	}
	else
	{
		Data_Rd[CRCSetting] &= TxCRCEn_Clear_Mask  ; 		
	}

	if ( RxCRC == RxCRC_Enable )
	{
		Data_Rd[CRCSetting] |= RxCRCEn_Set_Mask ; 		
	}
	else
	{
		Data_Rd[CRCSetting] &= RxCRCEn_Clear_Mask ; 		
	}

	Data_Wr[CRCSetting] = Data_Rd[CRCSetting] ;
	htk_SPI_writeSingleRegister(CRCSetting, Data_Wr[CRCSetting]);
}

/*******************************************************************************
* Function Name : BC45_Clear_Crypto1On_Bit
* Description   : Disable the crypto1-engine by Clearing Crypto Bit in Control Register(Reg 0x09), bit3 (Crypto_On bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Clear_Crypto1On_Bit( void )
{	
	// Read Register 0x09 before Write
	htk_SPI_readSingleRegister(ControlReg, &Data_Rd[ControlReg]);
	// Clear Only Crypto Bit (Bit3)
	Data_Wr[ControlReg] = Data_Rd[ControlReg] & Crypto1On_Clear_Mask ;
	htk_SPI_writeSingleRegister(ControlReg, Data_Wr[ControlReg]);
}

/*******************************************************************************
* Function Name : BC45_Flush_FIFO
* Description   : Clear the FIFO buffer by Setting FlushFIFO Bit in Control Register(0x09), bit0 (Flush FIFO bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Flush_FIFO( void )
{	
	// Read Register 0x09 before write
	htk_SPI_readSingleRegister(ControlReg, &Data_Rd[ControlReg]);
	// Set Only FlushFIFO Bit (Bit0)
	Data_Wr[ControlReg] = Data_Rd[ControlReg] | FlushFIFO_Set_Mask ;
	htk_SPI_writeSingleRegister(ControlReg, Data_Wr[ControlReg]);
}

/*******************************************************************************
* Function Name : BC45_Disable_And_Clear_Flag_IRQ
* Description   : Disable interrupt and clear interrupt flag by Clearing Interrupt Enable and Interrupt Flag Register (Reg 0x06, 0x07)
* Input         : 
*				  - IRQ_Source : IRQ Source as defined in Interrupt enable and Interrupt flag register (BC45 Datasheet)
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Disable_And_ClearFlag_IRQ( uint8_t IRQ_Source )
{	
	uint8_t  temp_IRQ_Source ;

	temp_IRQ_Source = 0x7F & IRQ_Source ; // Force MSB Bit is '0' 
	
	htk_SPI_writeSingleRegister( InterruptEn, temp_IRQ_Source); //Disable Interrupt
	htk_SPI_writeSingleRegister(InterruptRq, temp_IRQ_Source); //Clear Interrupt
}

/*******************************************************************************
* Function Name : BC45_Clear_State_When_TimeOut
* Description   : Clear BC45 internal state to idle when timer interrupt occurs 
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Clear_State_When_TimeOut( void )
{
	// Disable all interrupt enable	reg
	// Disable all interrupt flag reg
	// Write Idle Cmd
	// Flush FIFO
	
	Data_Wr[InterruptEn] = CLEAR_ALL_IRQ_SOURCE ;	// Disable All Interrupt Source  
	Data_Wr[InterruptRq] = CLEAR_ALL_IRQ_SOURCE ;	// Clear All Interrupt Flg  
	Data_Wr[CommandReg]  = CMDIdle ;	// Write Idle Cmd 

	htk_SPI_writeSingleRegister(InterruptEn, Data_Wr[InterruptEn]);
	htk_SPI_writeSingleRegister(InterruptRq, Data_Wr[InterruptRq]);
	htk_SPI_writeSingleRegister(CommandReg , Data_Wr[CommandReg]);
	
	BC45_Flush_FIFO() ;
}

/*******************************************************************************
* Function Name : BC45_Set_Send1Pulse_Bit
* Description   : Set Send1Pluse Bit in CoderControl Register(Reg 0x14), bit7 (Send1Pluse bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Set_Send1Pulse_Bit( void )
{
	// Read Register 0x14 before write
	htk_SPI_readSingleRegister(CoderControl, &Data_Rd[CoderControl]);
	// Set Only Send1Pluse Bit (Bit7)
	Data_Wr[CoderControl] = Data_Rd[CoderControl] | Send1Pulse_Set_Mask ;
	htk_SPI_writeSingleRegister(CoderControl, Data_Wr[CoderControl]);
}

/*******************************************************************************
* Function Name : BC45_Clear_Send1Pulse_Bit
* Description   : Clear Send1Pluse Bit in CoderControl Register(0x14), bit7 (Send1Pluse bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Clear_Send1Pulse_Bit( void )
{
	// Read Register 0x14 before write
	htk_SPI_readSingleRegister(CoderControl, &Data_Rd[CoderControl]);
	// Clear Only Send1Pluse Bit (Bit7)
	Data_Wr[CoderControl] = Data_Rd[CoderControl] & Send1Pulse_Clear_Mask ;
	htk_SPI_writeSingleRegister(CoderControl, Data_Wr[CoderControl]);
}

/*******************************************************************************
* Function Name : BC45_Set_ModulatorSource
* Description   : Set ModulatorSource bits in TxControl Register(Reg 0x11), bit5:6
* Input         : 
*					- ModulatorSource
*						- ModSource_TriState
*						- ModSource_High
*						- ModSource_Internal
*						- ModSource_SIGIN0
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Set_ModulatorSource( uint8_t ModulatorSource ) 
{
	if ( ModulatorSource > ModSource_SIGIN0 )
	{
		ModulatorSource = ModSource_SIGIN0 ;
	}

	// Read Register 0x11 before write
	htk_SPI_readSingleRegister(TxControl, &Data_Rd[TxControl]);
	// Set Only ModulatorSource (Bit5:6)
	Data_Wr[TxControl] = (uint8_t)((Data_Rd[TxControl] & ModSource_Clear_Mask) | (uint8_t)(ModulatorSource << 5)) ;
	htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
}

/*******************************************************************************
* Function Name : BC45_Set_Force100ASK_Bit
* Description   : Set Force100ASK Bit in TxControl Register(Reg 0x11), bit4 (Force100ASK bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Set_Force100ASK_Bit( void ) 
{
	// Read Register 0x11 before write
	htk_SPI_readSingleRegister(TxControl, &Data_Rd[TxControl]);
	// Set Only Force100ASK Bit (Bit4)
	Data_Wr[TxControl] = Data_Rd[TxControl] | Force100ASK_Set_Mask ;
	htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
}

/*******************************************************************************
* Function Name : BC45_Clear_Force100ASK_Bit
* Description   : Clear Force100ASK Bit in TxControl Register(Reg 0x11), bit4 (Force100ASK bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Clear_Force100ASK_Bit( void ) 
{
	// Read Register 0x11 before write
	htk_SPI_readSingleRegister(TxControl, &Data_Rd[TxControl]);
	// Clear Only Force100ASK Bit (Bit4)
	Data_Wr[TxControl] = Data_Rd[TxControl] & Force100ASK_Clear_Mask ;
	htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
}

/*******************************************************************************
* Function Name : BC45_ON_RF
* Description   : Turn on RF field, depending on driver type, by configure TxControl register(Reg 0x11)
* Input         : 
*				  - Driver_Config_Type : 
*						- DRIVER_CONFIG_X_CC     : Diffential Close Coupling Network with internal envelope
*						- DRIVER_CONFIG_X_CCXENV : Diffential Close Coupling Network with external envelope
*						- DRIVER_CONFIG_X_CCXENV : Diffential Close Coupling Network with external envelope
*						- DRIVER_CONFIG_X_E50OUT : 50 ohm output from Class-E driver with external envelope 
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_ON_RF( uint8_t  Driver_Config_Type ) 
{
	if(Driver_Config_Type == DRIVER_CONFIG_X_E50OUT) // For Class-E Antenna
	{	
		// Read Register 0x11 before write
		htk_SPI_readSingleRegister(TxControl, &Data_Rd[TxControl]);
		Data_Wr[TxControl] = ((Data_Rd[TxControl] & Force100ASK_Clear_Mask & TX2Inv_Clear_Mask & TX1RFEn_Clear_Mask)
                         | TX2Cw_Set_Mask | TX2RFEn_Set_Mask);
		htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
	}
	else
	{
		// Read Register 0x11 before write
		htk_SPI_readSingleRegister(TxControl, &Data_Rd[TxControl]);
		// Set Only Bit TX2RFEn and TX1RFEn (Bit1:0)
		Data_Wr[TxControl] = (Data_Rd[TxControl] | TX2RFEn_Set_Mask | TX1RFEn_Set_Mask);	
		htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
	}
}

/*******************************************************************************
* Function Name : BC45_OFF_RF
* Description   : Turn off RF field, depending on driver type, by configure TxControl register(Reg 0x11)
* Input         : 
*				  - Driver_Config_Type : 
*						- DRIVER_CONFIG_X_CC     : Diffential Close Coupling Network with internal envelope
*						- DRIVER_CONFIG_X_CCXENV : Diffential Close Coupling Network with external envelope
*						- DRIVER_CONFIG_X_CCXENV : Diffential Close Coupling Network with external envelope
*						- DRIVER_CONFIG_X_E50OUT : 50 ohm output from Class-E driver with external envelope 
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_OFF_RF( uint8_t  Driver_Config_Type ) 
{
	if(Driver_Config_Type == DRIVER_CONFIG_X_E50OUT) // For Class-E Antenna
	{	
		// Read Register 0x11 before write
		htk_SPI_readSingleRegister(TxControl, &Data_Rd[TxControl]);
		Data_Wr[TxControl] = (Data_Rd[TxControl] & (~ModSource_Clear_Mask)); 
		htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
	}
	else
	{
		// Read Register 0x11 before write
		htk_SPI_readSingleRegister(TxControl, &Data_Rd[TxControl]);
		// Clear only bit TX2RFEn and TX1RFEn (Bit1:0)	
		Data_Wr[TxControl] = (Data_Rd[TxControl] & TX2RFEn_Clear_Mask & TX1RFEn_Clear_Mask); 
		htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
	}
}

/*******************************************************************************
* Function Name : BC45_Timer_Tstart_Tstop_Control
* Description   : Configure the timer start and stop in TimerControl Register(Reg 0x2B)
* Input         : 
*				  - TStartWhen : 
*						- TimerManual 
*						- TStartTxBegin 
*						- TStartTxEnd 
*				  - TStopWhen  :  
*						- TimerManual 
*						- TStopRxBegin 
*						- TStopRxEnd 
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Timer_Tstart_Tstop_Control( uint8_t TStartWhen, uint8_t TStopWhen ) 
{	
	Data_Wr[TimerControl] = TStartWhen  | ( TStopWhen << 2 ) ;	
	htk_SPI_writeSingleRegister(TimerControl, Data_Wr[TimerControl]);
}

/*******************************************************************************
* Function Name : BC45_Timer_Set_Resp_Waiting_Time
* Description   : set the RFID data response waiting time after transmision by configure TimerClock, TimerReloadValue Register(Reg 0x2A, 0x2C)
* Input         : 
*				  - Time :
*				 		- 0x00 -- Use prior setting
*				   		- 0x01 -- ~ 1   ms
*				   		- 0x02 -- ~ 2   ms
*				   		- 0x03 -- ~ 4   ms
*				   		- 0x04 -- ~ 8   ms
*				   		- 0x05 -- ~ 16  ms
*				   		- 0x06 -- ~ 32  ms
*				   		- 0x07 -- ~ 64  ms
*				   		- 0x08 -- ~ 128 ms
*				   		- 0x09 -- ~ 256 ms
*				   		- 0x0A -- ~ 512 ms
*				   		- 0x0B -- ~ 1   s
*				   		- 0x0C -- ~ 2   s
*				   		- 0x0D -- ~ 4   s
*				   		- 0x0E -- ~ 8   s
*				   		- 0x0F -- ~ 16  s
*				   		- 0x10 -- ~ 32  s
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Timer_Set_Resp_Waiting_Time( uint8_t Time ) 
{	
	if ( Time != 0 )  // Time = 0 : use previous value
	{
		// Read Register 0x2A before write
		htk_SPI_readSingleRegister(TimerClock, &Data_Rd[TimerClock]);
		// Change only TPreScaler (Bit4:0)
		Data_Wr[TimerClock]  = ( Data_Rd[TimerClock] & TPreScaler_Clear_Mask ) | ( ( Time + 5 ) & TPreScaler_Mask )  ;	
		Data_Wr[TimerReload] = 0xD4 ;	// TReload Value = 212 (Fixed)

		htk_SPI_writeSingleRegister(TimerClock, Data_Wr[TimerClock]);
		htk_SPI_writeSingleRegister(TimerReload, Data_Wr[TimerReload]);
	}
}

/*******************************************************************************
* Function Name : BC45_Start_Timer
* Description   : Set TStartNow Bit in Control Register(0x09), bit1 (TStartNow bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Start_Timer( void )
{	
	// Read Register 0x09 before write
	htk_SPI_readSingleRegister(ControlReg, &Data_Rd[ControlReg]);
	// Set Only Bit TStartNow (Bit1)
	Data_Wr[ControlReg] = Data_Rd[ControlReg] | TStartNow_Set_Mask ;
	htk_SPI_writeSingleRegister(ControlReg, Data_Wr[ControlReg]);
}

/*******************************************************************************
* Function Name : BC45_Stop_Timer
* Description   : Set TStopNow Bit in Control Register(0x09), bit2 (TStopNow bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Stop_Timer( void )
{	
	// Read Register 0x09 before write
	htk_SPI_readSingleRegister(ControlReg, &Data_Rd[ControlReg]);
	// Set Only Bit TStopNow (Bit2)
	Data_Wr[ControlReg] = Data_Rd[ControlReg] | TStopNow_Set_Mask ;	
	htk_SPI_writeSingleRegister(ControlReg, Data_Wr[ControlReg]);
}

/*******************************************************************************
* Function Name : BC45_SOFEOF_Selection
* Description   : Set SOF and EOF width in TypeBFraming register(Reg 0x17)
* Input         : 
*				  - SOF_EOF_Sel : SOF_Sel(4 bits) + EOF_Sel(4 bits)
*						High Nibble : SOF_Sel(Bit7:4)
*							- 0 : SOF = 10 etu + 2 etu
*							- 1 : SOF = 10 etu + 3 etu
*							- 2 : SOF = 11 etu + 2 etu
*							- 3 : SOF = 11 etu + 3 etu
*							- Other : SOF = 11 etu + 3 etu
*						Low Nibble : EOF_Sel(Bit3:0)
*							- 0 : EOF = 10 etu
*							- 1 : EOF = 11 etu
*							- Other : EOF = 11 etu
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_SOFEOF_Selection( uint8_t SOF_EOF_Sel )
{	
	uint8_t  SOF_SEL, EOF_SEL ;

	// Read Register 0x17 before write 
	htk_SPI_readSingleRegister(TypeBFraming, &Data_Rd[TypeBFraming]);
	Data_Rd[TypeBFraming] &= ( EOFWidth_Clear_Mask & SOFWidth_Clear_Mask ) ;
	
	SOF_SEL = ( SOF_EOF_Sel >> 4 ) ;
	EOF_SEL = ( 0x0F & SOF_EOF_Sel ) ;
	
	// SOF Sel
	if ( SOF_SEL == SOF_10etu_Add_2etu ) 
	{
		Data_Rd[TypeBFraming] |= SOF_10etu_Add_2etu_Set_Mask ;
	}
	else if ( SOF_SEL == SOF_10etu_Add_3etu ) 
	{
		Data_Rd[TypeBFraming] |= SOF_10etu_Add_3etu_Set_Mask ;
	}
	else if ( SOF_SEL == SOF_11etu_Add_2etu ) 
	{
		Data_Rd[TypeBFraming] |= SOF_11etu_Add_2etu_Set_Mask ;
	}
	else // Default 11etu + 3etu
	{
		Data_Rd[TypeBFraming] |= SOF_11etu_Add_3etu_Set_Mask ;
	}
	
	// EOF Sel
	if ( EOF_SEL == EOF_10etu ) 
	{
		Data_Rd[TypeBFraming] |= EOF_10etu_Set_Mask ;
	}
	else // Default 11etu
	{
		Data_Rd[TypeBFraming] |= EOF_11etu_Set_Mask ;
	}

	Data_Wr[TypeBFraming] = Data_Rd[TypeBFraming] ;
	htk_SPI_writeSingleRegister(TypeBFraming, Data_Wr[TypeBFraming]);
}


/*******************************************************************************
* Function Name : BC45_Set_RxMultiple_Bit
* Description   : Set RxMultiple Bit in DecoderControl Register(0x09), bit7 (RxMultiple bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/

void BC45_Set_RxMultiple_Bit( void ) 
{
	// Read Register 0x1A before write
	htk_SPI_readSingleRegister(DecoderControl, &Data_Rd[DecoderControl]);
	// Set Only RxMultiple Bit (Bit7)
	Data_Wr[DecoderControl] = Data_Rd[DecoderControl] | RxMultiple_Set_Mask ;
	htk_SPI_writeSingleRegister(DecoderControl, Data_Wr[DecoderControl]);
}

/*******************************************************************************
* Function Name : BC45_Clear_RxMultiple_Bit
* Description   : Clear RxMultiple Bit in DecoderControl Register(0x09), bit7 (RxMultiple bit)
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/

void BC45_Clear_RxMultiple_Bit( void ) 
{
	// Read Register 0x1A before write
	htk_SPI_readSingleRegister(DecoderControl, &Data_Rd[DecoderControl]);
	// Clear Only RxMultiple Bit (Bit7)
	Data_Wr[DecoderControl] = Data_Rd[DecoderControl] & RxMultiple_Clear_Mask ;
	htk_SPI_writeSingleRegister(DecoderControl, Data_Wr[DecoderControl]);
}


/*******************************************************************************
* Function Name : BC45_IRQ_Execute_FIFO_Data
* Description   : Write data into FIFO of BC45 and execute command and wait until irq occurs 
*				  Transmitted Data can > 64 byte 

* Input         : 
*				  - CMD : Commands
*						- CMDTransmit(0x1A)
*						- CMDTransceive(0x1E)
*						- CMDWriteE2(0x01)
*						- CMDLoadKey(0x19)
*						- CMDLoadKeyE2(0x0B)
*						- Authent(0x1C)
*				  - Data 	    : Data
*				  - LenData		: Length of Data  
*				  - TimeOut_MCU_ms : TimeOut(For Microcontroller) unit is milli-second
* Output        : None
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_IRQ_Execute_FIFO_Data( uint8_t  CMD, uint8_t  *Data, uint16_t  LenData, uint16_t  TimeOut_MCU_ms )
{
	uint8_t   Status = 0, Flg_WriteCMD = 0, Flg_Tx_Complete = 0 ;
	uint16_t  Index = 0 ;
	
	// Enable Idle,LoAlert,Timer irq
	Data_Wr[InterruptEn] = 0x80 | TxIRQ | LoAlertIRQ | TimerIRQ | IdleIRQ ;	 
	htk_SPI_writeSingleRegister(InterruptEn, Data_Wr[InterruptEn]);

	// Start Timer Timeout X ms (Microcontroller)
	Systick_Timeout_Start( TimeOut_MCU_ms ) ; 
	do
	{
		// Check Timeout Controller
		if ( TimeOut_Check() != 1 )
		{
			if ( BC45_IRQ_PIN() == 1 )  // Check IRQ pin 
			{					
				// Check irq source
				htk_SPI_readSingleRegister(InterruptRq, &Data_Rd[InterruptRq]);// Read irq flag
				if ( ((Data_Rd[InterruptRq] & IdleIRQ) == IdleIRQ) || ((Data_Rd[InterruptRq] & TxIRQ) == TxIRQ) ) // Check irq flag that is IdleIRQ, TxIRQ or not ?
				{
					// Transmition complete
					BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
					Flg_Tx_Complete = 1 ;
					
					Status = _SUCCESS_ ;
				}
				else if ( (Data_Rd[InterruptRq] & TimerIRQ) == TimerIRQ )	// Check Timer irq	(Check Time Out)
				{	
					// Time out ChipReader(BC45)
					BC45_Clear_State_When_TimeOut() ;
					Flg_Tx_Complete = 1 ;
					
					Status = NO_RESPONSE ;
				}
				else if ( (Data_Rd[InterruptRq] & LoAlertIRQ) == LoAlertIRQ )	// Check IRQ flag that is a LoAlertIRQ or not ?
				{	
					if ( Index != LenData ) 
					{
						if ( (LenData - Index) > HiLevel ) // HiLevel = 64 - Water level
						{	
							// Write tx data into FIFO = HiLevel Bytes
							htk_SPI_writeMultiData(FIFOData, (Data + Index), HiLevel);
							Index = Index + HiLevel ;					
							
							// Clear LoAlert flag
							Data_Wr[InterruptRq] = 0x00 | LoAlertIRQ ;
							htk_SPI_writeSingleRegister(InterruptRq, Data_Wr[InterruptRq]);
						}
						else
						{	
							// Write Tx Data into FIFO = LenData - Index Bytes (Complete Writing)
							htk_SPI_writeMultiData(FIFOData, (Data + Index), (LenData - Index));
							Index = LenData ;			
					
							// Should be disable LoAlertIRQ after write data completely.   
							// If not disable LoAlertIRQ ( It always active if not data in FIFO),It will not detect rising edged from irq pin(Cannot detect TxIRQ). 

							// Disable and Clear Flg LoAlertIRQ
							BC45_Disable_And_ClearFlag_IRQ( LoAlertIRQ ) ;
						}
					}

					if ( Flg_WriteCMD == 0 ) // Write data into FIFO before send command
					{	
						// Write Cmd	( Once time )
						Flg_WriteCMD = 1 ;
						BC45_WriteCMD( CMD ) ;
					}
				}
			}			
		}
		else
		{	
			// Time-Out (Microcontroller)
			BC45_Clear_State_When_TimeOut() ;
			Flg_Tx_Complete = 1 ;
			
			Status = ASIC_EXE_TIMEOUT ;
		}
	}
	while( !(Flg_Tx_Complete) ) ; // Check Tx complete

	Systick_Timeout_Stop() ;	// Stop Timer (Microcontroller)
	
	return Status ;
}

/*******************************************************************************
* Function Name : BC45_IRQ_Read_FIFO
* Description   : Read FIFO and store in Data_Rx until reception data complete(Idle IRQ occur)
* Input         : 
*				  - TimeOut_MCU_ms : TimeOut(For Microcontroller) unit is milli-second
*         - RxMultiple_En  : Enable RxMultiple Bit
* Output        : 
*				  - Data_Rx 	   		: Received Data 
*				  - LenData_Rx     : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_IRQ_Read_FIFO( uint8_t  *Data_Rx, uint16_t  *LenData_Rx, uint16_t  TimeOut_MCU_ms, uint8_t RxMultiple_En )
{
	uint8_t   Status = 0, Length = 0, Flg_Rx_Complete = 0, Rx_Slot = 0 ;
	uint16_t  Index = 0 ; 
	
	// Enable HiAlert,Idle,Timer IRQ
	Data_Wr[0x06] = 0x80 | HiAlertIRQ | IdleIRQ | TimerIRQ | RxIRQ ;
	htk_SPI_writeSingleRegister(InterruptEn, Data_Wr[0x06]);
        
	if( RxMultiple_En == 0x01)
	{
		 BC45_Set_RxMultiple_Bit();
	}
        
	// Start Timer Timeout X ms (Microcontroller)
	Systick_Timeout_Start( TimeOut_MCU_ms ) ; 
	do
	{
		// Timeout Controller
		if ( TimeOut_Check() != 1 )
		{
			if ( BC45_IRQ_PIN() == 1 )  // Check external interrupt(Interrput from BC45) 
			{						
				// Check irq source
				htk_SPI_readSingleRegister(InterruptRq, &Data_Rd[InterruptRq]);
				if ( ((Data_Rd[InterruptRq] & IdleIRQ) == IdleIRQ ) || ((Data_Rd[InterruptRq] & RxIRQ) == RxIRQ ) )		// Check irq flag that is a recieve complete or not ?
				{
					// Read FIFO length of data 
					htk_SPI_readSingleRegister(FIFOLength, &Length);

					if( ( Index + Length ) >= DATA_RF_BUFFER_SIZE )
					{
						BC45_Clear_State_When_TimeOut() ;
						*(LenData_Rx) = 0 ;	 // Force Num_data = 0 byte
						Flg_Rx_Complete = 1 ;
						Status = ASIC_EXE_TIMEOUT ;
					}
					else
					{
						htk_SPI_readSingleRegister(DecoderControl, &Data_Rd[0x1A]);
            if ( (Data_Rd[0x1A] & RxMultiple_Mask ) == RxMultiple_Mask)
						{
							if ( RxMultiple_En == 0x00 )
							{
								htk_SPI_readMultiData(FIFOData, (Data_Rx + Index), Length);
								Index += Length ;
							}
							else
							{
								* ( Data_Rx + Index )      = Rx_Slot ;
								* ( Data_Rx + Index + 1 )  = _SUCCESS_ ;
								* ( Data_Rx + Index + 2 )  = Length ;
								htk_SPI_readMultiData(FIFOData, (Data_Rx + Index + 3), Length);
								Index = Index + Length + 3 ;
								Rx_Slot ++ ;
							}
																					 
							Data_Wr[0x07] = 0x00 | RxIRQ ;
							htk_SPI_writeSingleRegister(InterruptRq, Data_Wr[0x07]);

							htk_SPI_readSingleRegister(ControlReg  , &Data_Rd[0x09]);
							
							//modify on 2021/10/28
							//Data_Rd[0x09] |= TStartNow_Set_Mask	;
							Data_Wr[0x09] = Data_Rd[0x09] | TStartNow_Set_Mask;
							htk_SPI_writeSingleRegister(ControlReg, Data_Wr[0x09]);
						}
						else
						{
							htk_SPI_readMultiData(FIFOData, (Data_Rx + Index), Length);
							Index += Length ;
							*(LenData_Rx) = Index ;
							BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
																									
							Flg_Rx_Complete = 1 ;
							Status = _SUCCESS_ ;
						}
					}
				}
        else if ( (Data_Rd[InterruptRq] & HiAlertIRQ) == HiAlertIRQ )	// Check HiAlert irq
				{
					if( ( Index + HiLevel ) >= DATA_RF_BUFFER_SIZE )
					{
						BC45_Clear_State_When_TimeOut() ;
						*(LenData_Rx) = 0 ;	 // Force Num_data = 0 byte
						Flg_Rx_Complete = 1 ;
						Status = ASIC_EXE_TIMEOUT ;
					}
					else
					{
						htk_SPI_readMultiData(FIFOData, (Data_Rx + Index), HiLevel);
						Index += HiLevel ;
	
						Data_Wr[InterruptRq] = 0x00 | HiAlertIRQ ;	// Clear irq HiAlertIRQ flag  
						htk_SPI_writeSingleRegister(InterruptRq, Data_Wr[InterruptRq]);
					}
				}
				else if ( (Data_Rd[InterruptRq] & TimerIRQ) == TimerIRQ )	// Check Timer irq(Check Time Out)
				{	
					// Time out ChipReader(BC45)
					Delay_us(5);
					BC45_Clear_State_When_TimeOut() ;
					Flg_Rx_Complete = 1 ;
					*(LenData_Rx) = Index ;
															
					if ( Index > 0 ) // Case of RxMultiple is set
					{
						Status = _SUCCESS_ ;
					}
					else
					{
						Status = NO_RESPONSE ;
					}
				}
			}					
		}
		else
		{	
			// Time-Out (Microcontroller)
			if ( Index > 0 ) // Case of RxMultiple is set
			{
					Status = _SUCCESS_ ;
			}
			else
			{
				Status = ASIC_EXE_TIMEOUT ;
			}
						
			*(LenData_Rx) = Index ; 	 // Force Num_data = 0 byte
			Flg_Rx_Complete = 1 ;
      BC45_Clear_State_When_TimeOut() ;
		}
	}
	while( !(Flg_Rx_Complete) ) ;

	Systick_Timeout_Stop() ;	// Stop Timer (Microcontroller)
	
	return Status ;
}

/*******************************************************************************
* Function Name : BC45_IRQ_Read_FIFO_TimeSlot 
* Description   : Read FIFO and store in Data_Rx until Timeout from TimerIRq
* Input         : 
*				  - TimeOut_MCU_ms : TimeOut(For Microcontroller) unit is milli-second
* Output        : 
*				  - Data_Rx 	   : Received Data 
*				  - LenData_Rx     : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_IRQ_Read_FIFO_TimeSlot( uint8_t  *Data_Rx, uint16_t  *LenData_Rx, uint16_t  TimeOut_MCU_ms )
{
	uint8_t   Status = 0, Length = 0, Flg_Rx_Complete = 0 ;
	uint16_t  Index = 0 ;
	
	// Enable HiAlert,Idle,Timer IRQ
	Data_Wr[0x06] = 0x80 | HiAlertIRQ | TimerIRQ | RxIRQ ;
	htk_SPI_writeSingleRegister(InterruptEn, Data_Wr[0x06]);
        
	// Start Timer Timeout X ms (Microcontroller)
	Systick_Timeout_Start( TimeOut_MCU_ms ) ; 
	do
	{
		// Timeout Controller
		if ( TimeOut_Check() != 1 )
		{
			if ( BC45_IRQ_PIN() == 1 )  // Check external interrupt(Interrput from BC45) 
			{						
				// Check irq source
				htk_SPI_readSingleRegister( InterruptRq, &Data_Rd[InterruptRq]);
				if ( (Data_Rd[InterruptRq] & RxIRQ) == RxIRQ )	// Check irq flag that Rx complete or not ?, for RxMultiple (IdleIrq not set)
				{
					// Read FIFO length of data 
					htk_SPI_readSingleRegister( FIFOLength,  &Length);

					// Read data in FIFO
					htk_SPI_readMultiData( FIFOData, (Data_Rx + Index), Length);
					Index += Length ;
					
					Data_Wr[InterruptRq] = 0x00 | RxIRQ ;	// Clear irq HiAlertIRQ flag  
					htk_SPI_writeSingleRegister(InterruptRq, Data_Wr[InterruptRq]);
				}
				else if ( (Data_Rd[InterruptRq] & HiAlertIRQ) == HiAlertIRQ )	// Check HiAlert irq
				{
					htk_SPI_readMultiData( FIFOData, (Data_Rx + Index), HiLevel);
					Index += HiLevel ;

					Data_Wr[InterruptRq] = 0x00 | HiAlertIRQ ;	// Clear irq HiAlertIRQ flag  
					htk_SPI_writeSingleRegister(InterruptRq, Data_Wr[InterruptRq]);
				}
				else if ( (Data_Rd[InterruptRq] & TimerIRQ) == TimerIRQ )	// Check Timer irq(Check Time Out)
				{	
					// Time out ChipReader(BC45)
					BC45_Clear_State_When_TimeOut() ;
					Flg_Rx_Complete = 1 ;
					
                    if (Index == 0)
                    {
                    	htk_SPI_readSingleRegister(SecondStatus, &Data_Rd[SecondStatus]);
                        if ((Data_Rd[SecondStatus] & 0x08) == 0x08)
                        {
                        	Status = SUBC_DET_ERR ;
                        }
                        else
                        {
                            Status = NO_RESPONSE ;
                        }
                    }
                    else
                    {
                        Status = _SUCCESS_ ;
                    }
				}
			}					
		}
		else
		{	
			// Time-Out (Microcontroller)
			BC45_Clear_State_When_TimeOut() ;
            Flg_Rx_Complete = 1 ;
            Status = ASIC_EXE_TIMEOUT ;
        }
	}
	while( !(Flg_Rx_Complete) ) ;

	Systick_Timeout_Stop();	// Stop Timer (Microcontroller)
    *(LenData_Rx) = Index ;
	
	return Status ;
}



/*******************************************************************************
* Function Name : BC45_Transmit
* Description   : Transmit data by executing transmit command
* Input         : 
*				  - Data_Tx    : Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : None
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Transmit( uint8_t  *Data_Tx ,uint16_t  LenData_Tx )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	// BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;

	//----------- Transmit ----------------//
	Resp = BC45_IRQ_Execute_FIFO_Data ( CMDTransmit, Data_Tx, LenData_Tx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;
		
	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_Receive
* Description   : Receive response data by executing receive command
* Input         : None
* Output        : 
*				  - Data_Rx    : Received Data
*				  - LenData_Rx : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Receive( uint8_t  *Data_Rx ,uint16_t  *LenData_Rx )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;

	BC45_Start_Timer() ;

	//------------------- Recieve -------------------//
	BC45_WriteCMD( CMDReceive ) ;
	Resp = BC45_IRQ_Read_FIFO( Data_Rx, LenData_Rx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val , 0 ) ;

	BC45_Stop_Timer() ;
	
	if ( Resp == _SUCCESS_ )  
	{
		Resp = BC45_Check_RFErr() ;
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		*( LenData_Rx ) = 0 ;		
	}
	
	return Resp ;
}


/*******************************************************************************
* Function Name : BC45_Receive_With_RxMultiple
* Description   : Receive response data by executing receive command and automatically set RxMultiple bit
* Input         : None
* Output        : 
*				  - Data_Rx    : Received Data
*				  - LenData_Rx : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Receive_With_RxMultiple ( uint8_t  *Data_Rx ,uint16_t  *LenData_Rx )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;

	BC45_Start_Timer() ;

	//------------------- Recieve -------------------//
	BC45_WriteCMD( CMDReceive ) ;
	Resp = BC45_IRQ_Read_FIFO( Data_Rx, LenData_Rx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val , 1 ) ;

	BC45_Stop_Timer() ;
	
	if ( Resp == _SUCCESS_ )  
	{
		Resp = BC45_Check_RFErr() ;
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		*( LenData_Rx ) = 0 ;		
	}
	
	return Resp ;
}


/*******************************************************************************
* Function Name : BC45_Receive_TimeSlot
* Description   : Receive response data by executing receive command
*               : Using Timer IRq to finish routine
* Input         : None
* Output        : 
*				  - Data_Rx    : Received Data
*				  - LenData_Rx : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Receive_TimeSlot( uint8_t  *Data_Rx ,uint16_t  *LenData_Rx )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	//------------------- Recieve -------------------//
	BC45_WriteCMD( CMDReceive ) ;
	Resp = BC45_IRQ_Read_FIFO_TimeSlot( Data_Rx, LenData_Rx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;

	if ( Resp == _SUCCESS_ )  
	{
        Resp = BC45_Check_RFErr() ;
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		*( LenData_Rx ) = 0 ;		
	}
	
	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_Transceive
* Description   : Transmit data and receive response data by executing transceive command
* Input         : 
*				  - Data_Tx 	: Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Rx 	: Received Data
*				  - LenData_Rx : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Transceive( uint8_t  *Data_Tx ,uint16_t  LenData_Tx, uint8_t  *Data_Rx ,uint16_t  *LenData_Rx )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TStartTxEnd, TStopRxBegin ) ;

	//----------- Transmit ----------------//
	//Resp = BC45_IRQ_Execute_FIFO_Data( CMDTranceive, Data_Tx, LenData_Tx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;
	Resp = BC45_IRQ_Execute_FIFO_Data( CMDTranceive, Data_Tx, LenData_Tx, 5000 ) ;
	
  if ( Resp == _SUCCESS_ )
	{
		//------------------- Recieve -------------------//
		//Resp = BC45_IRQ_Read_FIFO( Data_Rx, LenData_Rx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val , 0 ) ;
		Resp = BC45_IRQ_Read_FIFO( Data_Rx, LenData_Rx, 10000 , 0 ) ;
		if ( Resp == _SUCCESS_ )  
		{
			Resp = BC45_Check_RFErr() ;	
		}
		else
		{	// Time-out Timer BC45, Time out MCU
			*( LenData_Rx ) = 0 ;			
		}
	}
	else
	{
		*( LenData_Rx ) = 0 ;		
	}

	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_Transceive_NFC_Type1
* Description   : Transmit 1 byte data and receive response data following NFC type1 tag
* Input         : 
*				  - Data_Tx 	: Transmitted Data
*				  - LenData_Tx  : Length of Transmitted Data  
*         - RxCRCEn     : Enable Rx CRC
* Output        : 
*				  - Data_Rx 	: Received Data
*				  - LenData_Rx  : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Transceive_NFC_Type1( uint8_t  *Data_Tx ,uint16_t  LenData_Tx, uint8_t  *Data_Rx ,uint16_t  *LenData_Rx, uint8_t RxCRCEn )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TStartTxEnd, TStopRxBegin ) ;

	//----------- Transmit ----------------//
	Resp = BC45_IRQ_Execute_FIFO_Data( CMDTranceive, Data_Tx, LenData_Tx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;
	if ( RxCRCEn == 0)
	{
		Data_Wr[CRCSetting]   = 0x23 ;	// Enable Parity
	}
	else
	{
			Data_Wr[CRCSetting]   = 0x2B ;	// Enable Parity, and CRC
	}
	htk_SPI_writeSingleRegister(CRCSetting, Data_Wr[CRCSetting]);
			
	if ( Resp == _SUCCESS_ )
	{
        //------------------- Recieve -------------------//
		Resp = BC45_IRQ_Read_FIFO( Data_Rx, LenData_Rx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val , 0 ) ;
               
		if ( Resp == _SUCCESS_ )  
		{
				Resp = BC45_Check_RFErr() ;
								
				if (Resp == PARITY_ERR) // other version cannot manage parity problem
				{
					Resp = _SUCCESS_;
				}
		}
		else
		{	// Time-out Timer BC45, Time out MCU
			*( LenData_Rx ) = 0 ;			
		}
	}
	else
	{
		*( LenData_Rx ) = 0 ;		
	}

	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_Transceive_With_RxMultiple (available for BC45B4523)
* Description   : Transmit data and receive response data by executing transceive command and automatically set RxMultiple bit
* Input         : 
*				  - Data_Tx 	: Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Rx 	: Received Data 
*                                               : RxSlot[0] + Resp[0] + Len[0] + Data[0][0] + ... + Data[0][N-1] + ... 
*                                                + RxSlot[n] + Resp[n] + Len[n] + Data[n][0] + ... + Data[n][N-1] + ... 
*				  - LenData_Rx  : Length of Received Data  
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Transceive_With_RxMultiple ( uint8_t  *Data_Tx ,uint16_t  LenData_Tx, uint8_t  *Data_Rx ,uint16_t  *LenData_Rx )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TStartTxEnd, TStopRxBegin ) ;

	//----------- Transmit ----------------//
	Resp = BC45_IRQ_Execute_FIFO_Data( CMDTranceive, Data_Tx, LenData_Tx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;
	
    if ( Resp == _SUCCESS_ )
	{
		//------------------- Recieve -------------------//
		Resp = BC45_IRQ_Read_FIFO( Data_Rx, LenData_Rx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val , 1 ) ;
		if ( Resp == _SUCCESS_ )  
		{
			Resp = BC45_Check_RFErr() ;	
		}
		else
		{	// Time-out Timer BC45, Time out MCU
			*( LenData_Rx ) = 0 ;			
		}
	}
	else
	{
		*( LenData_Rx ) = 0 ;		
	}

	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_ReadE2
* Description   : Read data form BC45 EEPROM
* Input         : 
*				  - StartAddr     : First address that read from BC45 EEPROM
*				  - LenData_Rd_E2 : Length of read data  
* Output        : 
*				  - Data_E2 	   : Data that read from EEPROM
*				  - LenData_E2    : Length of read Data
* Return        : 
*				  - Status
* 				    	- _SUCCESS_
*						- ACCESS_E2_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_ReadE2( uint8_t StartAddr, uint8_t LenData_Rd_E2, uint8_t *Data_E2, uint16_t *LenData_E2 )
{
	uint8_t   Resp ;
	uint8_t   Data[2] ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;
	
	Data[0]	= StartAddr ;
	Data[1] = LenData_Rd_E2 ;
	BC45_WriteFIFO( Data, 2 ) ; 
	
	//----------- Read E2 ----------------//
	BC45_WriteCMD( CMDReadE2 ) ;	
	Resp = BC45_IRQ_Read_FIFO( Data_E2, LenData_E2, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val , 0 ) ;

	if ( Resp == _SUCCESS_ )  
	{
		Resp = BC45_Check_E2Err() ;
		if ( Resp == _SUCCESS_ )
		{
			if ( *(LenData_E2) != LenData_Rd_E2 )
			{
				Resp = ACCESS_E2_ERR ;
			}
		}
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		*( LenData_E2 ) = 0 ;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_WriteE2
* Description   : Write data into BC45 EEPROM
* Input         : 
*				  - StartAddr 	   : First address that write into EEPROM
*				  - Data_E2 	   : Data write to EEPROM
*				  - LenData_Wr_E2 : Length of Data write to EEPROM  
* Output        : None
* Return        : 
*				  - Status
* 				    	- _SUCCESS_
*						- WRITE_E2_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_WriteE2( uint8_t StartAddr, uint8_t *Data_E2, uint16_t LenData_Wr_E2 )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;
	
	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;

	// Write Start Address
	BC45_WriteFIFO( &StartAddr, 1 ) ; 
	
	// Write E2
	Resp = BC45_IRQ_Execute_FIFO_Data( CMDWriteE2, Data_E2, LenData_Wr_E2, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;  

	if ( Resp == _SUCCESS_ )  
	{
		Resp = BC45_Check_E2Err() ;
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_LoadE2Config
* Description   : Load 32 Bytes Data from BC45 EEPROM to Register page (0x10 to 0x2F)
* Input         : 
*				  - Start_Addr : First Key Addr in EEPROM  
* Output        : None
* Return        : 
*				  - Status
* 				    	- _SUCCESS_
* 				    	- KEY_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_LoadE2Config( uint8_t Star_Addr )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;
	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;

	Resp = BC45_IRQ_Execute_FIFO_Data( CMDLoadConfig, &Star_Addr, 1, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;  

	if ( Resp == _SUCCESS_ )  
	{
		Resp = BC45_Check_E2Err() ;
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		;
	}
    
	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_LoadKey
* Description   : Load Key 12 Bytes to Master Key Buffer
* Input         : 
*				  - Key    : Key  
*				  - LenKey : Must be 12 Bytes  
* Output        : None
* Return        : 
*				  - Status
* 				    	- _SUCCESS_
* 				    	- KEY_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_LoadKey( uint8_t *Key, uint8_t LenKey )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;
	
	Resp = BC45_IRQ_Execute_FIFO_Data( CMDLoadKey, Key, LenKey, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;  

	if ( Resp == _SUCCESS_ )  
	{
		Resp = BC45_Check_KeyErr() ;
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_LoadKeyE2
* Description   : Load 12 Bytes Key from BC45 EEPROM to Master Key Buffer
* Input         : 
*				  - Start_Addr : First Key Addr in EEPROM  
* Output        : None
* Return        : 
*				  - Status
* 				    	- _SUCCESS_
* 				    	- KEY_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_LoadKeyE2( uint8_t Star_Addr )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;
	
	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;

	Resp = BC45_IRQ_Execute_FIFO_Data( CMDLoadKeyE2, &Star_Addr, 1, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;  

	if ( Resp == _SUCCESS_ )  
	{
		Resp = BC45_Check_KeyErr() ;
	}
	else
	{	// Time-out Timer BC45, Time out MCU
		;
	}

	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_Cal_CRC
* Description   : Calculate the CRC calculation result following input data
* Input         : 
*				  - Data_Cal      
*				  - LenData_Cal
* Output        : 
*				  - CRC_Result	  : The first byte is CRC_ResultMSB
*				  - LenCRC_Result : 2 Bytes
* Return        : 
*				  - Status
* 				    	- _SUCCESS_
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Cal_CRC( uint8_t *Data_Cal, uint16_t LenData_Cal, uint8_t *CRC_Result, uint16_t *LenCRC_Result )
{
	uint8_t   Resp ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;
	
	BC45_Timer_Tstart_Tstop_Control( TimerManual, TimerManual ) ;

	Resp = BC45_IRQ_Execute_FIFO_Data( CMDCalCRC, Data_Cal, LenData_Cal, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;  
	if ( Resp == _SUCCESS_ )
	{
		htk_SPI_readSingleRegister(CRCResultMSB, &Data_Rd[CRCResultMSB]);
		htk_SPI_readSingleRegister(CRCResultLSB, &Data_Rd[CRCResultLSB]);
		
		*( CRC_Result )     = Data_Rd[CRCResultMSB] ;		
		*( CRC_Result + 1 ) = Data_Rd[CRCResultLSB] ;	
		*( LenCRC_Result )  = 2 ;
	}
	
	return Resp ;
}

/*******************************************************************************
* Function Name : BC45_Authent
* Description   : Execute the Mifare Authentication Routine
* Input         : 
*				  - Data_Authent    : Selected_Key( 1 Byte ) + Block_Num( 1 Byte ) + UID( 4 Bytes )
*						- Select_Key
*							- 0x60 : Used Key A
*							- 0x61 : Used Key B				
*				  - LenData_Authent : Length of Data_Authent ( Should be 6 Bytes )
* Output        : None
* Return        : 
*				  - Status
* 				    	- _SUCCESS_
*						- NO_RESPONSE
*						- AUTHENT_ERR								 
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Authent( uint8_t *Data_Authent, uint8_t LenData_Authent )
{
	uint8_t   Resp ;
	uint8_t   tmp_Data_Rx[64] ;
	uint16_t  tmp_LenData_Rx = 0 ;
	
	BC45_Disable_And_ClearFlag_IRQ( ALL_IRQ_SOURCE ) ;
	BC45_Flush_FIFO() ;

	BC45_Timer_Tstart_Tstop_Control( TStartTxEnd, TStopRxBegin ) ;

	//----------- Transmit ----------------//
	Resp = BC45_IRQ_Execute_FIFO_Data( CMDAuthent, Data_Authent, LenData_Authent, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val ) ;
	if ( Resp == _SUCCESS_ )  
	{
		//------------------- Recieve -------------------//
		Resp = BC45_IRQ_Read_FIFO( tmp_Data_Rx, &tmp_LenData_Rx, BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val , 0) ;
		if ( Resp == _SUCCESS_ )  
		{
			Resp = BC45_Check_RFErr() ;
			if ( Resp == _SUCCESS_ )
			{	// Check Cypto Bit 
				Resp = BC45_Check_Crypto_Bit() ;
				if ( Resp == CRYPTO_NOT_ON )
				{
					Resp = AUTHENT_ERR ;
				}
			}
		}
	}
	
	return Resp ;
}

/*******************************************************************************
* Function Name : Transparent_With_CRC
* Description   : Transmit data with appending calculated CRC bytes and receive response data with CRC checking
*				  No CRC is shown in response Data_Resp if recieved CRC is correct (CRC_ERR).
* Input         : 
*				  - Data_Tx    : Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Resp    : Response Data 
*				  - LenData_Resp : Length of Response Data
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Transparent_With_CRC( uint8_t *Data_Tx, uint16_t LenData_Tx, uint8_t TimeOut, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t   Resp ;
  
	Resp = Transparent_Configure_CRC ( 1, 1 , Data_Tx , LenData_Tx, TimeOut , Data_Resp, LenData_Resp );

	return Resp ;	
}



/*******************************************************************************
* Function Name : Transparent_Without_CRC
* Description   : Transmit data without appending calculated CRC bytes and receive response data
* Input         : 
*                                 - Data_Tx 	: Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Resp    : Response Data 
*				  - LenData_Resp : Length of Response Data
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Transparent_Without_CRC( uint8_t *Data_Tx, uint16_t LenData_Tx, uint8_t TimeOut, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t   Resp ;
  
	Resp = Transparent_Configure_CRC ( 0, 0 , Data_Tx , LenData_Tx, TimeOut , Data_Resp, LenData_Resp );

	return Resp ;		
}

/*******************************************************************************
* Function Name : Transparent_Configure_CRC
* Description   : Transmit data and receive response data with CRC Enable Configuration
* Input         : 
*				  - TxCRCEn     : TxCRC Enable
*                                 - RxCRCEn     : RxCRC Enable
*                                 - Data_Tx 	: Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Resp    : Response Data 
*				  - LenData_Resp : Length of Response Data
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Transparent_Configure_CRC( uint8_t TxCRCEn, uint8_t RxCRCEn ,uint8_t *Data_Tx, uint16_t LenData_Tx, uint8_t TimeOut, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t   Resp ;

	// Back Up TPreScaler and TReloadValue 
	htk_SPI_readSingleRegister(TimerClock , &Data_Rd[TimerClock]);
	htk_SPI_readSingleRegister(TimerReload , &Data_Rd[TimerReload]);

	BC45_Timer_Set_Resp_Waiting_Time( TimeOut ) ;

	BC45_CRC_Setting( TxCRCEn, RxCRCEn ) ;

	Resp = BC45_Transceive( Data_Tx, LenData_Tx, Data_Resp, LenData_Resp ) ;		

	// Load Back up Value
	htk_SPI_writeSingleRegister(TimerClock , Data_Rd[TimerClock]);
	htk_SPI_writeSingleRegister(TimerReload , Data_Rd[TimerReload]);

	return Resp ;	
}

/*******************************************************************************
* Function Name : Transparent_NFC_Type1_With_CRC
* Description   : Transmit data with appending calculated CRC bytes and receive response data with CRC checking following NFC type1
* Input         : 
*				  - Data_Tx 	: Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Resp    : Response Data 
*				  - LenData_Resp : Length of Response Data
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Transparent_NFC_Type1_With_CRC( uint8_t *Data_Tx, uint16_t LenData_Tx, uint8_t TimeOut, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
        uint8_t   Resp ;
  
	Resp = Transparent_NFC_Type1_Config_CRC ( 1, 1 , Data_Tx , LenData_Tx, TimeOut , Data_Resp, LenData_Resp );
          
        return Resp ;
}


/*******************************************************************************
* Function Name : Transparent_NFC_Type1_Without_CRC
* Description   : Transmit data without appending calculated CRC bytes and receive response data following NFC type1
* Input         : 
*				  - Data_Tx 	: Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Resp    : Response Data 
*				  - LenData_Resp : Length of Response Data
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Transparent_NFC_Type1_Without_CRC( uint8_t *Data_Tx, uint16_t LenData_Tx, uint8_t TimeOut, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
        uint8_t   Resp ;
  
	Resp = Transparent_NFC_Type1_Config_CRC ( 0, 0 , Data_Tx , LenData_Tx, TimeOut , Data_Resp, LenData_Resp );
          
        return Resp ;
}
/*******************************************************************************
* Function Name : Transparent_NFC_Type1_Config_CRC
* Description   : Transmit data and receive response data with CRC Enable Configuration following NFC type1
* Input         : 
*				  - Data_Tx 	: Transmitted Data
*				  - LenData_Tx : Length of Transmitted Data  
* Output        : 
*				  - Data_Resp    : Response Data 
*				  - LenData_Resp : Length of Response Data
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Transparent_NFC_Type1_Config_CRC( uint8_t TxCRCEn, uint8_t RxCRCEn, uint8_t *Data_Tx, uint16_t LenData_Tx, uint8_t TimeOut, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t   Resp ;
    uint8_t   Data_Tx_Temp, Data_CRC[2] ;
    uint16_t  count, LenCRC;
    uint16_t  LenTx ;

	// Back Up TPreScaler and TReloadValue
    htk_SPI_readSingleRegister(TimerClock , &Data_Rd[TimerClock]);
    htk_SPI_readSingleRegister(TimerReload, &Data_Rd[TimerReload]);

    htk_SPI_readSingleRegister(CRCSetting , &Data_Rd[CRCSetting]);
    htk_SPI_readSingleRegister(CRCPresetLSB, &Data_Rd[CRCPresetLSB]);
    htk_SPI_readSingleRegister(CRCPresetMSB, &Data_Rd[CRCPresetMSB]);

	BC45_Timer_Set_Resp_Waiting_Time( TimeOut ) ;

    Data_Tx_Temp = 0x22;
    htk_SPI_writeSingleRegister(CRCSetting   , Data_Tx_Temp); // Disable Parity at Tx

    Data_Tx_Temp = 0xFF;
    htk_SPI_writeSingleRegister(CRCPresetLSB   , Data_Tx_Temp); // Config CRCInit

    Data_Tx_Temp = 0xFF;
    htk_SPI_writeSingleRegister(CRCPresetMSB   , Data_Tx_Temp); // Config CRCInit
       
    if ( TxCRCEn == 0 )
    {
    	LenTx = LenData_Tx ;
    }
    else
    {
        Resp  = BC45_Cal_CRC( Data_Tx, LenData_Tx, &Data_CRC[0], &LenCRC );
        LenTx = LenData_Tx + 2;
    }
        
        
    for (count = 0; count < LenTx  ; count++)
    {
    	if (count == 0)
        {   
    		Data_Tx_Temp = 0x07;
    		htk_SPI_writeSingleRegister(BitFramingReg , Data_Tx_Temp); // Set TxLastBit = 7
            Resp = BC45_Transmit( Data_Tx + count , 1 ); // Deliver CMD only 7 bit
        }
        else
        {
        	if (Resp == _SUCCESS_)
            {
        		if ( TxCRCEn == 0 )
                {
        			if (count < LenTx - 1)
                    {
        				Resp = BC45_Transmit( Data_Tx + count , 1 ); // Deliver Data
                    }
                    else
                    {
                    	Resp = BC45_Transceive_NFC_Type1( Data_Tx + count , 1, Data_Resp, LenData_Resp, RxCRCEn ) ; // Deliver Last Byte with Transceive CMD
                    }
                }
                else
                {
                    if (count < LenTx - 2 )
                    {
                    	Resp = BC45_Transmit( Data_Tx + count , 1 );
                    }
                    else if (count < LenTx - 1) // Deliver CRC MSB
                    {
                    	Resp = BC45_Transmit( Data_CRC + 1 , 1 );
                    }
                    else
                    {
                    	Resp = BC45_Transceive_NFC_Type1( Data_CRC  , 1, Data_Resp, LenData_Resp , RxCRCEn) ; // Deliver Last Byte with Transceive CMD
                    }
                }
                    
            }
        }
    }
	          
	// Load Back up Value
    htk_SPI_writeSingleRegister(TimerClock , Data_Rd[TimerClock]);
    htk_SPI_writeSingleRegister(TimerReload , Data_Rd[TimerReload]);
 	
	return Resp ;	
}



/*******************************************************************************
* Function Name : Transparent_With_RxMultiple
* Description   : Transmit data and receive response data with CRC Enable Configuration
* Input         : 
*                                 - Data_Tx 	  : Transmitted Data
*				  - LenData_Tx    : Length of Transmitted Data  
* Output        : 
*				  - Data_Resp    : Response Data 
*				  - LenData_Resp : Length of Response Data
* Return        : 
*				  - Status
*						- _SUCCESS_
*						- NO_RESPONSE
*						- FRAMING_ERR 
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- BUFFER_OVERFLOW_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Transparent_With_RxMultiple( uint8_t *Data_Tx, uint16_t LenData_Tx, uint8_t TimeOut, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t   Resp , Data_Temp;

	// Back Up TPreScaler and TReloadValue
    htk_SPI_readSingleRegister(TimerClock , &Data_Rd[TimerClock]);
    htk_SPI_readSingleRegister(TimerReload, &Data_Rd[TimerReload]);
    htk_SPI_readSingleRegister(DecoderControl , &Data_Temp);
	
    BC45_Timer_Set_Resp_Waiting_Time( TimeOut ) ;

	Resp = BC45_Transceive_With_RxMultiple ( Data_Tx, LenData_Tx, Data_Resp, LenData_Resp ) ;
        
	// Load Back up Value
	htk_SPI_writeSingleRegister(DecoderControl, Data_Temp);
	htk_SPI_writeSingleRegister(TimerClock, Data_Rd[TimerClock]);
	htk_SPI_writeSingleRegister(TimerReload, Data_Rd[TimerReload]);

	return Resp ;	
}

/*******************************************************************************
* Function Name : BC45_Config_Driver
* Description   : Configure Transmitter Control Register (0x11) of BC45 following driving network type
* Input         : 
*				  - Driver_Config_Type : 
*						- DRIVER_CONFIG_X_CC     : Diffential Close Coupling Network with internal envelope
*						- DRIVER_CONFIG_X_CCXENV : Diffential Close Coupling Network with external envelope
*						- DRIVER_CONFIG_X_S50OUT : Single-ended Drive with external envelope
*						- DRIVER_CONFIG_X_E50OUT : 50 ohm output from Class-E driver with external envelope 
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Config_Driver( uint8_t  Driver_Config_Type )	 
{
	htk_SPI_readSingleRegister( RxControl2, &Data_Rd[RxControl2]);
	if ( Driver_Config_Type == DRIVER_CONFIG_X_CCXENV ) 
	{
		Data_Wr[TxControl] = 0x58 ;	
		Data_Wr[RxControl2] = Data_Rd[RxControl2] | 0x04 ; // Set bit 2  		
	}
	else if ( Driver_Config_Type == DRIVER_CONFIG_X_S50OUT ) 
	{
		Data_Wr[TxControl] = 0x50 ;	
		Data_Wr[RxControl2] = Data_Rd[RxControl2] | 0x04 ; // Set bit 2  		
	}
	else if ( Driver_Config_Type == DRIVER_CONFIG_X_E50OUT ) 
	{
		Data_Wr[TxControl] = 0x00 ;	
		Data_Wr[RxControl2] = Data_Rd[RxControl2] | 0x04 ; // Set bit 2  		
	}
	else //  X_CC
	{
		Data_Wr[TxControl] = 0x58 ;			
		Data_Wr[RxControl2] = Data_Rd[RxControl2] & 0xFB ; // Clear bit 2  		
	}

	htk_SPI_writeSingleRegister(TxControl, Data_Wr[TxControl]);
	htk_SPI_writeSingleRegister(RxControl2, Data_Wr[RxControl2]);
}

/*******************************************************************************
* Function Name : BC45_InitChip
* Description   : Initialze Transmitter Control Register of BC45
* Input         : 
*				  - Driver_Config_Type : 
*						- DRIVER_CONFIG_X_CC     : Diffential Close Coupling Network with internal envelope
*						- DRIVER_CONFIG_X_CCXENV : Diffential Close Coupling Network with external envelope
*						- DRIVER_CONFIG_X_S50OUT : Single-ended Drive with external envelope
*						- DRIVER_CONFIG_X_E50OUT : 50 ohm output from Class-E driver with external envelope 
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_InitChip( uint8_t  Driver_Config_Type )	 
{	
	uint8_t page;

  BC45_Config_Driver(Driver_Config_Type);	//antenna type
  Data_Wr[ModConductance] = Param_14443B_106.GsCfgMod;	
	// Write to BC45 register
  htk_SPI_writeSingleRegister(ModConductance, Data_Wr[ModConductance]);

	//test
  Data_Wr[RxControl2]  = 0x41;
	//Data_Wr[RxControl2]  = 0x43;
  Data_Wr[RxControl3]  = Param_14443A_106.RxControl_3;	
  Data_Wr[RxThreshold] = Param_14443A_106.Rx_Threshold;	
	// Write to BC45 register
  htk_SPI_writeSingleRegister(RxThreshold, Data_Wr[RxThreshold]);
  htk_SPI_writeSingleRegister(RxControl2, Data_Wr[RxControl2]);
  htk_SPI_writeSingleRegister(RxControl3, Data_Wr[RxControl3]); // Availble for BC45B4523

	//low/high pass filter
  Data_Wr[ManFilterCtrl] = 0x19;	//Reg 0x2E
  Data_Wr[FilterCorCoef] = 0x45;	//Reg 0x2F
  
	// Write to register

  /* Select Page 1 for BC45 */
  page = 0x01;
  htk_SPI_writeSingleRegister(0x00, page);
  /**************************/
  htk_SPI_writeSingleRegister(ManFilterCtrl, Data_Wr[ManFilterCtrl]);
  htk_SPI_writeSingleRegister(FilterCorCoef, Data_Wr[FilterCorCoef]);

  /* Back to Page 0 for BC45*/
  page = 0x00;
  htk_SPI_writeSingleRegister(0x00, page);
  /**********************/
        
  Data_Wr[FIFOLevel]      = WaterLevel; // FIFO Level
	Data_Wr[IOConfig]       = 0x00;	      // Not inv irq
	Data_Wr[TestAnaSel]     = 0x2E;
	Data_Wr[GainST3]  			= Param_14443A_106.Gain_ST3;	
	Data_Wr[Rx43AOption]  	= Param_14443A_106.Rx43A_Option;

// Write to HTK register
	htk_SPI_writeSingleRegister(FIFOLevel, 	Data_Wr[FIFOLevel]);
	htk_SPI_writeSingleRegister(IOConfig, 	Data_Wr[IOConfig]);
	htk_SPI_writeSingleRegister(TestAnaSel, Data_Wr[TestAnaSel]);
	htk_SPI_writeSingleRegister(GainST3, 		Data_Wr[GainST3]);

        
	BC45_Disable_And_ClearFlag_IRQ(ALL_IRQ_SOURCE);	

}


/*******************************************************************************
* Function Name : BC45_Config_14443A
* Description   : Configure Registers for ISO14443A Standard Operation
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Config_14443A( void )
{	
	uint8_t dataReg;

	//BC45 Rev B configuration for iso14443A 106 kbps==========================
	Data_Wr[TxControl] 				= 0x5B;
	Data_Wr[CWConductance]		= 0x3F;
	Data_Wr[ModConductance]		= 0x10;
	Data_Wr[CoderControl]			= 0x19;
	Data_Wr[ModWidth]					= 0x0F;
	Data_Wr[ModWidthSOF]			= 0x0F;
	Data_Wr[TypeBFraming]			= 0x3B;

	Data_Wr[RxControl1]				= 0x6B;
	Data_Wr[DecoderControl]		= 0x28;
	Data_Wr[Bitphase]					= 0x3D;
	Data_Wr[RxThreshold]			= 0x6C;//0xAA;
	Data_Wr[BPSKDemod]				= 0x02;
	//test
	Data_Wr[RxControl2]				= 0x41;
	//Data_Wr[RxControl2]				= 0x43;
	Data_Wr[RxControl3]				= 0xC3;//0xE3;//0xE0;

	//Data_Wr[RxWait]						= 0x04;
	Data_Wr[RxWait]						= 0x07;
	Data_Wr[CRCSetting]				= 0x03;
	Data_Wr[CRCPresetLSB]			= 0x63;
	Data_Wr[CRCPresetMSB]			= 0x63;

	Data_Wr[FIFOLevel]				= 0x10;
	Data_Wr[TimerClock]				= 0x0A;
	Data_Wr[TimerControl]			= 0x06;
	Data_Wr[TimerReload]			= 0xFF;
	Data_Wr[ManFilterCtrl]		= 0x19;
	Data_Wr[FilterCorCoef]		= 0x45;

	Data_Wr[IOConfig]					= 0x00;
	Data_Wr[TestAnaSel]				= 0x2E;
	
	Data_Wr[Rx43AOption]			= 0x28;//0x88;//0x80;
	Data_Wr[GainST3]					= 0x02;

	//Select register sector 0
	htk_SPI_writeSingleRegister(PageReg, 0x00);
	htk_SPI_writeSingleRegister(TxControl,  Data_Wr[TxControl]);
	htk_SPI_writeSingleRegister(CWConductance,  Data_Wr[CWConductance]);
	htk_SPI_writeSingleRegister(ModConductance, Data_Wr[ModConductance]);
	htk_SPI_writeSingleRegister(CoderControl,  Data_Wr[CoderControl]);
	htk_SPI_writeSingleRegister(ModWidth,  Data_Wr[ModWidth]);
	htk_SPI_writeSingleRegister(ModWidthSOF, Data_Wr[ModWidthSOF]);
	htk_SPI_writeSingleRegister(TypeBFraming,  Data_Wr[TypeBFraming]);

	htk_SPI_writeSingleRegister(RxControl1,  Data_Wr[RxControl1]);
	htk_SPI_writeSingleRegister(DecoderControl,  Data_Wr[DecoderControl]);
	htk_SPI_writeSingleRegister(Bitphase, Data_Wr[Bitphase]);
	htk_SPI_writeSingleRegister(RxThreshold,  Data_Wr[RxThreshold]);
	htk_SPI_writeSingleRegister(BPSKDemod,  Data_Wr[BPSKDemod]);
	htk_SPI_writeSingleRegister(RxControl2, Data_Wr[RxControl2]);
	htk_SPI_writeSingleRegister(RxControl3,  Data_Wr[RxControl3]);

	htk_SPI_writeSingleRegister(RxWait,  Data_Wr[RxWait]);
	htk_SPI_writeSingleRegister(CRCSetting,  Data_Wr[CRCSetting]);
	htk_SPI_writeSingleRegister(CRCPresetLSB, Data_Wr[CRCPresetLSB]);
	htk_SPI_writeSingleRegister(CRCPresetMSB,  Data_Wr[CRCPresetMSB]);

	htk_SPI_writeSingleRegister(FIFOLevel,  Data_Wr[FIFOLevel]);
	htk_SPI_writeSingleRegister(TimerClock,  Data_Wr[TimerClock]);
	htk_SPI_writeSingleRegister(TimerControl, Data_Wr[TimerControl]);
	htk_SPI_writeSingleRegister(TimerReload,  Data_Wr[TimerReload]);

	//crystal,39, 3a
	htk_SPI_writeSingleRegister(0x39, 0x10);
	htk_SPI_writeSingleRegister(0x3a, 0x00);

	//Select register sector 1
	htk_SPI_writeSingleRegister(PageReg,  0x01);
	htk_SPI_readSingleRegister(0x0F, &dataReg);
	//Check BC45 Revision
	if(dataReg == BC45_RevB)
	{
		htk_SPI_writeSingleRegister(0x05, 0x05);
	}
	else
	{
		htk_SPI_writeSingleRegister(0x05, 0x00);
	}
	//crystal
	//htk_SPI_writeSingleRegister(0x11, 0x02);
	//htk_SPI_writeSingleRegister(0x13, 0x30);
	htk_SPI_writeSingleRegister(0x11, 0x03);
	htk_SPI_writeSingleRegister(0x13, 0x12);
	
	//2e
	htk_SPI_writeSingleRegister(ManFilterCtrl, Data_Wr[ManFilterCtrl]);
	//2f
	htk_SPI_writeSingleRegister(FilterCorCoef, Data_Wr[FilterCorCoef]);

	//Select register sector 0
	htk_SPI_writeSingleRegister(PageReg,  		0x00);
	htk_SPI_writeSingleRegister(IOConfig,  		Data_Wr[IOConfig]);
	htk_SPI_writeSingleRegister(Rx43AOption,  Data_Wr[Rx43AOption]);
  htk_SPI_writeSingleRegister(GainST3,  		Data_Wr[GainST3]);
}

/*******************************************************************************
* Function Name : BC45_Speed_14443A
* Description   : Configure Registers Related to RF-Communication Bit Rate following ISO14443A Standard
* Input         : 
*				  - SPD_SEL : Speed selection
*						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        : None
*******************************************************************************/
void BC45_Speed_14443A( uint8_t SPD_SEL )
{	
	uint8_t  Tx_Speed, Rx_Speed;
	
	Tx_Speed = (SPD_SEL >> 4);
	Rx_Speed = (SPD_SEL & 0x0F); 
	
	if(Tx_Speed == SPEED_212_KBPS)  // Tx 212 kbps
	{	
		Data_Wr[CoderControl] = 0x11;	// Set Tx Coding
		Data_Wr[ModWidth]     = 0x07;	// Set ModWidth
		Data_Wr[ModWidthSOF]  = 0x07;	// Set ModWidthSOF
	}
	else if(Tx_Speed == SPEED_424_KBPS) // Tx 424 kbps
	{	
		Data_Wr[CoderControl] = 0x09;	// Set Tx Coding
		Data_Wr[ModWidth]     = 0x02;	// Set ModWidth
		Data_Wr[ModWidthSOF]  = 0x02;	// Set ModWidthSOF
	}
	else if(Tx_Speed == SPEED_848_KBPS) // Tx 848 kbps
	{	
		Data_Wr[CoderControl] = 0x01;	// Set Tx Coding
		Data_Wr[ModWidth]     = 0x01;	// Set ModWidth
		Data_Wr[ModWidthSOF]  = 0x01;	// Set ModWidthSOF
	}
	else  // Tx 106 kbps
	{	
		Data_Wr[CoderControl] = 0x19;	// Set Tx Coding
		Data_Wr[ModWidth]     = 0x0F;	// Set ModWidth
		Data_Wr[ModWidthSOF]  = 0x0F;	// Set ModWidthSOF
	}
	// Write to HTK register
	htk_SPI_writeSingleRegister(CoderControl, Data_Wr[CoderControl]);
	htk_SPI_writeSingleRegister(ModWidth,     Data_Wr[ModWidth]);
	htk_SPI_writeSingleRegister(ModWidthSOF,  Data_Wr[ModWidthSOF]);
	
	htk_SPI_readSingleRegister(RxControl1,    &Data_Rd[RxControl1]);
	
	if(Rx_Speed == SPEED_212_KBPS) // Rx 212 kbps
	{	
		Data_Wr[RxControl1]     = 0x48 | (Data_Rd[RxControl1] & 0x07);	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x29;	// Set Rx-Framing and Zero after coll
		Data_Wr[Bitphase]       = Param_14443A_212.BitPhase; //0x32;	// Set Bitphase
		Data_Wr[RxThreshold]    = Param_14443A_212.Rx_Threshold;
		Data_Wr[BPSKDemod]      = Param_14443A_212.BPSK_Demod;
		Data_Wr[RxControl3]     = Param_14443A_212.RxControl_3;
		Data_Wr[GainST3]        = Param_14443A_212.Gain_ST3;
		Data_Wr[Rx43AOption]  	= Param_14443A_212.Rx43A_Option;
	}
	else if(Rx_Speed == SPEED_424_KBPS) // Rx 424 kbps
	{	
		Data_Wr[RxControl1]     = 0x28 | (Data_Rd[RxControl1] & 0x07);	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x29;	// Set Rx-Framing and Zero after coll
		Data_Wr[Bitphase]       = Param_14443A_424.BitPhase;	// Set Bitphase
		Data_Wr[RxThreshold]    = Param_14443A_424.Rx_Threshold;
		Data_Wr[BPSKDemod]      = Param_14443A_424.BPSK_Demod;
		Data_Wr[RxControl3]     = Param_14443A_424.RxControl_3;
		Data_Wr[GainST3]        = Param_14443A_424.Gain_ST3;
		Data_Wr[Rx43AOption]  	= Param_14443A_424.Rx43A_Option;
	}
	else if(Rx_Speed == SPEED_848_KBPS) // Rx 848 kbps
	{	
		Data_Wr[RxControl1]     = 0x08 | (Data_Rd[RxControl1] & 0x07); // Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x29;	// Set Rx-Framing and Zero after coll
		Data_Wr[Bitphase]       = Param_14443A_848.BitPhase; // Set Bitphase
		Data_Wr[RxThreshold]    = Param_14443A_848.Rx_Threshold;
		Data_Wr[BPSKDemod]      = Param_14443A_848.BPSK_Demod;
		Data_Wr[RxControl3]     = Param_14443A_848.RxControl_3;
		Data_Wr[GainST3]  		  = Param_14443A_848.Gain_ST3;
		Data_Wr[Rx43AOption]  	= Param_14443A_848.Rx43A_Option;
	}
	else  // Rx 106 kbps
	{	
		Data_Wr[RxControl1]     = 0x68 | (Data_Rd[RxControl1] & 0x07);	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x28;	// Set Rx-Framing and Zero after coll
		Data_Wr[BPSKDemod]      = Param_14443A_106.BPSK_Demod;
		Data_Wr[RxThreshold]    = Param_14443A_106.Rx_Threshold;
		Data_Wr[RxControl3]     = Param_14443A_106.RxControl_3;
		Data_Wr[GainST3]        = Param_14443A_106.Gain_ST3;
		Data_Wr[Rx43AOption]  	= Param_14443A_106.Rx43A_Option;
                
		if(Tx_Speed == SPEED_212_KBPS)    // Tx 212 kbps
		{	
			Data_Wr[Bitphase] = Param_14443A_212.BitPhase;
		}		
		else if(Tx_Speed == SPEED_424_KBPS) // Tx 424 kbps
		{	
			Data_Wr[Bitphase] = Param_14443A_424.BitPhase;
		}		
		else if(Tx_Speed == SPEED_848_KBPS) // Tx 848 kbps
		{	
			Data_Wr[Bitphase] = Param_14443A_848.BitPhase;
		}		
		else  // Tx 106 kbps
		{	
			Data_Wr[Bitphase] = 0x40; // Set Bitphase , change from 0x44
			Data_Wr[Bitphase] = Param_14443A_106.BitPhase;
		}
	}
	// Write to HTK register
	htk_SPI_writeSingleRegister(RxControl1, 	Data_Wr[RxControl1]);
	htk_SPI_writeSingleRegister(DecoderControl, Data_Wr[DecoderControl]);
	htk_SPI_writeSingleRegister(Bitphase, 		Data_Wr[Bitphase]);
	htk_SPI_writeSingleRegister(BPSKDemod, 		Data_Wr[BPSKDemod]);
	htk_SPI_writeSingleRegister(RxControl3, 	Data_Wr[RxControl3]);
	htk_SPI_writeSingleRegister(RxThreshold, 	Data_Wr[RxThreshold]);
//	htk_SPI_writeSingleRegister(GainST3, 	Data_Wr[GainST3]);
//	htk_SPI_writeSingleRegister(AnalogAdjust3, 	Data_Wr[AnalogAdjust3]);
}

/*******************************************************************************
* Function Name : BC45_Config_14443B
* Description   : Configure Registers for ISO14443B Standard Operation
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Config_14443B( void )
{	
	uint8_t dataReg;

	//BC45 Rev B configuration for iso14443B 106 kbps==========================
	Data_Wr[TxControl] 				= 0x4B;
	Data_Wr[CWConductance]		= 0x3F;

	//Data_Wr[ModConductance]	= 0x10;
	//crystal
	Data_Wr[ModConductance]		= 0x17;

	Data_Wr[CoderControl]			= 0x20;
	Data_Wr[ModWidth]					= 0x3F;
	Data_Wr[ModWidthSOF]			= 0x3F;

	//Data_Wr[TypeBFraming]		= 0x0D;
	//crystal
	Data_Wr[TypeBFraming]			= 0x01;

	Data_Wr[RxControl1]				= 0x6B;
	Data_Wr[DecoderControl]		= 0x19;
	Data_Wr[Bitphase]					= 0x54;
	Data_Wr[RxThreshold]			= 0x88;
	Data_Wr[BPSKDemod]				= 0x02;
	Data_Wr[RxControl2]				= 0x41;
	Data_Wr[RxControl3]				= 0xC3;//0xE3;//0xE1;

	Data_Wr[RxWait]						= 0x03;
	Data_Wr[CRCSetting]				= 0x2E;
	Data_Wr[CRCPresetLSB]			= 0xFF;
	Data_Wr[CRCPresetMSB]			= 0xFF;

	Data_Wr[FIFOLevel]				= 0x10;
	Data_Wr[TimerClock]				= 0x0A;
	Data_Wr[TimerControl]			= 0x06;
	Data_Wr[TimerReload]			= 0xFF;
	Data_Wr[ManFilterCtrl]		= 0x19;
	Data_Wr[FilterCorCoef]		= 0x45;

	Data_Wr[IOConfig]					= 0x00;
	Data_Wr[Rx43AOption]			= 0x28;//0x88;//0x80;
	Data_Wr[GainST3]					= 0x02;

	//Select register sector 0
	htk_SPI_writeSingleRegister(PageReg, 0x00);
	htk_SPI_writeSingleRegister(TxControl,  Data_Wr[TxControl]);
	htk_SPI_writeSingleRegister(CWConductance,  Data_Wr[CWConductance]);
	htk_SPI_writeSingleRegister(ModConductance, Data_Wr[ModConductance]);
	htk_SPI_writeSingleRegister(CoderControl,  Data_Wr[CoderControl]);
	htk_SPI_writeSingleRegister(ModWidth,  Data_Wr[ModWidth]);
	htk_SPI_writeSingleRegister(ModWidthSOF, Data_Wr[ModWidthSOF]);
	htk_SPI_writeSingleRegister(TypeBFraming,  Data_Wr[TypeBFraming]);

	htk_SPI_writeSingleRegister(RxControl1,  Data_Wr[RxControl1]);
	htk_SPI_writeSingleRegister(DecoderControl,  Data_Wr[DecoderControl]);
	htk_SPI_writeSingleRegister(Bitphase, Data_Wr[Bitphase]);
	htk_SPI_writeSingleRegister(RxThreshold,  Data_Wr[RxThreshold]);
	htk_SPI_writeSingleRegister(BPSKDemod,  Data_Wr[BPSKDemod]);
	htk_SPI_writeSingleRegister(RxControl2, Data_Wr[RxControl2]);
	htk_SPI_writeSingleRegister(RxControl3,  Data_Wr[RxControl3]);

	htk_SPI_writeSingleRegister(RxWait,  Data_Wr[RxWait]);
	htk_SPI_writeSingleRegister(CRCSetting,  Data_Wr[CRCSetting]);
	htk_SPI_writeSingleRegister(CRCPresetLSB, Data_Wr[CRCPresetLSB]);
	htk_SPI_writeSingleRegister(CRCPresetMSB,  Data_Wr[CRCPresetMSB]);

	htk_SPI_writeSingleRegister(FIFOLevel,  Data_Wr[FIFOLevel]);
	htk_SPI_writeSingleRegister(TimerClock,  Data_Wr[TimerClock]);
	htk_SPI_writeSingleRegister(TimerControl, Data_Wr[TimerControl]);
	htk_SPI_writeSingleRegister(TimerReload,  Data_Wr[TimerReload]);

	//crystal,39, 3a
	htk_SPI_writeSingleRegister(0x39, 0x06);
	htk_SPI_writeSingleRegister(0x3a, 0x00);

	//Select register sector 1
	htk_SPI_writeSingleRegister(PageReg,  0x01);
	htk_SPI_readSingleRegister(0x0F, &dataReg);
	//Check BC45 Revision
	if(dataReg == BC45_RevB)
	{
		htk_SPI_writeSingleRegister(0x05, 0x05);
	}
	else
	{
		htk_SPI_writeSingleRegister(0x05, 0x00);
	}
	//crystal
	htk_SPI_writeSingleRegister(0x11, 0x02);
	htk_SPI_writeSingleRegister(0x13, 0x27);
	//2e
	htk_SPI_writeSingleRegister(ManFilterCtrl,  Data_Wr[ManFilterCtrl]);
	//2f
	htk_SPI_writeSingleRegister(FilterCorCoef, Data_Wr[FilterCorCoef]);
		
	//Select register sector 0
	htk_SPI_writeSingleRegister(PageReg,  		0x00);
	htk_SPI_writeSingleRegister(IOConfig,  		Data_Wr[IOConfig]);
	htk_SPI_writeSingleRegister(Rx43AOption,  Data_Wr[Rx43AOption]);
	htk_SPI_writeSingleRegister(GainST3,  		Data_Wr[GainST3]);
}

/*******************************************************************************
* Function Name : BC45_Speed_14443B
* Description   : Configure Registers Related to RF-Communication Bit Rate following ISO14443B Standard
* Input         : 
*				  - SPD_SEL : Speed selection
*						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        : None
*******************************************************************************/
void BC45_Speed_14443B( uint8_t SPD_SEL )
{	
	uint8_t  Tx_Speed, Rx_Speed ;
	
	Tx_Speed = ( SPD_SEL >> 4 ) ;
	Rx_Speed = ( SPD_SEL & 0x0F ) ; 

	if ( Tx_Speed == SPEED_212_KBPS ) // Tx 212 kbps
	{	
		Data_Wr[CoderControl] = 0x18 ; // Set Tx Coding
		Data_Wr[ModWidth]     = 0x1F ; // ModWidth	 
		Data_Wr[ModWidthSOF]  = 0x1F ; // ModWidthSOF	 
        Data_Wr[ModConductance] = Param_14443B_212.GsCfgMod ;
	}
	else if	( Tx_Speed == SPEED_424_KBPS ) // Tx 424 kbps
	{	
		Data_Wr[CoderControl] = 0x10 ; // Set Tx Coding
		Data_Wr[ModWidth]     = 0x11 ; // ModWidth	 
		Data_Wr[ModWidthSOF]  = 0x11 ; // ModWidthSOF	
        Data_Wr[ModConductance] = Param_14443B_424.GsCfgMod ;
	}
	else if ( Tx_Speed == SPEED_848_KBPS ) // Tx 848 kbps
	{	
		Data_Wr[CoderControl] = 0x08 ; // Set Tx Coding
		Data_Wr[ModWidth]     = 0x07 ; // ModWidth	 
		Data_Wr[ModWidthSOF]  = 0x07 ; // ModWidthSOF	
        Data_Wr[ModConductance] = Param_14443B_848.GsCfgMod ;
	}
	else  // Tx 106 kbps
	{	
		Data_Wr[CoderControl] = 0x20 ; // Set Tx Coding
		Data_Wr[ModWidth]     = 0x3F ; // ModWidth	 
		Data_Wr[ModWidthSOF]  = 0x3F ; // ModWidthSOF	
        Data_Wr[ModConductance] = Param_14443B_106.GsCfgMod ;
	}

	htk_SPI_writeSingleRegister(CoderControl, Data_Wr[CoderControl]);
	htk_SPI_writeSingleRegister(ModWidth, Data_Wr[ModWidth]);
	htk_SPI_writeSingleRegister(ModWidthSOF, Data_Wr[ModWidthSOF]);
	htk_SPI_writeSingleRegister(ModConductance, Data_Wr[ModConductance]);
	
	if ( Rx_Speed == SPEED_212_KBPS ) // Rx 212 kbps
	{	
		Data_Wr[RxControl1] = 0x4B ; // Set SubCCar, SubCPulse
		Data_Wr[Bitphase]       = Param_14443B_212.BitPhase ;
		Data_Wr[BPSKDemod]     =  Param_14443B_212.BPSK_Demod ;	
		Data_Wr[RxThreshold]   =  Param_14443B_212.Rx_Threshold ;	
		Data_Wr[RxControl3]    =  Param_14443B_212.RxControl_3 ;	
		Data_Wr[GainST3] 			 =  Param_14443B_212.Gain_ST3 ;	 // Gain ST3
		Data_Wr[Rx43AOption] 	 =  Param_14443B_212.Rx43A_Option ;	 // RST_Int_Width, HDR_43A_Option	                
	}
	else if	( Rx_Speed == SPEED_424_KBPS ) // Rx 424 kbps
	{	
		Data_Wr[RxControl1] = 0x2B ; // Set SubCCar, SubCPulse
		Data_Wr[Bitphase]     = Param_14443B_424.BitPhase ;
		Data_Wr[RxThreshold]  = Param_14443B_424.Rx_Threshold ;	
		Data_Wr[RxControl3]   = Param_14443B_424.RxControl_3 ;	
		Data_Wr[BPSKDemod]    =  Param_14443B_424.BPSK_Demod ;	
		Data_Wr[GainST3] 			=  Param_14443B_424.Gain_ST3 ;	 // Gain ST3
		Data_Wr[Rx43AOption] 	=  Param_14443B_424.Rx43A_Option ;	 // RST_Int_Width, HDR_43A_Option	                
	}
	else if ( Rx_Speed == SPEED_848_KBPS ) // Rx 848 kbps
	{	
		Data_Wr[RxControl1] 	= 0x0B ; // Set SubCCar, SubCPulse
		Data_Wr[Bitphase]     = Param_14443B_848.BitPhase ;
		Data_Wr[RxThreshold]  = Param_14443B_848.Rx_Threshold ;	
		Data_Wr[RxControl3]   = Param_14443B_848.RxControl_3 ;	
		Data_Wr[BPSKDemod]    =  Param_14443B_848.BPSK_Demod ;	
		Data_Wr[GainST3] 			=  Param_14443B_848.Gain_ST3 ;	 // Gain ST3
		Data_Wr[Rx43AOption] 	=  Param_14443B_848.Rx43A_Option ;	 // RST_Int_Width, HDR_43A_Option	
                
	}
	else  // Rx 106 kbps
	{	
		Data_Wr[RxControl1] = 0x6B ; // Set SubCCar, SubCPulse
		Data_Wr[Bitphase]       = Param_14443B_106.BitPhase ;
		Data_Wr[RxThreshold]   	= Param_14443B_106.Rx_Threshold ;	
		Data_Wr[RxControl3]    	= Param_14443B_106.RxControl_3 ;	
		Data_Wr[BPSKDemod]     	=  Param_14443B_106.BPSK_Demod ;	
		Data_Wr[GainST3] 				=  Param_14443B_106.Gain_ST3 ;	 // Gain ST3
		Data_Wr[Rx43AOption] 		=  Param_14443B_106.Rx43A_Option ;	 // RST_Int_Width, HDR_43A_Option	
                
	}

	htk_SPI_writeSingleRegister(RxControl1, 	Data_Wr[RxControl1]);
	htk_SPI_writeSingleRegister(Bitphase, 		Data_Wr[Bitphase]);
	htk_SPI_writeSingleRegister(BPSKDemod, 		Data_Wr[BPSKDemod]);
	htk_SPI_writeSingleRegister(RxControl3,	 	Data_Wr[RxControl3]);
	htk_SPI_writeSingleRegister(RxThreshold, 	Data_Wr[RxThreshold]);
//	htk_SPI_writeSingleRegister(AnalogAdjust1, 	Data_Wr[AnalogAdjust1]);
//	htk_SPI_writeSingleRegister(AnalogAdjust2, 	Data_Wr[AnalogAdjust2]);
//	htk_SPI_writeSingleRegister(AnalogAdjust3, 	Data_Wr[AnalogAdjust3]);
}


/*******************************************************************************
* Function Name : BC45_Config_15693
* Description   : Configure Registers for ISO15693 Standard Operation
* Input         : None
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Config_15693( void )
{	
	uint8_t dataReg;

	//BC45 Ref B configuration for iso15693 ==================================
	//Tx 1 of 4, Rx 1 Sub Hi
	Data_Wr[TxControl] 				= 0x5B;
	Data_Wr[CWConductance]		= 0x3F;
	Data_Wr[ModConductance]		= 0x10;
	Data_Wr[CoderControl]			= 0x2F;
	Data_Wr[ModWidth]					= 0x3F;
	Data_Wr[ModWidthSOF]			= 0x3F;
	Data_Wr[TypeBFraming]			= 0x3B;

	Data_Wr[RxControl1]				= 0x93;
	Data_Wr[DecoderControl]		= 0x30;
	Data_Wr[Bitphase]					= 0x40;
	Data_Wr[RxThreshold]			= 0x4C;//0x88;
	Data_Wr[BPSKDemod]				= 0x04;
	Data_Wr[RxControl2]				= 0x41;
	Data_Wr[RxControl3]				= 0xF3;//0xE3;

	Data_Wr[RxWait]						= 0x01;
	Data_Wr[CRCSetting]				= 0x2C;
	Data_Wr[CRCPresetLSB]			= 0xFF;
	Data_Wr[CRCPresetMSB]			= 0xFF;

	Data_Wr[FIFOLevel]				= 0x10;
	Data_Wr[TimerClock]				= 0x0A;
	Data_Wr[TimerControl]			= 0x06;
	Data_Wr[TimerReload]			= 0xFF;
	Data_Wr[ManFilterCtrl]		= 0x19;
	Data_Wr[FilterCorCoef]		= 0x45;

	Data_Wr[IOConfig]					= 0x00;
	Data_Wr[TestAnaSel]				= 0x2E;
	Data_Wr[Rx43AOption]			= 0x28;//0x88;//0x80;
	Data_Wr[GainST3]					= 0x12;

	//Select register sector 0
	htk_SPI_writeSingleRegister(PageReg, 0x00);
	htk_SPI_writeSingleRegister(TxControl,  Data_Wr[TxControl]);
	htk_SPI_writeSingleRegister(CWConductance,  Data_Wr[CWConductance]);
	htk_SPI_writeSingleRegister(ModConductance, Data_Wr[ModConductance]);
	htk_SPI_writeSingleRegister(CoderControl,  Data_Wr[CoderControl]);
	htk_SPI_writeSingleRegister(ModWidth,  Data_Wr[ModWidth]);
	htk_SPI_writeSingleRegister(ModWidthSOF, Data_Wr[ModWidthSOF]);
	htk_SPI_writeSingleRegister(TypeBFraming,  Data_Wr[TypeBFraming]);

	htk_SPI_writeSingleRegister(RxControl1,  Data_Wr[RxControl1]);
	htk_SPI_writeSingleRegister(DecoderControl,  Data_Wr[DecoderControl]);
	htk_SPI_writeSingleRegister(Bitphase, Data_Wr[Bitphase]);
	htk_SPI_writeSingleRegister(RxThreshold,  Data_Wr[RxThreshold]);
	htk_SPI_writeSingleRegister(BPSKDemod,  Data_Wr[BPSKDemod]);
	htk_SPI_writeSingleRegister(RxControl2, Data_Wr[RxControl2]);
	htk_SPI_writeSingleRegister(RxControl3,  Data_Wr[RxControl3]);

	htk_SPI_writeSingleRegister(RxWait,  Data_Wr[RxWait]);
	htk_SPI_writeSingleRegister(CRCSetting,  Data_Wr[CRCSetting]);
	htk_SPI_writeSingleRegister(CRCPresetLSB, Data_Wr[CRCPresetLSB]);
	htk_SPI_writeSingleRegister(CRCPresetMSB,  Data_Wr[CRCPresetMSB]);

	htk_SPI_writeSingleRegister(FIFOLevel,  Data_Wr[FIFOLevel]);
	htk_SPI_writeSingleRegister(TimerClock,  Data_Wr[TimerClock]);
	htk_SPI_writeSingleRegister(TimerControl, Data_Wr[TimerControl]);
	htk_SPI_writeSingleRegister(TimerReload,  Data_Wr[TimerReload]);

	//Select register sector 1
	htk_SPI_writeSingleRegister(PageReg,  0x01);
	htk_SPI_readSingleRegister(0x0F, &dataReg);
	//Check BC45 Revision
	if(dataReg == BC45_RevB)
	{
		htk_SPI_writeSingleRegister(0x05, 0x05);
	}
	else
	{
		htk_SPI_writeSingleRegister(0x05, 0x00);
	}
	htk_SPI_writeSingleRegister(ManFilterCtrl, Data_Wr[ManFilterCtrl]);
	htk_SPI_writeSingleRegister(FilterCorCoef, Data_Wr[FilterCorCoef]);

	//Select register sector 0
	htk_SPI_writeSingleRegister(PageReg,  		0x00);
	htk_SPI_writeSingleRegister(IOConfig,  		Data_Wr[IOConfig]);
	htk_SPI_writeSingleRegister(Rx43AOption,  Data_Wr[Rx43AOption]);
	htk_SPI_writeSingleRegister(GainST3,  		Data_Wr[GainST3]);
}

/*******************************************************************************
* Function Name : BC45_Speed_15693
* Description   : Configure Registers Related to RF-Communication Bit Rate following ISO15693 Standard
* Input         : 
*				  - SPD_SEL : Speed selection 
*						High Nibble : Tx_Speed(Bit7:4)
*							- 0000b : 1 out of 256
*							- 0001b : 1 out of 4 
*							- Other : 1 out of 4 
*						Low Nibble : RxSpeed(Bit3:0)				
*							- 0000b : 1 sub low    
*							- 0001b : 1 sub high
*							- 0010b : 1 sub ultra high
*							- 0011b : 2 sub low
*							- 0100b : 2 sub high
*							- Other : 1 sub high
* Output        : None
* Return        : None
*******************************************************************************/
void BC45_Speed_15693( uint8_t SPD_SEL ) 
{	
	uint8_t  Tx_Speed, Rx_Speed ;
	
	Tx_Speed = ( SPD_SEL >> 4 ) ;
	Rx_Speed = ( SPD_SEL & 0x0F ) ; 

	if ( Tx_Speed == SPEED_1_OUT_OF_256 ) // Tx 1 out of 256
	{	
		Data_Wr[CoderControl] = 0x2E ;	// Set Tx Coding
	}
	else  // Tx 1 out of 4
	{	
		Data_Wr[CoderControl] = 0x2F ;	// Set Tx Coding
	}
	htk_SPI_writeSingleRegister(CoderControl, Data_Wr[CoderControl]);
	
        
	if ( Rx_Speed == SPEED_1_SUB_LOW ) // 1 Sub, Lo Rate
	{	
		Data_Wr[RxControl1]     = 0xD3 ;	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x30 ;	// Set Rx-Framing,Rx Coding (Manc)
		Data_Wr[RxWait] 			= 0x02 ;	// Set RxWait
		
		Data_Wr[Bitphase]     = Param_15693_1sub_lo.BitPhase  ;
		Data_Wr[RxThreshold]  = Param_15693_1sub_lo.Rx_Threshold ;
		Data_Wr[BPSKDemod]    = Param_15693_1sub_lo.BPSK_Demod ;
		Data_Wr[RxControl3]   = Param_15693_1sub_lo.RxControl_3 ;
		Data_Wr[GainST3] 			= Param_15693_1sub_lo.Gain_ST3 ;
		Data_Wr[Rx43AOption] 	= Param_15693_1sub_lo.Rx43A_Option ;
                
	}
	else if	( Rx_Speed == SPEED_1_SUB_ULTRA_HIGH ) // 1 Sub, Ultra-Hi Rate
	{	
		Data_Wr[RxControl1]     = 0x73 ;	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x30 ;	// Set Rx-Framing,Rx Coding (Manc)
		Data_Wr[RxWait] 	= 0x10 ;	// Set RxWait

		Data_Wr[Bitphase]     = Param_15693_1sub_uhi.BitPhase  ;
		Data_Wr[RxThreshold]  = Param_15693_1sub_uhi.Rx_Threshold ;
		Data_Wr[BPSKDemod]    = Param_15693_1sub_uhi.BPSK_Demod ;
		Data_Wr[RxControl3]   = Param_15693_1sub_uhi.RxControl_3 ;
		Data_Wr[GainST3] 			= Param_15693_1sub_uhi.Gain_ST3 ;
		Data_Wr[Rx43AOption] 	= Param_15693_1sub_uhi.Rx43A_Option ;
	}
	else if ( Rx_Speed == SPEED_2_SUB_LOW ) // 2 Sub, Lo Rate
	{	
		Data_Wr[RxControl1]     = 0xD3 ;	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x32 ;	// Set Rx-Framing,Rx Coding  (FSK)
		Data_Wr[RxWait] 	= 0x02 ;	// Set RxWait
		
		Data_Wr[Bitphase]    = Param_15693_2sub_lo.BitPhase  ;
		Data_Wr[RxThreshold]   = Param_15693_2sub_lo.Rx_Threshold ;
		Data_Wr[BPSKDemod]     = Param_15693_2sub_lo.BPSK_Demod ;
		Data_Wr[RxControl3]    = Param_15693_2sub_lo.RxControl_3 ;
		Data_Wr[GainST3] 			 = Param_15693_2sub_lo.Gain_ST3 ;
		Data_Wr[Rx43AOption] 	 = Param_15693_2sub_lo.Rx43A_Option ;
	}
	else if ( Rx_Speed == SPEED_2_SUB_HIGH ) // 2 Sub, Hi Rate
	{	
		Data_Wr[RxControl1]     = 0x93 ;	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x32 ;	// Set Rx-Framing,Rx Coding  (FSK)
		Data_Wr[RxWait] 		= 0x08 ;	// Set RxWait

		Data_Wr[Bitphase]      = Param_15693_2sub_hi.BitPhase  ;
		Data_Wr[RxThreshold]   = Param_15693_2sub_hi.Rx_Threshold ;
		Data_Wr[BPSKDemod]     = Param_15693_2sub_hi.BPSK_Demod ;
		Data_Wr[RxControl3]    = Param_15693_2sub_hi.RxControl_3 ;
		Data_Wr[GainST3] 			 = Param_15693_2sub_hi.Gain_ST3 ;
		Data_Wr[Rx43AOption] 	 = Param_15693_2sub_hi.Rx43A_Option ;
	}
	else  // 1 Sub, Hi Rate
	{	
		Data_Wr[RxControl1]     = 0x93 ;	// Set SubCCar, SubCPulse
		Data_Wr[DecoderControl] = 0x30 ;	// Set Rx-Framing,Rx Coding (Manc)
		Data_Wr[RxWait] 		= 0x08 ;	// Set RxWait

		Data_Wr[Bitphase]      = Param_15693_1sub_hi.BitPhase  ;
		Data_Wr[RxThreshold]   = Param_15693_1sub_hi.Rx_Threshold ;
		Data_Wr[BPSKDemod]     = Param_15693_1sub_hi.BPSK_Demod ;
		Data_Wr[RxControl3]    = Param_15693_1sub_hi.RxControl_3 ;
		Data_Wr[GainST3] 			 = Param_15693_1sub_hi.Gain_ST3 ;
		Data_Wr[Rx43AOption] 	 = Param_15693_1sub_hi.Rx43A_Option ;
                
	}

	htk_SPI_writeSingleRegister(RxControl1, 	Data_Wr[RxControl1]);
	htk_SPI_writeSingleRegister(DecoderControl, Data_Wr[DecoderControl]);
	htk_SPI_writeSingleRegister(Bitphase, 		Data_Wr[Bitphase]);
	htk_SPI_writeSingleRegister(RxWait, 		Data_Wr[RxWait]);

	htk_SPI_writeSingleRegister(RxThreshold, 	Data_Wr[RxThreshold]);
	htk_SPI_writeSingleRegister(BPSKDemod, 		Data_Wr[BPSKDemod]);
	htk_SPI_writeSingleRegister(RxControl3, 	Data_Wr[RxControl3]);
//	htk_SPI_writeSingleRegister(AnalogAdjust1, 	Data_Wr[AnalogAdjust1]);
//	htk_SPI_writeSingleRegister(AnalogAdjust2, 	Data_Wr[AnalogAdjust2]);
//	htk_SPI_writeSingleRegister(AnalogAdjust3, 	Data_Wr[AnalogAdjust3]);
        
}


/*******************************************************************************
* Function Name : BC45_Diagnose
* Description   : Diagnose BC45 basic functions and interface between MCU and BC45.
*				  Diagnosis includes FIFO, SPI, IRQ PIN
* Input         : None
* Output        : None
* Return        : 
*				  	- Status
*						- _SUCCESS_				  
*						- BC45_DIAGNOSE_ERR				  
*******************************************************************************/
uint8_t BC45_Diagnose( void )
{
	uint8_t  Status ;
	uint8_t  FIFO_Data ;
	uint8_t  InterruptFlag_Data ;
	uint8_t  FIFO_Length ;
	
	// Flush , Read FIFO_Length must be 0 , Check Interrupt Flag = LoAlert is set
	BC45_Flush_FIFO() ;
	FIFO_Length = BC45_Read_FIFOLength() ;
	htk_SPI_readSingleRegister(InterruptRq, &InterruptFlag_Data);
	if ( (FIFO_Length == 0) && (InterruptFlag_Data == LoAlertIRQ) )
	{	
		// Write FIFO , Read FIFO_Length must be 1
		htk_SPI_writeSingleRegister( FIFOData, 0xAA ) ;
		FIFO_Length = BC45_Read_FIFOLength() ;
		if ( FIFO_Length == 1 )
		{	
			// Read FIFO , Read FIFO_Length must be 0
			htk_SPI_readSingleRegister(FIFOData, &FIFO_Data);
			FIFO_Length = BC45_Read_FIFOLength() ;
			if ( (FIFO_Data == 0xAA) && (FIFO_Length == 0) )
			{	
				// Enalble Interrupt --> IRQ pin must be '1'
				htk_SPI_writeSingleRegister(InterruptEn,  (0x80 | LoAlertIRQ));
				if ( BC45_IRQ_PIN() == 1 )
				{
					// Disable Interrupt --> IRQ pin must be '0'
					BC45_Disable_And_ClearFlag_IRQ( LoAlertIRQ ) ;
					if ( BC45_IRQ_PIN() == 0 )
					{
						Status = _SUCCESS_ ;						
					}
					else // IRQ pin != '0'
					{
						Status = BC45_DIAGNOSE_ERR ;
					}
				}
				else // IRQ pin != '1'
				{
					Status = BC45_DIAGNOSE_ERR ;
				}
			}
			else // Data in FIFO != 0xAA or FIFO length != 0
			{
				Status = BC45_DIAGNOSE_ERR ;
			}
		}
		else // Write FIFO = 1 byte but FIFO length != 1
		{
			Status = BC45_DIAGNOSE_ERR ;
		}
	}
	else // FIFO_Length != 0 or LoAlertFlag not set
	{
		Status = BC45_DIAGNOSE_ERR ;
	}
	
	return Status ;
}

/*******************************************************************************
* Function Name : BC45_Get_Chip_Version
* Description   : Get the ASIC Versions
*				 
* Input         : None
* Output        : None
* Return        : 
*					- ASIC Version  
*                        
*******************************************************************************/
uint8_t BC45_Get_Chip_Version( void )
{
	//Crystal
	return 0;
}
