/*****************************************************************************
* File Name          : BC45_Board_ASIC_Category.c
* Author             : CrystalSu
* Version            : V1.0.0.0
* Date               : Feb 10, 2020
* Description        : 
*                       - Initial_Standard_Analog_Param
*                       - Config_Standard_Analog_Param
*                       - Load_Standard_Analog_Param
*                       - BC45_Board_Get_Analog_Param
*                       - BC45_Board_Set_Analog_Param
******************************************************************************/   

#include <string.h>
#include "BC45_Board_Define.h"
#include "BC45_Chip_Function.h"
#include "Common_Utility_Category.h"
#include "BC45_Board_ASIC_Category.h"

uint8_t          Hardware_Parameter[LEN_HARDWARE_PARAM_BYTE] ;
tStandard_Param  AnalogCfg_Parameter ;

/*******************************************************************************
* Function Name : BC45_Board_ASIC_Command
* Description   : Perform 
*				  	- air interface commands following ISO15693
*					- setting up ISO15693 configuration
*					- setting and getting RF communication speed
*			
* Input         : 	- Command : Commands associated to ISO15693 as shown in source below 
*					- Param	: Parameters associated to command as shown in source below (after CMD_TYPE)
*					- LenParam : Length of input parameters
* Output        : 
*					- Data_Resp	: Reponse from operation the command
*					- LenData_Resp : Length of output response
* Return        : 
*				   - Response : Result from operating the function
*				 	 	- _SUCCESS_ 
*						- NO_RESPONSE
*						- FRAMING_ERR
*						- COLLISION_ERR
*						- PARITY_ERR
*						- CRC_ERR
*						- INVALID_RESP
*						- ASIC_EXE_TIMEOUT  
*******************************************************************************/
uint8_t BC45_Board_ASIC_Command( uint8_t Command, uint8_t *Param, uint16_t LenParam, uint8_t *Data_Resp, uint16_t *LenData_Resp )
{
	uint8_t   i ;
	uint8_t   Resp ;
	uint8_t   Num_Addr, Start_Address ;
	uint8_t   Addr[64], Data[64] ;

	switch(Command)
	{
		case Reset_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				BC45_Chip_Reset() ;
				BC45_InitChip( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
				Resp = _SUCCESS_ ;
				*( LenData_Resp ) = 0 ; 
				break ;

		case Read_Reg_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Address + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + Data_Rd + LRC									
				if ( LenParam >= 1 )
				{ 
					Addr[0] = *( Param ) ;
					if ( Addr[0] <= MAX_ADDR )
					{
						Resp = BC45_Board_ReadRegBC45( Addr[0], Data_Resp, LenData_Resp ) ;	
					}
					else
					{
						Resp = PARAMETER_NOT_CORRECT ;
						*( LenData_Resp ) = 0 ; 
					}
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*( LenData_Resp ) = 0 ; 
				}
				break ;

				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Address[0] + ... + Address[N-1] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + Data_Rd[0] + ... + Data_Rd[N-1] + LRC									
		case Read_Mutiple_Reg_BC45 :
				if ( (LenParam >= 1) && (LenParam <= 64) )
				{ 
					Resp = BC45_Board_Read_Mutiple_RegBC45( Param, LenParam, Data_Resp, LenData_Resp ) ;	
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*( LenData_Resp ) = 0 ; 
				}
				break ;

		case Write_Reg_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Address[0] + Data_Wr[0] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 2 )
				{ 
					Addr[0] = *( Param ) ;
					Data[0] = *( Param + 1 ) ;
					if ( Addr[0] <= MAX_ADDR )
					{
						Resp = BC45_Board_WriteRegBC45( Addr[0], Data[0] ) ;	
					}
					else
					{
						Resp = PARAMETER_NOT_CORRECT ;
					}
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
				*( LenData_Resp ) = 0 ; 

				break ;

		case Write_Mutiple_Reg_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Address[0] + Data_Wr[0] + ... + Address[N-1] + Data_Wr[N-1] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( (LenParam >= 2) && ( (LenParam % 2) == 0 ) )
				{ 
					Num_Addr = LenParam / 2 ;
					for ( i = 0 ; i < Num_Addr ; i++ )
					{
						Addr[i] = *( Param +  (i * 2) ) ;
						Data[i] = *( Param + (i * 2) + 1 ) ;
					}
					Resp = BC45_Board_Write_Mutiple_RegBC45( Addr, Data, Num_Addr ) ;	
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
				*( LenData_Resp ) = 0 ; 

				break ;
#if 0 //not support yet (Crystal)
		case Read_E2_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Start_Address + Num_Rd + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + Data_E2[0] + ... + Data_E2[Num_Rd-1] + LRC									
				if ( LenParam >= 2 )
				{ 
					if ( *( Param + 1 ) <= 32 ) // Len Data Read E2
					{
						Resp = BC45_ReadE2( *( Param ), *( Param + 1 ), Data_Resp, LenData_Resp ) ;	
					}
					else
					{
						Resp = PARAMETER_NOT_CORRECT ;
						*( LenData_Resp ) = 0 ; 
					}
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*( LenData_Resp ) = 0 ; 
				}

				break ;

		case Write_E2_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Start_Address + Data_Wr[0] + ... + Data_Wr[N-1] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 2 )
				{ 
					Num_Addr = LenParam - 1 ;
					Start_Address = *( Param ) ;
					if ( ((Start_Address + Num_Addr - 1) < HARDWARE_PARAM_START_ADDR) || (Start_Address >= 0x70) )
					{
						Resp = BC45_WriteE2( Start_Address, ( Param + 1 ), Num_Addr ) ;	
					}
					else
					{
						Resp = PARAMETER_NOT_CORRECT ;
					}
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
				*( LenData_Resp ) = 0 ; 

				break ;

		case Load_E2_Config_BC45 : // 0x27
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Start_Address + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
												if ( LenParam >= 1 )
				{ 
					Resp = BC45_LoadE2Config( *( Param ) ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
				*( LenData_Resp ) = 0 ; 

				break ;
#endif
		case Cal_CRC :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Start_Addr + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 1 )
				{ 
					Resp = BC45_Cal_CRC( Param, LenParam, Data_Resp, LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*( LenData_Resp ) = 0 ; 
				}
		break ;

		case ON_Field_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				BC45_ON_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
				Resp = _SUCCESS_ ;
				*( LenData_Resp ) = 0 ; 
		break ;

		case OFF_Field_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				BC45_OFF_RF( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
				Resp = _SUCCESS_ ;
				*( LenData_Resp ) = 0 ; 
				break ;

		case Set_TimeOut_Wait_Tag_Resp_BC45 :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Timeout + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( LenParam >= 1 )
				{ 
					BC45_Timer_Set_Resp_Waiting_Time( *( Param ) ) ;	
					Resp = _SUCCESS_ ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
				*( LenData_Resp ) = 0 ; 
				break ;

		case BC45_Diagnose_Cmd :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				Resp = BC45_Diagnose() ;								
				*( LenData_Resp ) = 0 ; 
				break ;
                
		case BC45_Init_Standard_Ana_Param :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				Initial_Standard_Analog_Param() ;		
																												Resp = _SUCCESS_ ;
				*( LenData_Resp ) = 0 ; 
				break ;
                
		case BC45_Set_Standard_Ana_Param :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Standard + Addr_AnaParam[0] + Data_Wr[0] + ... + Addr_AnaParam[N-1] + Data_Wr[N-1] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				if ( (LenParam >= 3) && ( (LenParam % 2) == 1 ) )
				{ 
					Num_Addr = (LenParam  - 1 )/ 2 ;
					for ( i = 0 ; i < Num_Addr ; i++ )
					{
						Addr[i] = *( Param + (i * 2) + 1) ;
						Data[i] = *( Param + (i * 2) + 2 ) ;
					}
					Resp = BC45_Board_Set_Analog_Param( *Param ,  Addr, Data, Num_Addr ) ;	
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}								
				*( LenData_Resp ) = 0 ; 		
				break ;
                
		case BC45_Get_Standard_Ana_Param :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Standard + Addr_AnaParam[0] + Addr_AnaParam[1] + ... + Addr_AnaParam[N-1] + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + Data_AnaParam[0] + Data_AnaParam[1] + ... + Data_AnaParam[N- 1] + LRC									
				if ( (LenParam >= 2) && (LenParam <= 64) )
				{ 
					
																																Resp = BC45_Board_Get_Analog_Param( *Param , Param+1 , (LenParam - 1), Data_Resp,  LenData_Resp ) ;
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
					*( LenData_Resp ) = 0 ; 
				}

				break ;
                
		case BC45_Get_ASIC_Version :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + ASIC_Version + LRC									
								
																												*( Data_Resp ) = BC45_Get_Chip_Version () ;
				Resp = _SUCCESS_ ;
				*( LenData_Resp ) = 1 ; 								

				break ;
                
                
		/////////////////////// BC Proprietary and Test Command ////////////////////
		case Reset_BC45_Without_Init :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + LRC									
				BC45_Chip_Reset() ;
				Resp = _SUCCESS_ ;
				*( LenData_Resp ) = 0 ; 
				break ;
                
		case Write_Read_Reg_Check :
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + CMD + Address + Data_Wr + LRC
				// SOP + LEN_H + LEN_L + SEQ_NUM + DEV_ID + CMD_TYPE + FBP_CMD + RESP + Data_Rd + LRC	
					
				if ( LenParam >= 2 )
				{ 
					Addr[0] = *( Param ) ;
					Data[0] = *( Param + 1 ) ;
					if ( Addr[0] <= MAX_ADDR )
					{
						Resp = BC45_Board_WriteRegBC45( Addr[0], Data[0] ) ;	
																																				Resp = BC45_Board_ReadRegBC45 ( Addr[0], Data_Resp, LenData_Resp ) ;	
					}
					else
					{
						Resp = PARAMETER_NOT_CORRECT ;
					}
				}
				else
				{
					Resp = PARAMETER_NOT_CORRECT ;
				}
			
				break ;

		default :
				Resp = UNKNOWN_CMD ;
				*( LenData_Resp ) = 0 ; 
		break ;
	} ;
	
	return Resp ;
}

/*******************************************************************************
* Function Name : Initial_BC45_Board
* Description   : Initial BC45 Board paremeter from default values store in BC45 EEPROM 
*			      to BC45 registers and MCU variables.
*				  This routine includes BC45 Diagnosis, read paramters from BC45 EEPROM.
*				  If reading from BC45 fails by any reasons, default values are used.
* Input         : None
* Output        : None
* Return        : 
*				  	- Status
*						- _SUCCESS_				  
*						- BC45_DIAGNOSE_ERR				  
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- ACCESS_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Initial_BC45_Board( void )
{
	uint8_t Status;
	uint8_t msg[32];
	
	BC45_BOARD_PROPERTY.Device_ID = 0x00;
	BC45_BOARD_PROPERTY.Driver_Config_Type = 0x00;
	BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val = DEFAULT_ASIC_EXE_TIMEOUT; // Initial Timeout 3 S
	
	BC45_RSTPD_SET();
	Delay_us(2000);
	BC45_RSTPD_CLR();
	Delay_us(2400);					//Hard PD mode wakeup time
	
	Initial_Standard_Analog_Param(); // Initial Parameter
	BC45_InitChip(BC45_BOARD_PROPERTY.Driver_Config_Type);
	
	Status = BC45_Diagnose();
	if(Status == _SUCCESS_) 
	{
		BC45_Config_Driver(BC45_BOARD_PROPERTY.Driver_Config_Type);
		//strcpy(msg,"\r\ndiagnose successfully");
		//htk_UART_Transmit(msg,strlen(msg));
	}
	else // BC45_Diagnose Error
	{
		strcpy(msg,"\r\ndiagnose failed\r\n");
		htk_UART_Transmit(msg,strlen(msg));
	}
	
	return Status ;
}

/*******************************************************************************
* Function Name : BC45_Board_Get_Analog_Param
* Description   : Get BC45 Register Parameter from buffer following input standard
* Input         : 
*                   - Standard
*                   - Analog_Param_Address
*                   - Number of Analog_Param_Address
* Output        : 
*                   - Analog_Param_Value
*                   - Length
* Return        :
*                   -_SUCCESS_
*******************************************************************************/
uint8_t BC45_Board_Get_Analog_Param( uint8_t Standard, uint8_t *Addr_AnaParam_Rd, uint8_t Num_Address_Rd, uint8_t *Data_AnaParam_Rd, uint16_t *LenData_Rd ) 
{
  	uint8_t  i ;
        uint8_t  Address_AnaParam ;
        
        Load_Standard_Analog_Param (Standard , &AnalogCfg_Parameter); 
	
	for ( i = 0 ; i < Num_Address_Rd ; i++ )
	{ 
          Address_AnaParam = * (Addr_AnaParam_Rd + i);
          
         switch ( Address_AnaParam  )
         {   case Ana_Param_GsCfgMod :
               *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.GsCfgMod ;
            break ;
            
            case Ana_Param_BitPhase :
               *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.BitPhase ;
            break ;
            
            case Ana_Param_Rx_Threshold :
                *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.Rx_Threshold ;
            break ;
            
            case Ana_Param_BPSK_Demod :
                *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.BPSK_Demod ;
            break ;
            
            case Ana_Param_BPSK_RxControl_3 :
                *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.RxControl_3 ;
            break ;
            
            case Ana_Param_BPSK_AnaAdjust1 :
                *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.AnaAdjust1 ;
            break ;
            
            case Ana_Param_BPSK_AnaAdjust2 :
                *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.AnaAdjust2 ;
            break ;
            
            case Ana_Param_BPSK_AnaAdjust3 :
                *(Data_AnaParam_Rd + i) = AnalogCfg_Parameter.AnaAdjust3 ;
            break ;
            
            default :
            break ;
          }	
	}
        *( LenData_Rd ) = ( uint16_t ) Num_Address_Rd ;
	
	return _SUCCESS_ ;
  
  
}

/*******************************************************************************
* Function Name : BC45_Board_Set_Analog_Param
* Description   : Write BC45 Register Parameter into buffer following input standard
* Input         : 
*                   - Standard
*                   - Addr_AnaParam_Wr
*                   - Data_AnaParam_Wr
*                   - Num_Address_Wr
* Output        : None
* Return        :
*                   -_SUCCESS_
*******************************************************************************/
uint8_t BC45_Board_Set_Analog_Param( uint8_t Standard, uint8_t *Addr_AnaParam_Wr, uint8_t *Data_AnaParam_Wr, uint8_t Num_Address_Wr ) 
{	
	uint8_t i ;
        uint8_t Address_AnaParam ;
        

        Load_Standard_Analog_Param (Standard , &AnalogCfg_Parameter); 
        
        for ( i = 0; i < Num_Address_Wr ; i++ )
        {  Address_AnaParam =  * (Addr_AnaParam_Wr + i)  ;
         
          switch ( Address_AnaParam )
          {	
            case Ana_Param_GsCfgMod :
                AnalogCfg_Parameter.GsCfgMod = *(Data_AnaParam_Wr + i);
            break ;
            
            case Ana_Param_BitPhase :
                AnalogCfg_Parameter.BitPhase = *(Data_AnaParam_Wr + i);
            break ;
            
            case Ana_Param_Rx_Threshold :
                AnalogCfg_Parameter.Rx_Threshold = *(Data_AnaParam_Wr + i);
            break ;
            
            case Ana_Param_BPSK_Demod :
                AnalogCfg_Parameter.BPSK_Demod = *(Data_AnaParam_Wr + i);
            break ;
            
            case Ana_Param_BPSK_RxControl_3 :
                AnalogCfg_Parameter.RxControl_3 = *(Data_AnaParam_Wr + i);
            break ;
            
            case Ana_Param_BPSK_AnaAdjust1 :
                AnalogCfg_Parameter.AnaAdjust1 = *(Data_AnaParam_Wr + i);
            break ;
            
            case Ana_Param_BPSK_AnaAdjust2 :
                AnalogCfg_Parameter.AnaAdjust2 = *(Data_AnaParam_Wr + i);
            break ;
            
            case Ana_Param_BPSK_AnaAdjust3 :
                AnalogCfg_Parameter.AnaAdjust3 = *(Data_AnaParam_Wr + i);
            break ;
            
            default :
            break ;
          };
        }
        
        Config_Standard_Analog_Param (Standard , &AnalogCfg_Parameter);
              
        return _SUCCESS_ ;

}

/*******************************************************************************
* Function Name : Initial_Standard_Analog_Param
* Description   : Initialze some BC45 Register Parameter for all standard into Firmware Buffer
* Input         : None      
* Output        : None
* Return        : None
*******************************************************************************/
void Initial_Standard_Analog_Param( void  ) 
{	
	AnalogCfg_Parameter.GsCfgMod     = 0x10 ;
	AnalogCfg_Parameter.Rx_Threshold = 0x4C ;
	AnalogCfg_Parameter.BPSK_Demod   = 0x02 ;
	AnalogCfg_Parameter.RxControl_3  = 0xF0 ;
	
	AnalogCfg_Parameter.AnaAdjust1   = 0xBB ;
	
	AnalogCfg_Parameter.AnaAdjust2   = 0x19 ; // Gain State 3
	AnalogCfg_Parameter.AnaAdjust3   = 0x00 ;
	
	AnalogCfg_Parameter.BitPhase     = 0x40 ;
	Config_Standard_Analog_Param (Ana_Param_14443A_106 , &AnalogCfg_Parameter);
	
	AnalogCfg_Parameter.BitPhase     = 0x88 ;
	Config_Standard_Analog_Param (Ana_Param_14443A_212 , &AnalogCfg_Parameter);
	
	AnalogCfg_Parameter.BitPhase     = 0x32 ;
	Config_Standard_Analog_Param (Ana_Param_14443A_424 , &AnalogCfg_Parameter);

	AnalogCfg_Parameter.BitPhase     = 0x40 ;
	Config_Standard_Analog_Param (Ana_Param_14443A_848 , &AnalogCfg_Parameter);

	AnalogCfg_Parameter.GsCfgMod     = 0x17 ;
	AnalogCfg_Parameter.BitPhase     = 0x20 ;
	Config_Standard_Analog_Param (Ana_Param_14443B_106 , &AnalogCfg_Parameter);
	Config_Standard_Analog_Param (Ana_Param_14443B_212 , &AnalogCfg_Parameter);
	Config_Standard_Analog_Param (Ana_Param_14443B_424 , &AnalogCfg_Parameter);
	Config_Standard_Analog_Param (Ana_Param_14443B_848 , &AnalogCfg_Parameter);

	Config_Standard_Analog_Param (Ana_Param_Felica_212 , &AnalogCfg_Parameter);
	Config_Standard_Analog_Param (Ana_Param_Felica_424 , &AnalogCfg_Parameter);
	
	AnalogCfg_Parameter.Rx_Threshold = 0x6A ;
	AnalogCfg_Parameter.AnaAdjust2   = 0x21 ; // Gain State 3
	
	AnalogCfg_Parameter.BitPhase     = 0x0E ;
	Config_Standard_Analog_Param (Ana_Param_15693_1sub_lo , &AnalogCfg_Parameter);

	AnalogCfg_Parameter.BitPhase     = 0x40 ;
	Config_Standard_Analog_Param (Ana_Param_15693_1sub_hi , &AnalogCfg_Parameter);

	AnalogCfg_Parameter.BitPhase     = 0x88 ;
	Config_Standard_Analog_Param (Ana_Param_15693_1sub_uhi , &AnalogCfg_Parameter);
	
	AnalogCfg_Parameter.Rx_Threshold = 0xAA ;
	
	AnalogCfg_Parameter.BitPhase     = 0x0E ;
	Config_Standard_Analog_Param (Ana_Param_15693_2sub_lo , &AnalogCfg_Parameter);
	
	AnalogCfg_Parameter.BitPhase     = 0x40 ;
	Config_Standard_Analog_Param (Ana_Param_15693_2sub_hi , &AnalogCfg_Parameter);

}

/*******************************************************************************
* Function Name : Load_Standard_Analog_Param
* Description   : Load some BC45 Register Parameter to buffer following input standard
* Input         :     
*                         - Stadard
*                         - AnalogCfg_Parameter(struct - output)    
* Output        : None
* Return        : None
*******************************************************************************/
void Load_Standard_Analog_Param ( uint8_t Standard , tStandard_Param* Standard_Param_Out) 
{
   switch(Standard)      
      {
      case Ana_Param_14443A_106 :
            * Standard_Param_Out = Param_14443A_106;
        break;
        
      case Ana_Param_14443A_212 :
            * Standard_Param_Out = Param_14443A_212;
        break;
        
      case Ana_Param_14443A_424 :
            * Standard_Param_Out = Param_14443A_424;
        
        break;
      
      case Ana_Param_14443A_848 :
            * Standard_Param_Out = Param_14443A_848;
      
        
      case Ana_Param_14443B_106 :
            * Standard_Param_Out = Param_14443B_106;
        break;
        
      case Ana_Param_14443B_212 :
            * Standard_Param_Out = Param_14443B_212;
        break;
        
      case Ana_Param_14443B_424 :
            * Standard_Param_Out = Param_14443B_424;
        break;
      
      case Ana_Param_14443B_848 :
            * Standard_Param_Out = Param_14443B_848;
        break;  

      case Ana_Param_Felica_212 :
           * Standard_Param_Out = Param_Felica_212;
        break;  

      case Ana_Param_Felica_424 :
           * Standard_Param_Out = Param_Felica_424;
        break;   
        
      case Ana_Param_15693_1sub_lo :
           * Standard_Param_Out = Param_15693_1sub_lo;   
        break;  

      case Ana_Param_15693_1sub_hi :
           * Standard_Param_Out = Param_15693_1sub_hi;   
        break;      

      case Ana_Param_15693_1sub_uhi :
           * Standard_Param_Out = Param_15693_1sub_uhi;
        break;   
        
      case Ana_Param_15693_2sub_lo :
           * Standard_Param_Out = Param_15693_2sub_lo;       
        break;  

      case Ana_Param_15693_2sub_hi :
           * Standard_Param_Out = Param_15693_2sub_hi;
        break; 
        
      default :
           * Standard_Param_Out = Param_14443A_106;
        break ;  
      }
}
  



/*******************************************************************************
* Function Name : Config_Standard_Analog_Param
* Description   : Configure some BC45 Register Parameter for each Standard following input paramater
* Input         :     
*                         - Stadard
*                         - AnalogCfg_Parameter (struct - input)    
* Output        : None
* Return        : None
*******************************************************************************/
void Config_Standard_Analog_Param( uint8_t Standard , tStandard_Param *AnalogCfg_Parameter) 
{	
 
      switch(Standard)      
      {
      case Ana_Param_14443A_106 :
            Param_14443A_106.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443A_106.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443A_106.Rx_Threshold   = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443A_106.BPSK_Demod     = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443A_106.RxControl_3    = AnalogCfg_Parameter->RxControl_3;
            Param_14443A_106.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443A_106.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443A_106.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;
        
      case Ana_Param_14443A_212 :
            Param_14443A_212.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443A_212.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443A_212.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443A_212.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443A_212.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_14443A_212.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443A_212.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443A_212.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;
        
      case Ana_Param_14443A_424 :
            Param_14443A_424.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443A_424.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443A_424.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443A_424.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443A_424.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_14443A_424.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443A_424.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443A_424.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        
        break;
      
      case Ana_Param_14443A_848 :
            Param_14443A_848.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443A_848.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443A_848.Rx_Threshold   = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443A_848.BPSK_Demod     = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443A_848.RxControl_3    = AnalogCfg_Parameter->RxControl_3;
            Param_14443A_848.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443A_848.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443A_848.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;
      
        
      case Ana_Param_14443B_106 :
            Param_14443B_106.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443B_106.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443B_106.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443B_106.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443B_106.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_14443B_106.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443B_106.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443B_106.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;
        
      case Ana_Param_14443B_212 :
            Param_14443B_212.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443B_212.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443B_212.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443B_212.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443B_212.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_14443B_212.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443B_212.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443B_212.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;
        
      case Ana_Param_14443B_424 :
            Param_14443B_424.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443B_424.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443B_424.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443B_424.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443B_424.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_14443B_424.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443B_424.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443B_424.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        
        break;
      
      case Ana_Param_14443B_848 :
            Param_14443B_848.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443B_848.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_14443B_848.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443B_848.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443B_848.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_14443B_848.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443B_848.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443B_848.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;  

      case Ana_Param_Felica_212 :
            Param_Felica_212.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_Felica_212.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_Felica_212.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_Felica_212.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_Felica_212.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_Felica_212.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_Felica_212.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_Felica_212.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;  

      case Ana_Param_Felica_424 :
            Param_Felica_424.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_Felica_424.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_Felica_424.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_Felica_424.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_Felica_424.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_Felica_424.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_Felica_424.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_Felica_424.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;   
        
      case Ana_Param_15693_1sub_lo :
            Param_15693_1sub_lo.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_15693_1sub_lo.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_15693_1sub_lo.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_15693_1sub_lo.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_15693_1sub_lo.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_15693_1sub_lo.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_15693_1sub_lo.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_15693_1sub_lo.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;        
        break;  

      case Ana_Param_15693_1sub_hi :
            Param_15693_1sub_hi.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_15693_1sub_hi.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_15693_1sub_hi.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_15693_1sub_hi.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_15693_1sub_hi.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_15693_1sub_hi.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_15693_1sub_hi.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_15693_1sub_hi.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;      

      case Ana_Param_15693_1sub_uhi :
            Param_15693_1sub_uhi.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_15693_1sub_uhi.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_15693_1sub_uhi.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_15693_1sub_uhi.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_15693_1sub_uhi.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_15693_1sub_uhi.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_15693_1sub_uhi.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_15693_1sub_uhi.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break;   
        
      case Ana_Param_15693_2sub_lo :
            Param_15693_2sub_lo.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_15693_2sub_lo.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_15693_2sub_lo.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_15693_2sub_lo.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_15693_2sub_lo.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_15693_2sub_lo.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_15693_2sub_lo.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_15693_2sub_lo.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;        
        break;  

      case Ana_Param_15693_2sub_hi :
            Param_15693_2sub_hi.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_15693_2sub_hi.BitPhase      = AnalogCfg_Parameter->BitPhase;
            Param_15693_2sub_hi.Rx_Threshold    = AnalogCfg_Parameter->Rx_Threshold;
            Param_15693_2sub_hi.BPSK_Demod      = AnalogCfg_Parameter->BPSK_Demod;
            Param_15693_2sub_hi.RxControl_3     = AnalogCfg_Parameter->RxControl_3;
            Param_15693_2sub_hi.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_15693_2sub_hi.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_15693_2sub_hi.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break; 
        
      default :
            Param_14443A_106.GsCfgMod       = AnalogCfg_Parameter->GsCfgMod;
            Param_14443A_106.Rx_Threshold   = AnalogCfg_Parameter->Rx_Threshold;
            Param_14443A_106.BPSK_Demod     = AnalogCfg_Parameter->BPSK_Demod;
            Param_14443A_106.RxControl_3    = AnalogCfg_Parameter->RxControl_3;
            Param_14443A_106.AnaAdjust1     = AnalogCfg_Parameter->AnaAdjust1;
            Param_14443A_106.AnaAdjust2     = AnalogCfg_Parameter->AnaAdjust2;
            Param_14443A_106.AnaAdjust3     = AnalogCfg_Parameter->AnaAdjust3;
        break ;  
      }
}


/*******************************************************************************
* Function Name : Load_BC45_Board_Property
* Description   : Get BC45_Board_Property from BC45's EEPROM and set variables in MCU.
* Input         : 
* Output        : None
* Return        : 
*				  	- Status
*						- _SUCCESS_				  
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- ACCESS_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Load_BC45_Board_Property( void )
{	 
	uint8_t   Status ;
	uint8_t   temp_TimeOut_Value_Byte[2] ;
	uint16_t  temp_ASIC_Exe_Timeout ;

	Status = Read_And_Check_Hardware_Parameter( HARDWARE_PARAM_START_ADDR, LEN_HARDWARE_PARAM_BYTE, Hardware_Parameter )  ;
	if ( Status == _SUCCESS_ )
	{
		temp_TimeOut_Value_Byte[0] = Hardware_Parameter[ASIC_EXE_TIMEOUT_VAL_INDEX_H] ;
		temp_TimeOut_Value_Byte[1] = Hardware_Parameter[ASIC_EXE_TIMEOUT_VAL_INDEX_L] ;
		temp_ASIC_Exe_Timeout = ( uint16_t )( (temp_TimeOut_Value_Byte[0] << 8) | temp_TimeOut_Value_Byte[1] ) ;
		if ( temp_ASIC_Exe_Timeout > MINIMUM_ASIC_EXE_TIMEOUT )
		{
			BC45_BOARD_PROPERTY.Device_ID = Hardware_Parameter[DEVICE_ID_INDEX] ;
			BC45_BOARD_PROPERTY.Driver_Config_Type = Hardware_Parameter[DRIVER_CONFIG_INDEX] ;
			BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val = temp_ASIC_Exe_Timeout ;
			Status = _SUCCESS_ ;
		}
		else
		{	// Default value
			BC45_BOARD_PROPERTY.Device_ID = 0x00 ;
			BC45_BOARD_PROPERTY.Driver_Config_Type = 0x00 ;
			BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val = DEFAULT_ASIC_EXE_TIMEOUT ; // Initial Timeout
			Status = HARDWARE_PARAM_NOT_CORRECT ;
		}
	}
	else
	{	// Default value
		BC45_BOARD_PROPERTY.Device_ID = 0x00 ;
		BC45_BOARD_PROPERTY.Driver_Config_Type = 0x00 ;
		BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val = DEFAULT_ASIC_EXE_TIMEOUT ; // Initial Timeout
	}
	
	return Status ;	
}

uint8_t Cal_CheckSum( uint8_t *Data_Cal, uint8_t Len_Data_Cal )
{
	uint8_t  i ; 
	uint8_t  CHK_SUM_CAL ;
	
	CHK_SUM_CAL	= 0x00 ;
	for ( i = 0 ; i < Len_Data_Cal ; i++ )
	{	 
		CHK_SUM_CAL ^= *( Data_Cal + i ) ;
	}

	return CHK_SUM_CAL ;
}

/*******************************************************************************
* Function Name : Read_Hardware_Parameter
* Description   : Get BC45_Board_Property from BC45's EEPROM only 
* Input         : 
*				  	- Start_Addr
*				  	- Len_Read_Hardware_Param
* Output        : 	  
*				  	- Hardware_Param
* Return        : 
*				  	- Status
*						- _SUCCESS_				  
*						- ACCESS_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Read_Hardware_Parameter( uint8_t Start_Addr, uint8_t Len_Read_Hardware_Param, uint8_t *Hardware_Param )
{
	uint8_t   Status ;
	uint16_t  temp_Len_Hardware_Param ;
	
	Status = BC45_ReadE2( Start_Addr, Len_Read_Hardware_Param, Hardware_Param, &temp_Len_Hardware_Param )  ;

	return Status ; 
}

/*******************************************************************************
* Function Name : Read_And_Check_Hardware_Parameter
* Description   : Get BC45_Board_Property from BC45's EEPROM and verify check_sum of read data package.
* Input         : 
*				  	- Start_Addr
*				  	- Len_Read_Hardware_Param
* Output        : 	  
*				  	- Hardware_Param
* Return        : 
*				  	- Status
*						- _SUCCESS_				  
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- ACCESS_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Read_And_Check_Hardware_Parameter( uint8_t Start_Addr, uint8_t Len_Read_Hardware_Param, uint8_t *Hardware_Param )
{
	uint8_t Status ;
	uint8_t Check_Sum_Cal, Check_Sum_from_Packet ;
	
	Status = Read_Hardware_Parameter( Start_Addr, Len_Read_Hardware_Param, Hardware_Param ) ;
	if ( Status == _SUCCESS_ )
	{
		Check_Sum_from_Packet = *( Hardware_Param + HARDWARE_CHECKSUM_INDEX ) ;
		Check_Sum_Cal = Cal_CheckSum( Hardware_Param, Len_Read_Hardware_Param - 1 ) ;	
		if ( Check_Sum_Cal == Check_Sum_from_Packet )
		{
			Status = _SUCCESS_ ;
		}
		else
		{
			Status = CHECKSUM_HARDWARE_PARAM_FAIL ;
		}
	}
	
	return Status ;
}

/*******************************************************************************
* Function Name : Write_Hardware_Parameter
* Description   : Write BC45_Board_Property to specific address in BC45's EEPROM  
* Input         : 
*				 	- Start_Addr 		: Address in BC45 EEPROM where first data of Hardware_Parameter will be stored.
*				  	- Hardware_Param	: Data to be written
*				  	- Len_Write_Hardware_Param :
* Output        : None	  
* Return        : 
*				  	- Status
*						- _SUCCESS_				  
*						- ACCESS_E2_ERR
*						- WRITE_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Write_Hardware_Parameter( uint8_t Start_Addr, uint8_t *Hardware_Param, uint8_t Len_Write_Hardware_Param )
{
	uint8_t   Status ;
	
	Status = BC45_WriteE2( Start_Addr, Hardware_Param, Len_Write_Hardware_Param )  ;

	return Status ; 
}

/*******************************************************************************
* Function Name : Write_Specific_Hardware_Parameter
* Description   : Write Specific_Hardware_Parameter to BC45's EEPROM
*				  This rountine also recalculates check sum of total package 
*				  and then rewrite all parameter back to BC45's EEPROM.
*				  Note that multiple parameters in consecutive order can be written at the same time
* Input         : 
*				  	- Index_Hardware_Param : Index of Hardware_Parameter to be modified
*						- HARDWARE_CHECKSUM_INDEX				  
*						- DEVICE_ID_INDEX				  
*						- DRIVER_CONFIG_INDEX				  
*						- ASIC_EXE_TIMEOUT_VAL_INDEX_H				  
*				  	- Data	: New Data to replace
*				  	- LenData : Length of data to be replace
* Output        : None	  
* Return        : 
*				  	- Status
*						- _SUCCESS_				  
*						- ACCESS_E2_ERR
*						- WRITE_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Write_Specific_Hardware_Parameter( uint8_t Index_Hardware_Param, uint8_t *Data, uint8_t LenData )
{
	uint8_t   i ;
	uint8_t   Status ;
	uint8_t   Check_Sum_Cal ;
	
	Status = Read_Hardware_Parameter( HARDWARE_PARAM_START_ADDR, LEN_HARDWARE_PARAM_BYTE, Hardware_Parameter )  ;
	
	if ( Status == _SUCCESS_ )
	{
		for ( i = 0 ; i < LenData ; i++ )
		{
			Hardware_Parameter[Index_Hardware_Param + i] = *( Data + i ) ;
		}
		
		Check_Sum_Cal = Cal_CheckSum( Hardware_Parameter, LEN_HARDWARE_PARAM_BYTE - 1 ) ;
		Hardware_Parameter[HARDWARE_CHECKSUM_INDEX] = Check_Sum_Cal ;
		
		Status = Write_Hardware_Parameter( HARDWARE_PARAM_START_ADDR, Hardware_Parameter, LEN_HARDWARE_PARAM_BYTE ) ;
	}
	
	return Status ;
}

/*******************************************************************************
* Function Name : Read_Device_ID
* Description   : Read Device_ID from BC45's EEPROM
* Input         : None
* Output        : 	- Device_ID	  
* Return        : 
*				  	- Status
*						- _SUCCESS_
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- ACCESS_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Read_Device_ID( uint8_t *Device_ID )
{	 
	uint8_t   Status ;

	Status = Read_And_Check_Hardware_Parameter( HARDWARE_PARAM_START_ADDR, LEN_HARDWARE_PARAM_BYTE, Hardware_Parameter )  ;
	if ( Status == _SUCCESS_ )
	{
		*( Device_ID ) = Hardware_Parameter[DEVICE_ID_INDEX] ;
	}
	else
	{
		*( Device_ID ) = 0x00 ;
	}
	
	return Status ;	
}

/*******************************************************************************
* Function Name : BC45_Board_Write_Device_ID
* Description   : Write Device ID to BC45's EEPROM 
* Input         : 
*				  - NEW_DEVICE_ID
* Output        : None
* Return        : 
*				  - Response
*						- _SUCCESS_				  
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- WRITE_HARDWARE_PARAM_FAIL				  
*						- ACCESS_E2_ERR
*						- WRITE_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Board_Write_Device_ID( uint8_t NEW_DEVICE_ID )
{
	uint8_t   Resp ;
	uint8_t   temp_Device_ID = 0 ;
	
	Resp = Write_Specific_Hardware_Parameter( DEVICE_ID_INDEX, &NEW_DEVICE_ID, 1 ) ;
	if ( Resp == _SUCCESS_ ) 
	{	
		Resp = Read_Device_ID( &temp_Device_ID ) ;
		if ( Resp == _SUCCESS_ ) 
		{	
			if ( temp_Device_ID == NEW_DEVICE_ID ) 
			{
				BC45_BOARD_PROPERTY.Device_ID = temp_Device_ID ;
				Resp = _SUCCESS_ ;
			}
			else
			{
				Resp = WRITE_HARDWARE_PARAM_FAIL ;
			}
		}
	}
	else
	{
		Resp = WRITE_HARDWARE_PARAM_FAIL ;
	}	

	return Resp ;	
}

/*******************************************************************************
* Function Name : Read_Driver_Config
* Description   : Read Driver Configuation from BC45's EEPROM ( After reset, this value is loaded as a defult value )
* Input         : None
* Output        : 	  
*				  - 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 
* Return        : 
*				  	- Status
*						- _SUCCESS_
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- ACCESS_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t Read_Driver_Config( uint8_t *Driver_Config )
{
	uint8_t   Status ;

	Status = Read_And_Check_Hardware_Parameter( HARDWARE_PARAM_START_ADDR, LEN_HARDWARE_PARAM_BYTE, Hardware_Parameter )  ;
	if ( Status == _SUCCESS_ )
	{
		*( Driver_Config ) = Hardware_Parameter[DRIVER_CONFIG_INDEX] ;
	}
	else
	{
		*( Driver_Config ) = 0x00 ;
	}
	
	return Status ;	
}

/*******************************************************************************
* Function Name : BC45_Board_Write_Driver_Config
* Description   : Write Driver Configuration to BC45's EEPROM and update BC45_BOARD_PROPERTY.Driver_Config_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        : 
*				  - Response
*						- _SUCCESS_				  
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- WRITE_HARDWARE_PARAM_FAIL				  
*						- ACCESS_E2_ERR
*						- WRITE_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Board_Write_Driver_Config( uint8_t Driver_Config_Type )
{
	uint8_t   Resp ;
	uint8_t   temp_Driver_Config = 0 ;
	
	Resp = Write_Specific_Hardware_Parameter( DRIVER_CONFIG_INDEX, &Driver_Config_Type, 1 ) ;
	if ( Resp == _SUCCESS_ ) 
	{	
		Resp = Read_Driver_Config( &temp_Driver_Config ) ;
		if ( Resp == _SUCCESS_ ) 
		{	
			if ( temp_Driver_Config == Driver_Config_Type ) 
			{
				BC45_BOARD_PROPERTY.Driver_Config_Type = temp_Driver_Config ;
				// Update RF Driver
				BC45_Config_Driver( BC45_BOARD_PROPERTY.Driver_Config_Type ) ;
				Resp = _SUCCESS_ ;
			}
			else
			{
				Resp = WRITE_HARDWARE_PARAM_FAIL ;
			}
		}
	}
	else
	{
		Resp = WRITE_HARDWARE_PARAM_FAIL ;
	}
	
	return Resp ;	
}

/*******************************************************************************
* Function Name : Read_ASIC_Exe_Timeout_Val
* Description   : Read ASIC Execution Timeout Value
*				  This Timeout is for MCU in case of no response from ASIC.
* Input         : None
* Output        : 
*					- ASIC_Exe_Timeout_Val : ASIC Execute timeout (mS) Ex. If Timeout_Value = 1000, timeout = 1 sec.
* Return        : 
*				  	- Status
*						- _SUCCESS_
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- ACCESS_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint16_t Read_ASIC_Exe_Timeout_Val( uint16_t *ASIC_Exe_Timeout_Val )
{	 
	uint8_t   Status ;
	uint8_t   temp_TimeOut_Value_Byte[2] ;
	uint16_t  temp_Timeout_Val ;

	Status = Read_And_Check_Hardware_Parameter( HARDWARE_PARAM_START_ADDR, LEN_HARDWARE_PARAM_BYTE, Hardware_Parameter )  ;
	if ( Status == _SUCCESS_ )
	{
		temp_TimeOut_Value_Byte[0] = Hardware_Parameter[ASIC_EXE_TIMEOUT_VAL_INDEX_H] ;
		temp_TimeOut_Value_Byte[1] = Hardware_Parameter[ASIC_EXE_TIMEOUT_VAL_INDEX_L] ;
		temp_Timeout_Val = ( uint16_t )( (temp_TimeOut_Value_Byte[0] << 8) | temp_TimeOut_Value_Byte[1] )   ;
		*( ASIC_Exe_Timeout_Val ) = temp_Timeout_Val ;			
	}
	else
	{
		*( ASIC_Exe_Timeout_Val ) = DEFAULT_ASIC_EXE_TIMEOUT ;
	}
	
	return Status ;	
}

/*******************************************************************************
* Function Name : BC45_Board_Write_ASIC_Exe_Timeout_Val
* Description   : Write ASIC Execution Timeout Value to BC45's EEPROM and update BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val.
*				  This Timeout is for MCU in case of no response from ASIC. 
* Input         : 
*				  - Timeout_Value (mS) Ex. If Timeout_Value = 1000, timeout = 1 sec.
* Output        : None
* Return        : 
*				  - Response
*						- _SUCCESS_				  
*						- CHECKSUM_HARDWARE_PARAM_FAIL
*						- WRITE_HARDWARE_PARAM_FAIL				  
*						- ACCESS_E2_ERR
*						- WRITE_E2_ERR
*						- ASIC_EXE_TIMEOUT
*******************************************************************************/
uint8_t BC45_Board_Write_ASIC_Exe_Timeout_Val( uint16_t Timeout_Value )
{
	uint8_t   Resp ;
	uint8_t   temp_TimeOut_Value_Byte[2] ;
	uint16_t  temp_Timeout_Val = 0 ;
	
	if ( Timeout_Value < MINIMUM_ASIC_EXE_TIMEOUT )
	{
		Timeout_Value = MINIMUM_ASIC_EXE_TIMEOUT ;
	}

	temp_TimeOut_Value_Byte[0] = (uint8_t)( Timeout_Value >> 8 ) ;
	temp_TimeOut_Value_Byte[1] = (uint8_t)Timeout_Value ;
	
	Resp = Write_Specific_Hardware_Parameter( ASIC_EXE_TIMEOUT_VAL_INDEX_H, temp_TimeOut_Value_Byte, 2 ) ;
	if ( Resp == _SUCCESS_ ) 
	{	
		Resp = Read_ASIC_Exe_Timeout_Val( &temp_Timeout_Val ) ;
		if ( Resp == _SUCCESS_ ) 
		{	
			if ( temp_Timeout_Val == Timeout_Value ) 
			{
				BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val = temp_Timeout_Val ;
				// Init Watchdog
				// TODO: Should be removed or use other method instead of Watchdog
			  // Independent_Watchdog_Init( (BC45_BOARD_PROPERTY.ASIC_Exe_Timeout_Val + 1000) ) ;
				Resp = _SUCCESS_ ;
			}
			else
			{
				Resp = WRITE_HARDWARE_PARAM_FAIL ;
			}
		}
	}
	else
	{
		Resp = WRITE_HARDWARE_PARAM_FAIL ;
	}
	
	return Resp ;	
}

/*******************************************************************************
* Function Name : BC45_Board_ReadRegBC45
* Description   : Read single single registers of BC45
* Input         : 
*				  - Address_Rd
* Output        : 
*				  - Data_Resp
*				  - LenData_Resp
* Return        : 
*				  - Response
*						- _SUCCESS_				  
*******************************************************************************/
uint8_t BC45_Board_ReadRegBC45( uint8_t Address_Rd, uint8_t *Data_Rd, uint16_t *LenData_Rd )
{
	htk_SPI_readSingleRegister(Address_Rd, Data_Rd);
	*( LenData_Rd ) = 1 ; 

	return _SUCCESS_ ;	
}

/*******************************************************************************
* Function Name : BC45_Board_Read_Mutiple_RegBC45
* Description   : Read data from multiple registers of BC45
* Input         : 
*				  - Address_Rd
*				  - Num_Address_Rd
* Output        : 
*				  - Data_Resp
*				  - LenData_Resp
* Return        : 
*				  - Response
*						- _SUCCESS_				  
*******************************************************************************/
uint8_t BC45_Board_Read_Mutiple_RegBC45( uint8_t *Address_Rd, uint8_t Num_Address_Rd, uint8_t *Data_Rd, uint16_t *LenData_Rd ) 
{ 
	uint8_t  i ;
	
	for ( i = 0 ; i < Num_Address_Rd ; i++ )
	{
		htk_SPI_readSingleRegister(*( Address_Rd + i ), ( Data_Rd + i ));
	}
	*( LenData_Rd ) = ( uint16_t ) Num_Address_Rd ;
	
	return _SUCCESS_ ;
}

/*******************************************************************************
* Function Name : BC45_Board_Read_Mutiple_RegBC45
* Description   : Write single data to single registers of BC45
* Input         : 
*				  - Address_Wr
*				  - Data_Wr
* Output        : 
* Return        : 
*				  - Response
*						- _SUCCESS_				  
*******************************************************************************/
uint8_t BC45_Board_WriteRegBC45( uint8_t Address_Wr, uint8_t Data_Wr )
{
	htk_SPI_writeSingleRegister(Address_Wr, Data_Wr);

	return _SUCCESS_ ;	
}

/*******************************************************************************
* Function Name : BC45_Board_Write_Mutiple_RegBC45
* Description   : Write multiple data to multiple register of BC45
* Input         : 
*				  - Address_Wr
*				  - Data_Wr
*				  - Num_Address_Wr
* Output        : 
* Return        : 
*				  - Response
*						- _SUCCESS_				  
*******************************************************************************/
uint8_t BC45_Board_Write_Mutiple_RegBC45( uint8_t *Address_Wr, uint8_t *Data_Wr, uint8_t Num_Address_Wr ) 
{ 
	uint8_t  i ;
	
	for ( i = 0 ; i < Num_Address_Wr ; i++ )
	{
		htk_SPI_writeSingleRegister(*( Address_Wr + i ), *( Data_Wr + i ));
	}
	
	return _SUCCESS_ ;
}
