/***********************************************************************************************
 * @file    bc3603.c
 * @version $Rev:: 4837         $
 * @date    $Date:: 2022-09-02 #$
 * @brief   This file provides all the RF firmware functions.
 ***********************************************************************************************
 * @attention
 *
 * Firmware Disclaimer Information
 *
 * 1. The customer hereby acknowledges and agrees that the program technical documentation, including the
 *    code, which is supplied by Holtek Semiconductor Inc., (hereinafter referred to as "HOLTEK") is the
 *    proprietary and confidential intellectual property of HOLTEK, and is protected by copyright law and
 *    other intellectual property laws.
 *
 * 2. The customer hereby acknowledges and agrees that the program technical documentation, including the
 *    code, is confidential information belonging to HOLTEK, and must not be disclosed to any third parties
 *    other than HOLTEK and the customer.
 *
 * 3. The program technical documentation, including the code, is provided "as is" and for customer reference
 *    only. After delivery by HOLTEK, the customer shall use the program technical documentation, including
 *    the code, at their own risk. HOLTEK disclaims any expressed, implied or statutory warranties, including
 *    the warranties of merchantability, satisfactory quality and fitness for a particular purpose.
 *
 * <h2><center>Copyright (C) Holtek Semiconductor Inc. All rights reserved</center></h2>
 ***********************************************************************************************/

/* Includes -----------------------------------------------------------------------------------*/
#include "bc3603.h"

/* Private constants --------------------------------------------------------------------------*/
/** @defgroup RF_Private_Define RF private definitions
  * @{
  */
/*--------------------- Bank 1 Register Address ------------------------------------------------*/
#define AGC_CTL1_REGS               0x20
#define AGC_CTL2_REGS               0x21
#define AGC_CTL3_REGS					0x22
#define AGC_CTL4_REGS               0x23
#define AGC_CTL5_REGS					0x24
#define AGC_CTL6_REGS					0x25
#define AGC_CTL7_REGS					0x26
#define FILTER_CTL1_REGS				0x2C
#define FILTER_CTL2_REGS				0x2D
#define FILTER_CTL3_REGS				0x2E
#define FILTER_CTL4_REGS				0x2F
#define FILTER_CTL5_REGS				0x30
#define FILTER_CTL6_REGS				0x31
#define FILTER_CTL7_REGS				0x32
#define FILTER_CTL8_REGS				0x33
#define FILTER_CTL9_REGS				0x34
#define FILTER_CTL10_REGS				0x35
#define FILTER_CTL11_REGS				0x36
#define FILTER_CTL12_REGS				0x37
#define FILTER_CTL13_REGS				0x38
#define FILTER_CTL14_REGS				0x39
#define FILTER_CTL15_REGS				0x3A
#define FILTER_CTL16_REGS				0x3B
#define FILTER_CTL17_REGS				0x3C
#define FILTER_CTL18_REGS				0x3D
#define FILTER_CTL19_REGS				0x3E
/*--------------------- Bank 2 Register Address ------------------------------------------------*/
#define	RX_CTL2_REGS					0x2F
#define	HIGH_IP3							(uint8_t)(1 << 7)
/*--------------------- Register Default Table--------------------------------------------------*/
#define	BANK_CHANGE						0xC0

uint8_t	BC3603_RegisterDefaultTable[][2]=
{
    {BANK_CHANGE	, REGS_BANK0},
    {CLOCK_CTL_REGS, 0x11		},
    {CLOCK_CTL_REGS, 0x10		},
    {CONFIG_REGS	, 0x40		},
    {TRX_MODE_DELAY_REGS, 0x38	},
    {DEMOULATOR_CTL4_REGS,0x58	},
    {BANK_CHANGE	, REGS_BANK1},
    {AGC_CTL2_REGS	, 0x14		},
    {BANK_CHANGE	, REGS_BANK2},
    {			0x21	, 0x97		},
    {			0x2E	, 0x68		},
    {RX_CTL2_REGS	, 0x06		},
    {			0x33	, 0x41		},
    {			0x34	, 0x90		},/* RTXAC_EN=1*/
    {			0x39	, 0x9C		},
    {			0x3B	, 0x5D		},
    {BANK_CHANGE	, REGS_BANK0},
};
#define	REGS_DEFAULT_TAB_NUM			sizeof(BC3603_RegisterDefaultTable)/(2*sizeof(uint8_t))

uint8_t DataRate2KTable[][2]=
{
    {BANK_CHANGE	, REGS_BANK0},
    {MODULATOR_CTL1_REGS,0xF9	},
    {MODULATOR_CTL2_REGS,0x60	},
    {MODULATOR_CTL3_REGS,0x67	},
    {DEMOULATOR_CTL1_REGS,0x31	},
    {DEMOULATOR_CTL2_REGS,0x09	},
    {DEMOULATOR_CTL3_REGS,0xE6	},
    {DEMOULATOR_CTL5_REGS,0x1F	},
    {DEMOULATOR_CTL8_REGS,0x05	},
    {BANK_CHANGE	, REGS_BANK1},
    {AGC_CTL1_REGS, 0x00			},
    {AGC_CTL3_REGS, 0x04			},
    {AGC_CTL7_REGS, 0x30			},
    {FILTER_CTL1_REGS, 0x30		},
    {FILTER_CTL2_REGS, 0x20		},
    {FILTER_CTL3_REGS, 0x00		},
    {FILTER_CTL4_REGS, 0x00		},
    {FILTER_CTL5_REGS, 0x00		},
    {FILTER_CTL6_REGS, 0x00		},
    {FILTER_CTL7_REGS, 0x00		},
    {FILTER_CTL8_REGS, 0x02		},
    {FILTER_CTL9_REGS, 0x03		},
    {FILTER_CTL10_REGS, 0x00	},
    {FILTER_CTL11_REGS, 0x00	},
    {FILTER_CTL12_REGS, 0x00	},
    {FILTER_CTL13_REGS, 0x00	},
    {FILTER_CTL14_REGS, 0x00	},
    {FILTER_CTL15_REGS, 0x00	},
    {FILTER_CTL16_REGS, 0x00	},
    {FILTER_CTL17_REGS, 0x00	},
    {FILTER_CTL18_REGS, 0x00	},
    {FILTER_CTL19_REGS, 0x00	},
    {BANK_CHANGE	, REGS_BANK2},
    {RX_CTL2_REGS	, 0x06		},
    {BANK_CHANGE	, REGS_BANK0},
};
#define	DATARATE_TAB_NUM				sizeof(DataRate2KTable)/(2*sizeof(uint8_t))

uint8_t DataRate10KTable[][2]=
{
    {BANK_CHANGE	, REGS_BANK0},
    {MODULATOR_CTL1_REGS,0x31	},
    {MODULATOR_CTL2_REGS,0x60	},
    {MODULATOR_CTL3_REGS,0x66	},
    {DEMOULATOR_CTL1_REGS,0x09	},
    {DEMOULATOR_CTL2_REGS,0xC9	},
    {DEMOULATOR_CTL3_REGS,0xE6	},
    {DEMOULATOR_CTL5_REGS,0x1F	},
    {DEMOULATOR_CTL8_REGS,0x1A	},
    {BANK_CHANGE	, REGS_BANK1},
    {AGC_CTL1_REGS, 0x00			},
    {AGC_CTL3_REGS, 0x04			},
    {AGC_CTL7_REGS, 0x30			},
    {FILTER_CTL1_REGS, 0x10		},
    {FILTER_CTL2_REGS, 0xA4		},
    {FILTER_CTL3_REGS, 0x00		},
    {FILTER_CTL4_REGS, 0x00		},
    {FILTER_CTL5_REGS, 0x00		},
    {FILTER_CTL6_REGS, 0x00		},
    {FILTER_CTL7_REGS, 0x00		},
    {FILTER_CTL8_REGS, 0x10		},
    {FILTER_CTL9_REGS, 0x03		},
    {FILTER_CTL10_REGS, 0x00	},
    {FILTER_CTL11_REGS, 0x00	},
    {FILTER_CTL12_REGS, 0x00	},
    {FILTER_CTL13_REGS, 0x00	},
    {FILTER_CTL14_REGS, 0x00	},
    {FILTER_CTL15_REGS, 0x00	},
    {FILTER_CTL16_REGS, 0x00	},
    {FILTER_CTL17_REGS, 0x00	},
    {FILTER_CTL18_REGS, 0x00	},
    {FILTER_CTL19_REGS, 0x00	},
    {BANK_CHANGE	, REGS_BANK2},
    {RX_CTL2_REGS	, 0x06		},
    {BANK_CHANGE	, REGS_BANK0},
};

uint8_t DataRate50KTable[][2]=
{
    {BANK_CHANGE	, REGS_BANK0},
    {MODULATOR_CTL1_REGS,0x09	},
    {MODULATOR_CTL2_REGS,0x60	},
    {MODULATOR_CTL3_REGS,0x67	},
    {DEMOULATOR_CTL1_REGS,0x13	},
    {DEMOULATOR_CTL2_REGS,0xC0	},
    {DEMOULATOR_CTL3_REGS,0xE0	},
    {DEMOULATOR_CTL5_REGS,0x30	},
    {DEMOULATOR_CTL8_REGS,0x0D	},
    {BANK_CHANGE	, REGS_BANK1},
    {AGC_CTL1_REGS, 0x00			},
    {AGC_CTL3_REGS, 0x04			},
    {AGC_CTL7_REGS, 0x30			},
    {FILTER_CTL1_REGS, 0x00		},
    {FILTER_CTL2_REGS, 0x4C		},
    {FILTER_CTL3_REGS, 0x00		},
    {FILTER_CTL4_REGS, 0x00		},
    {FILTER_CTL5_REGS, 0x00		},
    {FILTER_CTL6_REGS, 0x00		},
    {FILTER_CTL7_REGS, 0x00		},
    {FILTER_CTL8_REGS, 0x00		},
    {FILTER_CTL9_REGS, 0x00		},
    {FILTER_CTL10_REGS, 0x00	},
    {FILTER_CTL11_REGS, 0x00	},
    {FILTER_CTL12_REGS, 0x00	},
    {FILTER_CTL13_REGS, 0x00	},
    {FILTER_CTL14_REGS, 0x00	},
    {FILTER_CTL15_REGS, 0x00	},
    {FILTER_CTL16_REGS, 0x00	},
    {FILTER_CTL17_REGS, 0x00	},
    {FILTER_CTL18_REGS, 0x00	},
    {FILTER_CTL19_REGS, 0x00	},
    {BANK_CHANGE	, REGS_BANK2},
    {RX_CTL2_REGS	, 0x06		},
    {BANK_CHANGE	, REGS_BANK0},
};

uint8_t DataRate125KTable[][2]=
{
    {BANK_CHANGE	, REGS_BANK0},
    {MODULATOR_CTL1_REGS,0x03	},
    {MODULATOR_CTL2_REGS,0x90	},
    {MODULATOR_CTL3_REGS,0x9A	},
    {DEMOULATOR_CTL1_REGS,0x07	},
    {DEMOULATOR_CTL2_REGS,0xC0	},
    {DEMOULATOR_CTL3_REGS,0xE0	},
    {DEMOULATOR_CTL5_REGS,0x30	},
    {DEMOULATOR_CTL8_REGS,0x20	},
    {BANK_CHANGE	, REGS_BANK1},
    {AGC_CTL1_REGS, 0x1C			},
    {AGC_CTL3_REGS, 0x07			},
    {AGC_CTL7_REGS, 0x50			},
    {FILTER_CTL1_REGS, 0x00		},
    {FILTER_CTL2_REGS, 0x19		},
    {FILTER_CTL3_REGS, 0x01		},
    {FILTER_CTL4_REGS, 0x1D		},
    {FILTER_CTL5_REGS, 0x00		},
    {FILTER_CTL6_REGS, 0x46		},
    {FILTER_CTL7_REGS, 0x03		},
    {FILTER_CTL8_REGS, 0x22		},
    {FILTER_CTL9_REGS, 0x00		},
    {FILTER_CTL10_REGS, 0x31	},
    {FILTER_CTL11_REGS, 0x03	},
    {FILTER_CTL12_REGS, 0x86	},
    {FILTER_CTL13_REGS, 0x03	},
    {FILTER_CTL14_REGS, 0x12	},
    {FILTER_CTL15_REGS, 0x00	},
    {FILTER_CTL16_REGS, 0x08	},
    {FILTER_CTL17_REGS, 0x00	},
    {FILTER_CTL18_REGS, 0x08	},
    {FILTER_CTL19_REGS, 0x00	},
    {BANK_CHANGE	, REGS_BANK2},
    {RX_CTL2_REGS	, 0x16		},
    {BANK_CHANGE	, REGS_BANK0},
};

uint8_t DataRate250KTable[][2]=
{
    {BANK_CHANGE	, REGS_BANK0},
    {MODULATOR_CTL1_REGS,0x01	},
    {MODULATOR_CTL2_REGS,0x90	},
    {MODULATOR_CTL3_REGS,0x9A	},
    {DEMOULATOR_CTL1_REGS,0x03	},
    {DEMOULATOR_CTL2_REGS,0x40	},
    {DEMOULATOR_CTL3_REGS,0x40	},
    {DEMOULATOR_CTL5_REGS,0x30	},
    {DEMOULATOR_CTL8_REGS,0x40	},
    {BANK_CHANGE	, REGS_BANK1},
    {AGC_CTL1_REGS, 0x18			},
    {AGC_CTL3_REGS, 0x04			},
    {AGC_CTL7_REGS, 0x30			},
    {FILTER_CTL1_REGS, 0x06		},
    {FILTER_CTL2_REGS, 0x94		},
    {FILTER_CTL3_REGS, 0x02		},
    {FILTER_CTL4_REGS, 0xCA		},
    {FILTER_CTL5_REGS, 0x02		},
    {FILTER_CTL6_REGS, 0x62		},
    {FILTER_CTL7_REGS, 0x00		},
    {FILTER_CTL8_REGS, 0x58		},
    {FILTER_CTL9_REGS, 0x03		},
    {FILTER_CTL10_REGS, 0xE9	},
    {FILTER_CTL11_REGS, 0x03	},
    {FILTER_CTL12_REGS, 0xB3	},
    {FILTER_CTL13_REGS, 0x03	},
    {FILTER_CTL14_REGS, 0x3E	},
    {FILTER_CTL15_REGS, 0x00	},
    {FILTER_CTL16_REGS, 0xE9	},
    {FILTER_CTL17_REGS, 0x03	},
    {FILTER_CTL18_REGS, 0x39	},
    {FILTER_CTL19_REGS, 0x00	},
    {BANK_CHANGE	, REGS_BANK2},
    {RX_CTL2_REGS	, 0x16		},
    {BANK_CHANGE	, REGS_BANK0},
};

uint8_t *DataRateTableIndex[DATARATE250K+1] =
{
    (uint8_t *)&DataRate2KTable,
    (uint8_t *)&DataRate10KTable,
    (uint8_t *)&DataRate50KTable,
    (uint8_t *)&DataRate125KTable,
    (uint8_t *)&DataRate250KTable
};

/**
  * @}
  */

/* Global functions ---------------------------------------------------------------------------*/
/** @defgroup RF_Exported_Functions RF exported functions
  * @{
  */
/***********************************************************************************************
 * @brief Write Table to register.
 * @param index: pointer to a table
 * @param length: table size
 * @retval None
 ***********************************************************************************************/
static void BC3603_RegisterTableWrite(uint8_t *index,uint16_t length)
{
    while(length)
    {
        if(*index == BANK_CHANGE)	BC3603_RegisterBank((RF_BANK_Enum)*(index+1));
        else								BC3603_WriteRegister(*index,*(index+1));
        index += 2;
        length--;
    }
}
/***********************************************************************************************
 * @brief Deinitialize the RF peripheral registers to their default reset values.
 * @param None
 * @retval None
 ***********************************************************************************************/
BC3603_ErrStatus BC3603_DeInit(void)
{
    /* configure SPI 4-wires */
    BC3603_SetupSPI4Wires();
    /* RF software reset */
    BC3603_SoftwareReset();
    BC3603_RegisterBank(REGS_BANK2);
    BC3603_WriteRegister(0x39,0x98);
    BC3603_RegisterBank(REGS_BANK0);
    /* RF enter light sleep */
    BC3603_EnterLightSleep();
    /* configure IRQ polarity to Active high,Cleared by writing 1 to the corresponding bits */
    BC3603_SetIRQPolarity(_IRQ_POLARITY_ ? IRQ_NONINVERTED:IRQ_INVERTED,IRQ_NONINVERTED);
    /* initial register to default */
    BC3603_RegisterDefault();
    /* wait crystal ready */
    if(BC3603_WaitCrystalReady() != BC3603_SUCCESS) return(BC3603_ERROR);
    /* enter deep sleep */
    BC3603_EnterDeepSleep();
    return(BC3603_SUCCESS);
}
/***********************************************************************************************
 * @brief Configure RF SPI to 4-wires & IRQ to active high.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_SetupSPI4Wires(void)
{
    /* configure 4-wires SPI,GIO1/GIO2 to MISO/IRQ */
#if	(_SDO_IRQ_LINE_ == 0)
    BC3603_WriteRegister(GPIO12_CTL_REGS,(RF_GDCS1mA << 6) | RF_GIO_MISO | (RF_GIO_IRQ << 3));
#else
    BC3603_WriteRegister(GPIO12_CTL_REGS,(RF_GDCS1mA << 6) | (RF_GIO_MISO << 3) | RF_GIO_IRQ);
#endif
    /* configure GIO3 & GIO4 to input mode */
    BC3603_WriteRegister(GPIO34_CTL_REGS, (RF_GIO_INPUT << 4) | RF_GIO_INPUT );
    /* configure SDO tri-state,GIO3/GIO4 pull-high,CSN/SCK/SDI not pull-high */
    BC3603_WriteRegister(GPIO_PULL_UP_REGS,IO_SDO_TEN | IO_GIO4PU | IO_GIO3PU | 0x31 );
}
/***********************************************************************************************
 * @brief RF registers to their default values.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_RegisterDefault(void)
{
    BC3603_RegisterTableWrite((uint8_t *)BC3603_RegisterDefaultTable,REGS_DEFAULT_TAB_NUM);
}
/***********************************************************************************************
 * @brief Software reset command.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_SoftwareReset(void)
{
    BC3603_StrobeCommand(SOFT_RESET_CMD);
}
/***********************************************************************************************
 * @brief Set RF register bank.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_RegisterBank(RF_BANK_Enum Bank)
{
    BC3603_StrobeCommand(REGS_BANK_CMD | Bank);
}
/***********************************************************************************************
 * @brief RF enter deep sleep mode.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_EnterDeepSleep(void)
{
    BC3603_StrobeCommand(DEEP_SLEEP_CMD);
}
/***********************************************************************************************
 * @brief RF enter idle mode.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_EnterIdleMode(void)
{
    BC3603_StrobeCommand(IDLE_MODE_CMD);
}
/***********************************************************************************************
 * @brief RF enter light sleep mode.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_EnterLightSleep(void)
{
    BC3603_StrobeCommand(LIGHT_SLEEP_CMD);
}
/***********************************************************************************************
 * @brief RF enter standby mode.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_EnterStandby(void)
{
    BC3603_StrobeCommand(STANDBY_MODE_CMD);
}
/***********************************************************************************************
 * @brief RF enter transmit mode.
 * @param FSAddr:FIFO address to start transmission.
 * @retval None
 ***********************************************************************************************/
void BC3603_EnterTransmit(uint8_t FSAddr)
{
    /* set FIFO start address for Tx */
    BC3603_WriteRegister(TX_FIFO_SA_REGS,FSAddr);
    BC3603_StrobeCommand(TX_MODE_CMD);
}
/***********************************************************************************************
 * @brief RF enter receiver mode.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_EnterReceiver(void)
{
    BC3603_StrobeCommand(RX_MODE_CMD);
}
/***********************************************************************************************
 * @brief reset Tx FIFO position.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_ResetTxFIFOPosition(void)
{
    BC3603_StrobeCommand(REST_TX_POS_CMD);
}
/***********************************************************************************************
 * @brief Reset Rx FIFO position.
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_ResetRxFIFOPosition(void)
{
    BC3603_StrobeCommand(REST_RX_POS_CMD);
}
/***********************************************************************************************
 * @brief write RF syncword
 * @param SyncWord: pointer to a syncword memory.
 * @param Length: syncword length.(MAX SYNCWORD_MAX_SIZE)
 * @retval None
 ***********************************************************************************************/
void BC3603_SetSyncWord(uint8_t *SyncWord,uint8_t Length)
{
    if(Length > SYNCWORD_MAX_SIZE)
    {
        Length = SYNCWORD_MAX_SIZE;
    }
    BC3603_WriteMultipleRegister(WRITE_SYNCWORD_CMD,SyncWord,Length);
}
/***********************************************************************************************
 * @brief read RF syncword
 * @param SyncWord: pointer to a syncword memory.
 * @param Length: syncword length.(MAX SYNCWORD_MAX_SIZE)
 * @retval None
 ***********************************************************************************************/
void BC3603_GetSyncWord(uint8_t *SyncWord,uint8_t Length)
{
    if(Length > SYNCWORD_MAX_SIZE)
    {
        Length = SYNCWORD_MAX_SIZE;
    }
    BC3603_ReadMultipleRegister(READ_SYNCWORD_CMD,SyncWord,Length);
}
/***********************************************************************************************
 * @brief write payload to Tx FIFO.
 * @param Payload: pointer to payload buffer
 * @param Length: payload length,(unit:byte).
 * @retval None
 ***********************************************************************************************/
void BC3603_WriteTransmitPayload(uint8_t *Payload,uint8_t Length)
{
    uint8_t	reg,pid;

    /* packet ID auto inc */
    reg = BC3603_ReadRegister(PACKET_CTL2_REGS);
    pid = reg >> 6;
    pid++;
    reg &= (uint8_t)~PKT_TXPID_MASK;
    reg |= ((pid << 6) & PKT_TXPID_MASK);
    BC3603_WriteRegister(PACKET_CTL2_REGS,reg);
    /* set payload length */
    BC3603_WriteRegister(TX_DATA_LENG_REGS,Length);
    /* reset Tx FIFO position */
    BC3603_StrobeCommand(REST_TX_POS_CMD);
    /* write FIFO */
    if(Length > FIFO_MAX_SIZE)
        BC3603_WriteMultipleRegister(WRITE_FIFO_CMD,Payload,FIFO_MAX_SIZE);
    else
        BC3603_WriteMultipleRegister(WRITE_FIFO_CMD,Payload,Length);
}
/***********************************************************************************************
 * @brief write data to Tx FIFO.
 * @param FIFO: pointer to a FIFO buffer.
 * @param Length: FIFO length.
 * @retval None
 ***********************************************************************************************/
void BC3603_WriteTxFIFO(uint8_t *FIFO,uint8_t Length)
{
    if(Length > FIFO_MAX_SIZE)
    {
        Length = FIFO_MAX_SIZE;
    }
    BC3603_WriteMultipleRegister(WRITE_FIFO_CMD,FIFO,Length);
}
/***********************************************************************************************
 * @brief read payload data form Rx FIFO.
 * @param Payload: pointer to a payload buffer
 * @retval payload data length
 ***********************************************************************************************/
uint8_t BC3603_ReadReceiverPayload(uint8_t *Payload)
{
//	uint8_t	reg;
    uint8_t	length;

//	reg = BC3603_ReadRegister(FIFO_CTL2_REGS);
    length = BC3603_ReadRegister(RX_DATA_LENG_REGS);
//	if(reg & (uint8_t)FIFO_RXPL2F_EN) length++;
    if(length > FIFO_MAX_SIZE)
        BC3603_ReadMultipleRegister(READ_FIFO_CMD,Payload,FIFO_MAX_SIZE);
    else
        BC3603_ReadMultipleRegister(READ_FIFO_CMD,Payload,length);
    return(length);
}
/***********************************************************************************************
 * @brief read data form Rx FIFO.
 * @param FIFO : pointer to a FIFO buffer.
 * @param Length : read FIFO length.
 * @retval None
 ***********************************************************************************************/
void BC3603_ReadRxFIFO(uint8_t *FIFO,uint8_t Length)
{
    if(Length > FIFO_MAX_SIZE)
    {
        Length = FIFO_MAX_SIZE;
    }
    BC3603_ReadMultipleRegister(READ_FIFO_CMD,FIFO,Length);
}
/***********************************************************************************************
 * @brief RF parameter configures
 * @param RF_InitStruct: pointer to a RF_InitTypeDef structure.
 * @retval BC3603_ERROR or BC3603_SUCCESS
 ***********************************************************************************************/
BC3603_ErrStatus BC3603_Configures(RF_InitTypeDef *RF_InitStruct)
{
    RF_FieldTypeDef 	Field;
    RF_CodecTypeDef 	Codec;

    /* Receiver continuation mode and payload length fields must be enabled at the same time */
    if(RF_InitStruct->ReceiverMode != RECEIVER_SINGLE)
    {
        if(RF_InitStruct->LengthField != BC3603_ENABLE) return(BC3603_ERROR);
    }
    /* automatic acknowledge and payload head fields must be enabled at the same time */
    if(RF_InitStruct->AutomaticACK != BC3603_DISABLE)
    {
        if((RF_InitStruct->HeadField == HEAD_OFF) || (RF_InitStruct->LengthField != BC3603_ENABLE))
            return(BC3603_ERROR);
    }
    /* set RF Frequency */
    BC3603_FrequencyConfig(RF_InitStruct->RFBand,RF_InitStruct->Frequency);
    /* set RF data rate */
    BC3603_DataRateConfig(RF_InitStruct->RFBand,RF_InitStruct->DataRate);
    /* set RF Tx power */
    BC3603_SetTxPower(RF_InitStruct->RFBand,RF_InitStruct->TxPower);
    /* RF VCO calibration */
    if(BC3603_VCOAutoCalibration() == BC3603_ERROR) return(BC3603_ERROR);
    /* set RF packet field */
    Field.PreambleClass = RF_InitStruct->TxPremClass;
    Field.PreamblePattern = RF_InitStruct->TxPremPattern;
    Field.SyncWord = RF_InitStruct->SyncWordWidth;
    Field.Trailer = RF_InitStruct->TrailerField;
    Field.Head = RF_InitStruct->HeadField;
    Field.Length = RF_InitStruct->LengthField;
    Field.CRCEn = RF_InitStruct->CRCField;
    Field.CRCInv = RF_InitStruct->CRCInv;
    Field.CRCByteOD = RF_InitStruct->CRCByteOD;
    Field.CRCBitOD = RF_InitStruct->CRCBitOD;
    Field.CRCSeed = RF_InitStruct->CRCSeed;
    BC3603_SetPacketField(&Field);
    BC3603_SetPreambleLength(RF_InitStruct->TxPremLength);
    /* set RF packet codec */
    Codec.HeadAddrExamine = RF_InitStruct->HeadAddrExamine;
    Codec.HammingCode = RF_InitStruct->HammingCode;
    Codec.Manchester = RF_InitStruct->ManchesterCode;
    Codec.WhiteningCodec = RF_InitStruct->WhiteningCodec;
    Codec.WhiteningSeed = RF_InitStruct->WhiteningSeed;
    BC3603_SetPacketCodec(&Codec);
    /* set RF receiver parameter */
    BC3603_ReceiverConfig(RF_InitStruct->ReceiverMode);
    /* set automatic ACK function */
    BC3603_ARKControl(RF_InitStruct->AutomaticACK);
    /* set ATRRXAP/ATRRXEP/ARKRXAP time unit */
    BC3603_ATRKTimeUnit(RF_InitStruct->TimeUnit);

    return(BC3603_SUCCESS);
}
/***********************************************************************************************
 * @brief Configure the data rate of RF.
 * @param Band: Selection of RF band
 *   This parameter can be one of below:
 *     @arg BAND315M	: 315MHZ band
 *     	   BAND433M	: 433MHZ band
 *     		BAND470M	: 470~510MHZ band
 *     		BAND868M	: 868MHZ band
 *     		BAND915M	: 915MHZ band
 * @param DataRate: Selection of data rate
 *   This parameter can be one of below:
 *     @arg DATARATE2K 	: data rate 2KBps
 *      		DATARATE10K	: data rate 10KBps
 *     		DATARATE50K	: data rate 50KBps
 *     		DATARATE125K: data rate 125KBps
 *     		DATARATE250K: data rate 250KBps
 * @retval None
 ***********************************************************************************************/
uint8_t	RxHighIP3Table[] = { 0,0,0,HIGH_IP3,HIGH_IP3};
void BC3603_DataRateConfig(RF_BAND_Enum Band,RF_DATARATE_Enum DataRate)
{
    uint8_t	*DR;
    uint8_t		reg;

    if(DataRate > DATARATE250K) DataRate = DATARATE250K;
    DR = DataRateTableIndex[DataRate];
    BC3603_RegisterTableWrite(DR,DATARATE_TAB_NUM);

    /* modify Rx control register 2 */
    BC3603_RegisterBank(REGS_BANK2);
    reg = BC3603_ReadRegister(RX_CTL2_REGS);
    reg |= RxHighIP3Table[Band];
    BC3603_WriteRegister(RX_CTL2_REGS,reg);
    BC3603_RegisterBank(REGS_BANK0);
}
/***********************************************************************************************
 * @brief Configure the frequency of RF.
 * @param Band: Selection of RF band
 *   This parameter can be one of below:
 *     @arg BAND315M	: 315MHZ band
 *     	   BAND433M	: 433MHZ band
 *     		BAND470M	: 470~510MHZ band
 *     		BAND868M	: 868MHZ band
 *     		BAND915M	: 915MHZ band
 * @param Frequency: frequency value(unit:HZ)
 * @retval None
 ***********************************************************************************************/
uint8_t	FrequencyBandTable[]=
{
    (BAND315M << 5),								/* 315MHZ band */
    (BAND433M << 5),								/* 433MHZ band */
    (BAND470M << 5),								/* 470~510MHZ band */
    (BAND868M << 5),								/* 868MHZ band */
    (BAND868M << 5)								/* 915MHZ band */
};
uint8_t	FrequencyODDIVTable[] = { 4,2,2,1,1 };
void BC3603_FrequencyConfig(RF_BAND_Enum Band,uint32_t Frequency)
{
    float Fn;
    uint8_t		Dn;
    uint32_t	Dk;

    if(Band > BAND915M) Band = BAND915M;
    Dn = BC3603_ReadRegister(OPERATION_CTL_REGS) & (uint8_t)~OM_BAND_MASK;
    Dn |= FrequencyBandTable[Band];
    BC3603_WriteRegister(OPERATION_CTL_REGS,Dn);

    Fn = (float)(Frequency*1000) * FrequencyODDIVTable[Band];
    Fn /= (float)XTAL_FREQUENCY;
    Dn = (uint8_t)Fn;
    Fn -= Dn;
    Fn *= 1048576.0;
    Dk = (uint32_t)Fn;
    BC3603_WriteRegister(FRACTIONAL_N_DN_REGS,Dn);
    if((Dk & 0xFF) <= 5) BC3603_WriteRegister(FRACTIONAL_N_DKL_REGS,0x05);
    else 						BC3603_WriteRegister(FRACTIONAL_N_DKL_REGS,Dk & 0xFF);
    BC3603_WriteRegister(FRACTIONAL_N_DKM_REGS,(Dk >> 8) & 0xFF);
    BC3603_WriteRegister(FRACTIONAL_N_DKH_REGS,(Dk >> 16) & 0xFF);
}
/***********************************************************************************************
 * @brief Configure the Tx power of RF.
 * @param Band: Selection of RF band
 *   This parameter can be one of below:
 *     @arg BAND315M	: 315MHZ band
 *     	   BAND433M	: 433MHZ band
 *     		BAND470M	: 470~510MHZ band
 *     		BAND868M	: 868MHZ band
 *     		BAND915M	: 915MHZ band
 * @param Power: Selection of Tx power
 *   This parameter can be one of below:
 *     @arg TXPOWER0DBM : Tx Power 0dBm
 *				TXPOWER10DBM: Tx Power 10dBm
 *				TXPOWER13DBM: Tx Power 13dBm
*				TXPOWER17DBM: Tx Power 17dBm
 *				TXPOWER19DBM: Tx Power 19dBm
 * @retval None
 ***********************************************************************************************/
uint8_t	TxPowerValueTable[][TXPOWER19DBM+1]=
{
    /*0dBm,10dBm,13dBm,17dBm,19dBm */
    { 0x18, 0x29, 0x32, 0x3B, 0x3B },		/* 315MHz */
    { 0x18, 0x27, 0x30, 0x37, 0x3B },		/* 433MHz */
    { 0x16, 0x2B, 0x33, 0x39, 0x3C },		/* 470MHz */
    { 0x20, 0x2F, 0x35, 0x3A, 0x3D },		/* 868MHz */
    { 0x16, 0x2B, 0x33, 0x3A, 0x3D }			/* 915MHz */
};
void BC3603_SetTxPower(RF_BAND_Enum Band,RF_TXPWR_Enum Power)
{
    if(Band > BAND915M) Band = BAND915M;
    if(Power > TXPOWER19DBM) Power = TXPOWER19DBM;
    BC3603_WriteRegister(TX_POWER_CTL_REGS,TxPowerValueTable[Band][Power]);
}
/***********************************************************************************************
 * @brief Enable or Disable the field of RF packet.
 * @param Field : pointer to a RF_FieldTypeDef structure.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetPacketField(RF_FieldTypeDef *Field)
{
    uint8_t	reg,reg1;

    reg1 = BC3603_ReadRegister(PACKET_CTL10_REGS);
    reg1 &= ~(PKT_PMLP_EN + PKT_PMLPLEN);
    reg1 |= ((Field->PreambleClass) & (PKT_PMLP_EN + PKT_PMLPLEN));

    reg = BC3603_ReadRegister(PACKET_CTL2_REGS);
    /* trailer field enable/disable */
    if(Field->Trailer != BC3603_DISABLE)
    {
        reg |= PKT_TRAILER_EN;
    }
    else
    {
        reg &= ~PKT_TRAILER_EN;
    }
    /* syncword width */
    if(Field->SyncWord > 0) Field->SyncWord--;
    reg &= ~PKT_SYNCLEN_MASK;
    reg |= (((uint8_t)Field->SyncWord << 1) & PKT_SYNCLEN_MASK);
    BC3603_WriteRegister(PACKET_CTL2_REGS,reg);

    reg1 &= ~PKT_SYNCLENLB;
    if((uint8_t)Field->SyncWord & 0x01) reg1 |= PKT_SYNCLENLB;

    reg = BC3603_ReadRegister(PACKET_CTL3_REGS);
    /* head field enable/disable/length */
    reg &= (uint8_t)~(PKT_PLHF_EN + PKT_PLHLEN);
    if(Field->Head != HEAD_OFF)
    {
        reg |= PKT_PLHF_EN;													/* header field enable */
        if(Field->Head == HEAD_16BIT)
        {
            reg |= PKT_PLHLEN;	   /* 16bit header length */
        }
    }
    /* length field enable/disable */
    if(Field->Length != BC3603_DISABLE)
    {
        reg |= PKT_PLLEN_EN;
    }
    else
    {
        reg &= ~PKT_PLLEN_EN;
    }
    /* CRC field enable/disable */
    reg &= ~(PKT_CRC_EN+PKT_CRCFMT);
    if(Field->CRCEn != CRC_OFF)
    {
        reg |= PKT_CRC_EN;
        if(Field->CRCEn == CRC_IBC16)
        {
            reg |= PKT_CRCFMT;
        }
    }
    if(Field->CRCInv == CRC_INVERTED)
    {
        reg1 |= PKT_CRCINV;
    }
    else
    {
        reg1 &= ~PKT_CRCINV;
    }
    if(Field->CRCBitOD == CRC_LSB_FIRST)
    {
        reg1 |= PKT_CRCBITO;
    }
    else
    {
        reg1 &= ~PKT_CRCBITO;
    }
    if(Field->CRCByteOD == CRC_LOW_FIRST)
    {
        reg1 |= PKT_CRCBYTEO;
    }
    else
    {
        reg1 &= ~PKT_CRCBYTEO;
    }

    BC3603_WriteRegister(PACKET_CTL3_REGS,reg);
    BC3603_WriteRegister(PACKET_CTL10_REGS,reg1);
    BC3603_WriteRegister(PREAMBLE_PATL_REGS,Field->PreamblePattern & 0xFF);
    BC3603_WriteRegister(PREAMBLE_PATH_REGS,(Field->PreamblePattern >> 8) & 0xFF);
    BC3603_WriteRegister(CRC_SEED_L_REGS,Field->CRCSeed & 0xFF);
    BC3603_WriteRegister(CRC_SEED_H_REGS,(Field->CRCSeed >> 8) & 0xFF);
}
/***********************************************************************************************
 * @brief Configure the parameter of RF codec.
 * @param Codec : pointer to a RF_CodecTypeDef structure.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetPacketCodec(RF_CodecTypeDef *Codec)
{
    uint8_t	reg,reg1;

    reg = BC3603_ReadRegister(PACKET_CTL3_REGS);
    /* header address examine enable/disable */
    if(Codec->HeadAddrExamine != BC3603_DISABLE)
    {
        reg |= PKT_PLHAC_EN;
    }
    else
    {
        reg &= ~PKT_PLHAC_EN;
    }
    /* Hamming code enable/disable */
    if(Codec->HammingCode != BC3603_DISABLE)
    {
        reg |= PKT_FEC_EN;
    }
    else
    {
        reg &= ~PKT_FEC_EN;
    }
    /* Manchester Code enable/disable */
    if(Codec->Manchester != BC3603_DISABLE)
    {
        reg |= PKT_MCH_EN;
    }
    else
    {
        reg &= ~PKT_MCH_EN;
    }
    BC3603_WriteRegister(PACKET_CTL3_REGS,reg);

    if(Codec->WhiteningCodec != WHT_OFF)
    {
        /* set whitening seed */
        reg = Codec->WhiteningSeed & PKT_WHTSD_MASK;
        /* enable whitening codec function */
        reg |= PKT_WHT_EN;
        BC3603_WriteRegister(WHITEN_CTL_REGS,reg);

        reg = BC3603_ReadRegister(PACKET_CTL15_REGS);
        reg &= PKT_WHTSD87_MASK;
        reg1 = (Codec->WhiteningSeed >> 1) & PKT_WHTSD87_MASK;
        reg |= reg1;
        BC3603_WriteRegister(PACKET_CTL15_REGS,reg);

        /* set whitening codec type */
        reg = BC3603_ReadRegister(PACKET_CTL2_REGS);
        reg &= ~PKT_WHTFMT0;
        reg1 = BC3603_ReadRegister(PACKET_CTL10_REGS);
        reg1 &= ~PKT_WHTFMT1;
        switch((uint8_t)Codec->WhiteningCodec)
        {
        case WHTPN7:
            reg |= PKT_WHTFMT0;
            break;
        case WHTPN9CCIT:
            reg1 |= PKT_WHTFMT1;
            break;
        case WHTPN9IBM:
            reg |= PKT_WHTFMT0;
            reg1 |= PKT_WHTFMT1;
            break;
        default:
        case WHT36X:
            break;
        }
        BC3603_WriteRegister(PACKET_CTL2_REGS,reg);
        BC3603_WriteRegister(PACKET_CTL10_REGS,reg1);
    }
    else
    {
        /* disable whitening codec function */
        reg = BC3603_ReadRegister(WHITEN_CTL_REGS);
        reg &= ~PKT_WHT_EN;
        BC3603_WriteRegister(WHITEN_CTL_REGS,reg);
    }
}
/***********************************************************************************************
 * @brief Configure the parameter of receiver mode.
 * @param RxMode: Selection of receiver mode
 *   This parameter can be one of below:
 *     @arg RECEIVER_SINGLE 	: single mode
 *				RECEIVER_CONTINUE : continue mode
 * @retval None
 ***********************************************************************************************/
void BC3603_ReceiverConfig(RF_RCVM_Enum RxMode)
{
    uint8_t	reg1,reg2;

    /* Rx continue mode enable/disable */
    reg1 = BC3603_ReadRegister(CONFIG_REGS);
    reg2 = BC3603_ReadRegister(FIFO_CTL2_REGS);
    if(RxMode != RECEIVER_SINGLE)
    {
        reg1 |= (uint8_t)CFG_RXCON_EN;					/* Enable Rx continue mode */
        reg2 |= (uint8_t)FIFO_RXPL2F_EN;            /* Enable Payload length for Rx FIFO */
    }
    else
    {
        reg1 &= (uint8_t)~CFG_RXCON_EN;					/* Disable Rx continue mode */
        reg2 &= (uint8_t)~FIFO_RXPL2F_EN;           /* Disable Payload length for Rx FIFO */
    }
    BC3603_WriteRegister(CONFIG_REGS,reg1);
    BC3603_WriteRegister(FIFO_CTL2_REGS,reg2);
}
/***********************************************************************************************
 * @brief Enable or Disable Extend FIFO mode.
 * @param FFMgs : Selection of FIFO depth low threshold
 *   This parameter can be one of below:
 *     @arg FFMG4BYTE	: FIFO length margin 4bytes
 *				FFMG8BYTE	: FIFO length margin 8bytes
 *				FFMG16BYTE	: FIFO length margin 16bytes
 *				FFMG32BYTE  : FIFO length margin 32bytes
 * @param NewState : This parameter can be BC3603_ENABLE or BC3603_DISABLE.
 * @retval None
 ***********************************************************************************************/
void BC3603_ExtendFIFOConfig(RF_FFMGS_Enum FFMgs,BC3603_ControlStatus NewState)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(FIFO_CTL2_REGS);
    if(NewState != BC3603_DISABLE)
    {
        reg |= FIFO_FFMG_EN;
        reg &= (uint8_t)~FIFO_FFMG_MASK;
        reg |= FFMgs;
    }
    else
    {
        reg &= (uint8_t)~FIFO_FFMG_EN;
    }
    BC3603_WriteRegister(FIFO_CTL2_REGS,reg);
}
/***********************************************************************************************
 * @brief Enable or Disable Infinite FIFO mode.
 * @param FFMgs : Selection of FIFO depth low threshold
 *   This parameter can be one of below:
 *     @arg FFMG4BYTE	: FIFO length margin 4bytes
 *				FFMG8BYTE	: FIFO length margin 8bytes
 *				FFMG16BYTE	: FIFO length margin 16bytes
 *				FFMG32BYTE  : FIFO length margin 32bytes
 * @param NewState : This parameter can be BC3603_ENABLE or BC3603_DISABLE.
 * @retval None
 ***********************************************************************************************/
void BC3603_InfiniteFIFOControl(RF_FFMGS_Enum FFMgs,BC3603_ControlStatus NewState)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(FIFO_CTL2_REGS);
    reg &= 0xFC;
    reg |= FFMgs;
    if(NewState != BC3603_DISABLE)
    {
        reg |= FIFO_FFINF_EN|reg|FIFO_FFMG_EN;
    }
    else
    {
        reg &= (uint8_t)~(FIFO_FFINF_EN|FIFO_FFMG_EN);
    }
    BC3603_WriteRegister(FIFO_CTL2_REGS,reg);
}
/***********************************************************************************************
 * @brief Check whether the infinite FIFO flag has been BC3603_ENABLE or BC3603_DISABLE.
 * @param None
 * @retval BC3603_SET or BC3603_RESET
 ***********************************************************************************************/
BC3603_FlagStatus BC3603_GetInfiniteFIFOStatus(void)
{
    if( BC3603_ReadRegister(FIFO_CTL2_REGS) & FIFO_FFINF_EN )
        return( BC3603_SET );
    else
        return(BC3603_RESET);
}
/***********************************************************************************************
 * @brief Configure GIO driving strength and pull resistor and SDO TriState.
 * @param GDCS : specify the GIO driving strength.
 *   This parameter can be one of the following values:
 *     @arg RF_GDCS500uA :	GIO driving strength 0.5mA
 *     @arg	RF_GDCS1mA	 :	GIO driving strength 1mA
 *     @arg	RF_GDCS5mA	 :	GIO driving strength 5mA
 *     @arg	RF_GDCS10mA  : GIO driving strength 10mA
 * @param PullBitMap: specify the GIO pull register enable or disable.
 *   This parameter can be any combination of IO_GIO1PU/IO_GIO2PU/IO_GIO3PU/IO_GIO4PU/IO_SPIPU.
 * @param SDOTri: specify the SDO Tri-State BC3603_ENABLE or BC3603_DISABLE.
 * @retval None
 ***********************************************************************************************/
void BC3603_GIOConfig(RF_GDCS_Enum GDCS,uint8_t PullBitMap,BC3603_ControlStatus SDOTri)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(GPIO12_CTL_REGS);
    reg &= (uint8_t)~IO_PADDS_MASK;
    reg |= (GDCS << 6) & IO_PADDS_MASK;
    BC3603_WriteRegister(GPIO12_CTL_REGS,reg);

    reg = BC3603_ReadRegister(GPIO_PULL_UP_REGS);
    PullBitMap &= (IO_GIO1PU | IO_GIO2PU | IO_GIO3PU |	IO_GIO4PU |	IO_SPIPU);
    reg &= ~(IO_GIO1PU | IO_GIO2PU | IO_GIO3PU |	IO_GIO4PU |	IO_SPIPU);
    reg |= PullBitMap;
    if(SDOTri != BC3603_DISABLE)
    {
        reg |= IO_SDO_TEN;
    }
    else
    {
        reg &= (uint8_t)~IO_SDO_TEN;
    }
    BC3603_WriteRegister(GPIO_PULL_UP_REGS,reg);
}
/***********************************************************************************************
 * @brief Configure the function of specified GIO pins.
 * @param GIO : GIO pins
 *   This parameter can be any combination of RF_GIO1/RF_GIO2/RF_GIO3/RF_GIO4.
 * @param Fun : Selection of GIO function
 *   This parameter can be one of below:
 *     @arg RF_GIO_INPUT 	: GPIO input mode
 *     		RF_GIO_MISO		: 4-wire SPI data output
 *     		RF_GIO_TRXD		: Direct mode TX/RD data input/output
 *     		RF_GIO_IRQ 		: interrupt request output
 *     		RF_GIO_LOSCI	: ATR clock external input
 *     		RF_GIO_TBCLK 	: Tx clock output
 *     		RF_GIO_RBCLK	: Rx(recovery) clock output
 *     		RF_GIO_FCLKO	: Frequency clock output
 *     		RF_GIO_LIRCO	: internal LIRC clock output
 *     		RF_GIO_EPACO	: External PA control output
 *     		RF_GIO_ELNACO	: External LNA control output
 *     		RF_GIO_TRBCLK	: Direct mode Tx/Rx bit clock output
 * @retval None
 ***********************************************************************************************/
void BC3603_SetGIOFunction(RF_GIOS_Enum GIO,RF_GIOF_Enum Fun)
{
    uint8_t regs,value;

    regs = GPIO12_CTL_REGS + (GIO / 2 );
    value = BC3603_ReadRegister(regs);
    if(GIO < 2 )
    {
        value &= ~(0x07 << (3*(GIO % 2)));
        value |= ((Fun & 0x07) << (3*(GIO % 2)));
    }
    else
    {
        value &= ~(0x0F << (4*(GIO % 2)));
        value |= ((Fun & 0x0F) << (4*(GIO % 2)));
    }
    BC3603_WriteRegister(regs,value);
}
/***********************************************************************************************
 * @brief Fine tune of Crystal load capacitor.
 * @param xshift: Coarse tune of XO load capacitor for different crystal CLOAD.
 * @param xtim: Fine tune of XO load capacitor.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetCrystalCload(uint8_t xshift,uint8_t xtim)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(XO_CAP_CTL_REGS);
    reg = (reg & ~XO_SHIFT_MASK) | ((xshift  << 6) & XO_SHIFT_MASK);
    reg = (reg & ~XO_TRIM_MASK) | (xtim & XO_TRIM_MASK);
    BC3603_WriteRegister(XO_CAP_CTL_REGS,reg);
}
/***********************************************************************************************
 * @brief Wait for Crystal is ready to be used..
 * @param None
 * @retval BC3603_SUCCESS or BC3603_ERROR
 ***********************************************************************************************/
BC3603_ErrStatus BC3603_WaitCrystalReady(void)
{
    uint32_t	ReadyCnt = 0;

    while((BC3603_ReadRegister(CLOCK_CTL_REGS) & RC_XCLK_RDY) == BC3603_RESET)
    {
        if(++ReadyCnt >= XCLK_READY_TIME) return(BC3603_ERROR);
    }
    return(BC3603_SUCCESS);
}
/***********************************************************************************************
 * @brief Check whether the power on flag has been set or not.
 * @param None
 * @retval BC3603_SET or BC3603_RESET
 ***********************************************************************************************/
BC3603_FlagStatus BC3603_GetPowerOnFlag(void)
{
    if((BC3603_ReadRegister(CLOCK_CTL_REGS) & RC_PWRON) != BC3603_RESET)
    {
        return(BC3603_SET);
    }
    else
    {
        return(BC3603_RESET);
    }
}
/***********************************************************************************************
 * @brief Clear the power on flag..
 * @param None
 * @retval None
 ***********************************************************************************************/
void BC3603_ClearPowerOnFlag(void)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(CLOCK_CTL_REGS);
    reg &= (uint8_t)~RC_PWRON;
    BC3603_WriteRegister(CLOCK_CTL_REGS,reg);
}
/***********************************************************************************************
 * @brief Enable or Disable Fsyck output.
 * @param CKPRE : Selection of FIFO depth low threshold
 *   This parameter can be one of below:
 *     @arg FSYCK_DIV1	: FSYCK = XCLK divison 1
 *				FSYCK_DIV2	: FSYCK = XCLK divison 2
 *				FSYCK_DIV4	: FSYCK = XCLK divison 4
 *				FSYCK_DIV8  : FSYCK = XCLK divison 8
 * @param NewState : This parameter can be BC3603_ENABLE or BC3603_DISABLE.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetFSYCKPrescaler(RF_FSYCK_Enum CKPRE,BC3603_ControlStatus NewState)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(CLOCK_CTL_REGS);
    if(NewState != BC3603_DISABLE)
    {
        reg |= (uint8_t)RC_FSYCK_EN;
    }
    else
    {
        reg &= (uint8_t)~RC_FSYCK_EN;
    }
    reg &= (uint8_t)~RC_FSYCK_DIV_MASK;
    reg |= (uint8_t)(CKPRE << 2) & RC_FSYCK_DIV_MASK;
    BC3603_WriteRegister(CLOCK_CTL_REGS,reg);
}
/***********************************************************************************************
 * @brief Configure the receiver detect event.
 * @param DETS: Selection of detect event.
 *   This parameter can be one of below:
 *     @arg DET_CARRY 		: RX detect event of carry
 *				DET_SYNCWORD	: Rx detect event of sync-word
 * @retval None
 ***********************************************************************************************/
void BC3603_SetReceiverDetectEvent(RF_RXDETS_Enum DETS)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(IRQ_CTL_REGS);
    reg &= (uint8_t)~IRQ_RXDETS_MASK;
    reg |= (uint8_t)(DETS << 2) & IRQ_RXDETS_MASK;
    BC3603_WriteRegister(IRQ_CTL_REGS,reg);
}
/***********************************************************************************************
 * @brief Check whether the receiver error flag has been set or not.
 * @param FlagBitMap: error flag
 *   This parameter can be any combination of IRQ_RXFFOW/IRQ_RXTO/IRQ_RXCRCF.
 * @retval BC3603_SET or BC3603_RESET
 ***********************************************************************************************/
BC3603_FlagStatus BC3603_GetReceiverErrorStatus(uint8_t FlagBitMap)
{
    FlagBitMap &= (IRQ_RXCRCF| IRQ_RXFFOW | IRQ_RXTO);

    if((BC3603_ReadRegister(IRQ_CTL_REGS) & FlagBitMap) != BC3603_RESET)
    {
        return(BC3603_SET);
    }
    else
    {
        return(BC3603_RESET);
    }
}
/***********************************************************************************************
 * @brief Check whether the receiver error flag has been set or not.
 * @param None
 *   This parameter can be any combination of IRQ_RXFFOW/IRQ_RXTO/IRQ_RXCRCF.
 * @retval Error Flag
 * 	@val 	IRQ_RXCRCF : Rx CRC error flag
 *				IRQ_RXFFOW : Rx FIFO overwrite flag
 *				IRQ_RXTO   : Rx timeout flag.
 ***********************************************************************************************/
uint8_t BC3603_GetReceiverErrorFlag(void)
{
    return(BC3603_ReadRegister(IRQ_CTL_REGS) & (IRQ_RXCRCF| IRQ_RXFFOW | IRQ_RXTO));
}
/***********************************************************************************************
 * @brief Set the IRQ active and clear IRQ flag polarity.
 * @param POR: Selection of IRQ active polarity
 *   This parameter can be one of below:
 *     @arg IRQ_INVERTED 		: IRQ polarity is active low or falling edge
 *				IRQ_NONINVERTED	: IRQ polarity is active high or rising edge
 * @param CPOR: Selection of clear IRQ flag polarity
 *   This parameter can be one of below:
 *     @arg IRQ_INVERTED 		: clear IRQ flag is write 0
 *				IRQ_NONINVERTED	: clear IRQ flag is write 1
 * @retval None
 ***********************************************************************************************/
void BC3603_SetIRQPolarity(RF_IRQPOL_Enum POR,RF_IRQPOL_Enum CPOR)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(IRQ_CTL_REGS);
    if(POR == IRQ_NONINVERTED)
    {
        reg |= (uint8_t)IRQ_POLARITY;
    }
    else
    {
        reg &= (uint8_t)~IRQ_POLARITY;
    }
    if(CPOR == IRQ_NONINVERTED)
    {
        reg |= (uint8_t)IRQ_CLR_POR;
    }
    else
    {
        reg &= (uint8_t)~IRQ_CLR_POR;
    }
    BC3603_WriteRegister(IRQ_CTL_REGS,reg);
}
/***********************************************************************************************
 * @brief Enable or Disable the specified IRQ interrupts.
 * @param IrqBitMap: specify IRQ enable
 *   This parameter can be any combination of
 *     @arg	IRQ_TXCMPIE	: TX Complete IRQ Enable
 *				IRQ_RXCMPIE : RX Complete IRQ Enable
 *				IRQ_CALCMPIE: Calibration Complete IRQ Enable
 *				IRQ_RXDETIE : RX Event Detected IRQ Enable
 *				IRQ_RXERRIE : RX Error IRQ Enable
 *				IRQ_FIFOLTIE: FIFO Low Threshold IRQ Enable
 *				IRQ_ATRCTIE : ATR Cycle Timer IRQ Enable
 *				IRQ_ARKTFIE : ARK TX Failure IRQ Enable
 * @param NewState: This parameter can be BC3603_ENABLE or BC3603_DISABLE.
 * @retval None
 ***********************************************************************************************/
void BC3603_IRQConfig(uint8_t IrqBitMap,BC3603_ControlStatus NewState)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(IRQ_ENABLE_REGS);
    if(NewState != BC3603_DISABLE)
    {
        reg |= IrqBitMap;
    }
    else
    {
        reg &= ~IrqBitMap;
    }
    BC3603_WriteRegister(IRQ_ENABLE_REGS,reg);
}
/***********************************************************************************************
 * @brief Get IRQ flag
 * @param None
 * @retval IRQ Flag
 *     @arg	IRQ_TXCMPIF	: TX Complete IRQ Flag
 *				IRQ_RXCMPIF : RX Complete IRQ Flag
 *				IRQ_CALCMPIF: Calibration Complete IRQ Flag
 *				IRQ_RXDETIF : RX Event Detected IRQ Flag
 *				IRQ_RXERRIF : RX Error IRQ Flag
 *				IRQ_FIFOLTIF: FIFO Low Threshold IRQ Flag
 *				IRQ_ATRCTIF : ATR Cycle Timer IRQ Flag
 *				IRQ_ARKTFIF : ARK TX Failure IRQ Flag
 ***********************************************************************************************/
uint8_t	BC3603_GetIRQFlag(void)
{
    return(BC3603_ReadRegister(IRQ_STATUS_REGS));
}
/***********************************************************************************************
 * @brief Check whether the IRQ flag has been set or not.
 * @param FlagBitMap: IRQ flag
 *   This parameter can be any combination of
 *     @arg	IRQ_TXCMPIF	: TX Complete IRQ Flag
 *				IRQ_RXCMPIF : RX Complete IRQ Flag
 *				IRQ_CALCMPIF: Calibration Complete IRQ Flag
 *				IRQ_RXDETIF : RX Event Detected IRQ Flag
 *				IRQ_RXERRIF : RX Error IRQ Flag
 *				IRQ_FIFOLTIF: FIFO Low Threshold IRQ Flag
 *				IRQ_ATRCTIF : ATR Cycle Timer IRQ Flag
 *				IRQ_ARKTFIF : ARK TX Failure IRQ Flag
 * @retval BC3603_SET or BC3603_RESET
 ***********************************************************************************************/
BC3603_FlagStatus BC3603_GetIRQFlagStatus(uint8_t FlagBitMap)
{
    if((BC3603_ReadRegister(IRQ_STATUS_REGS) & FlagBitMap) != BC3603_RESET)
    {
        return(BC3603_SET);
    }
    else
    {
        return(BC3603_RESET);
    }
}
/***********************************************************************************************
 * @brief Clear the specified IRQ flag.
 * @param FlagBitMap: IRQ flag
 *   This parameter can be any combination of
 *     @arg	IRQ_TXCMPIF	: TX Complete IRQ Flag
 *				IRQ_RXCMPIF : RX Complete IRQ Flag
 *				IRQ_CALCMPIF: Calibration Complete IRQ Flag
 *				IRQ_RXDETIF : RX Event Detected IRQ Flag
 *				IRQ_RXERRIF : RX Error IRQ Flag
 *				IRQ_FIFOLTIF: FIFO Low Threshold IRQ Flag
 *				IRQ_ATRCTIF : ATR Cycle Timer IRQ Flag
 *				IRQ_ARKTFIF : ARK TX Failure IRQ Flag
 * @retval None
 ***********************************************************************************************/
void BC3603_ClearIRQFlag(uint8_t FlagBitMap)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(IRQ_CTL_REGS);
    if((reg & IRQ_CLR_POR) == IRQ_CLR_POR)
        BC3603_WriteRegister(IRQ_STATUS_REGS,FlagBitMap);
    else
        BC3603_WriteRegister(IRQ_STATUS_REGS,~FlagBitMap);
}
/***********************************************************************************************
 * @brief Set Tx preamble length
 * @param Length: specify data length of the preamble.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetPreambleLength(uint8_t Length)
{
    if(Length > 0) Length--;
    BC3603_WriteRegister(PREAMBLE_LENG_REGS,Length);
}
/***********************************************************************************************
 * @brief Set Tx payload length
 * @param Length: specify data length of the Tx payload.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetTransmitLength(uint8_t Length)
{
    BC3603_WriteRegister(TX_DATA_LENG_REGS,Length);
}
/***********************************************************************************************
 * @brief Set Rx payload length
 * @param Length: specify data length of the Rx payload.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetReceiverLength(uint8_t Length)
{
    BC3603_WriteRegister(RX_DATA_LENG_REGS,Length);
}
/***********************************************************************************************
 * @brief Get Receiver payload length
 * @param None
 * @retval The value of the Payload length.
 ***********************************************************************************************/
uint8_t	BC3603_GetReceiverLength(void)
{
    return(BC3603_ReadRegister(RX_DATA_LENG_REGS));
}
/***********************************************************************************************
 * @brief Set Tx packet ID
 * @param PID: packet ID
 * @retval None
 ***********************************************************************************************/
void BC3603_SetPacketID(uint8_t PID)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(PACKET_CTL2_REGS);
    reg &= (uint8_t)~PKT_TXPID_MASK;
    reg |= ((PID << 6) & PKT_TXPID_MASK);
    BC3603_WriteRegister(PACKET_CTL2_REGS,reg);
}
/***********************************************************************************************
 * @brief Return the ID of Rx packet ID
 * @param None
 * @retval The value of the Packet ID.
 ***********************************************************************************************/
uint8_t BC3603_GetPacketID(void)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(TRX_MODE_DELAY_REGS);
    reg &= PKT_RXPID_MASK;
    reg >>= 6;
    return( reg );
}
/***********************************************************************************************
 * @brief Set the address of Head address
 * @param PLHA : head address
 * @retval None
 ***********************************************************************************************/
void BC3603_SetHeaderAddress(uint16_t PLHA)
{
    uint8_t		reg;

    reg = BC3603_ReadRegister(PACKET_CTL3_REGS);
    BC3603_WriteRegister(HEADER_ADDR0_REGS,PLHA & 0x3F);
    if(reg & PKT_PLHLEN)
    {
        BC3603_WriteRegister(HEADER_ADDR1_REGS,(PLHA >> 6) & 0xFF);
    }
}
/***********************************************************************************************
 * @brief Return the address of receiver head address
 * @param None
 * @retval The value of the Head address.
 ***********************************************************************************************/
uint16_t BC3603_GetHeaderAddress(void)
{
    uint16_t	PLHA = 0;

    if(BC3603_ReadRegister(PACKET_CTL3_REGS) & PKT_PLHLEN)
    {
        PLHA = BC3603_ReadRegister(HEADER_ADDR1_REGS);
    }

    PLHA = (PLHA << 6) | (BC3603_ReadRegister(HEADER_ADDR0_REGS) & 0x3F);

    return(PLHA);
}
/***********************************************************************************************
 * @brief Return the status of RF operation state
 * @param None
 * @retval The value of the operation state.
 *     @arg	OMST_DEEPSLEEP		: deep sleep mode
 *				OMST_IDLE			: idle mode
 *				OMST_LIGHTSLEEP	: light sleep mode
 *				OMST_STANDBY		: standby mode
 *				OMST_TX				: Tx mode
 *				OMST_RX				: Rx mode
 *				OMST_CALIBRATION	: calibration mode
 ***********************************************************************************************/
RF_OMST_Enum BC3603_GetOperationState(void)
{
    uint8_t reg;

    reg = BC3603_ReadRegister(OMODE_STATUS_REGS);
    return( (RF_OMST_Enum)(reg & STA_OMST_MASK));
}
/***********************************************************************************************
 * @brief Check whether the carrier detect flag has been set or not.
 * @param None
 * @retval BC3603_SET or BC3603_RESET
 ***********************************************************************************************/
BC3603_FlagStatus BC3603_GetCarrierDetectStatus(void)
{
    if((BC3603_ReadRegister(OMODE_STATUS_REGS) & STA_CD_FLAG) != BC3603_RESET)
    {
        return(BC3603_SET);
    }
    else
    {
        return(BC3603_RESET);
    }
}
/***********************************************************************************************
 * @brief Set the value of carrier detect threshold.
 * @param THold: specify the value of carrier detect threshold.
 * @retval None
 ***********************************************************************************************/
void BC3603_SetCarrierDetectThreshold(uint8_t THold)
{
    uint8_t	reg;

    if(THold < 75)
    {
        reg = 0;
    }
    else
    {
        reg = (THold - 75)/2;	   /* RSSI threshold = ((CTHD * 2)+1)+74 */
    }
    BC3603_WriteRegister(RSSI_CTL_REGS,reg);
}
/***********************************************************************************************
 * @brief Return the value of RF RSSI
 * @param None
 * @retval The value of RSSI
 ***********************************************************************************************/
uint8_t BC3603_GetRSSIValue(void)
{
    return (BC3603_ReadRegister(RSSI_NEGDB_REGS));
}
/***********************************************************************************************
 * @brief Return the value of RF RSSI(syncword ok)
 * @param None
 * @retval The value of RSSI
 ***********************************************************************************************/
uint8_t BC3603_GetSYNCRSSIValue(void)
{
    return (BC3603_ReadRegister(RSSI_SYNC_OK_REGS));
}
/***********************************************************************************************
 * @brief Set the time unit of ATRRXAP/ATRRXEP/ARKRXAP
 * @param Unit : Selection of time unit.
 *   This parameter can be one of below:
 *     @arg ATRTU_250US	: time unit:250us
 *				ATRTU_1MS	: time unit:1ms
 * @retval None
 ***********************************************************************************************/
void BC3603_ATRKTimeUnit(RF_ATRTU_Enum Unit)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(ATR_CONTROL_REGS);
    if(Unit != ATRTU_250US)
    {
        reg |= (uint8_t)ATR_TUNIT;
    }
    else
    {
        reg &= (uint8_t)~ATR_TUNIT;
    }
    BC3603_WriteRegister(ATR_CONTROL_REGS,reg);
}
/***********************************************************************************************
 * @brief Configure the parameter of ATR function
 * @param ATR_InitStruct : pointer to a ATR_InitTypeDef structure.
 * @retval None
 ***********************************************************************************************/
void BC3603_ATRConfig(ATR_InitTypeDef *ATR_InitStruct)
{
    uint8_t		reg;
    float	Unit;
    uint32_t 	cycle;

    reg = BC3603_ReadRegister(ATR_CONTROL_REGS);
    reg &= (uint8_t)~(ATR_MODE_MASK+ATR_CTMS+ATR_CLKSS+ATR_CLKDIV_MASK);
    reg |= (ATR_InitStruct->Prescaler << 6) + 			/* ATRCLK_DIV */
           (ATR_InitStruct->ClockSource << 5) +        /* ATRCLKS */
           (ATR_InitStruct->Mode << 1);                /* ATRCTM & ATRM */
    BC3603_WriteRegister(ATR_CONTROL_REGS,reg);
    /*ATR wake up delay time */
    reg = BC3603_ReadRegister(ARK_CONTROL_REGS);
    reg &= (uint8_t)~ATR_WDLY_MASK;
    reg |= (ATR_InitStruct->WakeUpDelayTime << 1) & ATR_WDLY_MASK;
    BC3603_WriteRegister(ARK_CONTROL_REGS,reg);
    /* ATR cycle counter */
    if(ATR_InitStruct->ClockSource == ATRCKS_EXTERAL)
    {
        Unit = 1000000.0/(float)ATR_InitStruct->ClockFrequency;
    }
    else
    {
        Unit = 1000000.0/LIRC_FREQUENCY;
    }
    switch((uint8_t)ATR_InitStruct->Prescaler)
    {
    /* clock source divide 4 */
    case ATRCK_DIV4:
        Unit *= 4;
        break;
    /* clock source divide 8 */
    case ATRCK_DIV8:
        Unit *= 8;
        break;
    /* clock source divide 16 */
    case ATRCK_DIV16:
        Unit *= 16;
        break;
    }
    cycle = BC3603_ATRConvertTimeUnit(ATR_InitStruct->CycleCounter,ATR_CYCLE_MAX,Unit);
    BC3603_WriteRegister(ATR_CYCLE_L_REGS,cycle & 0xFF);
    BC3603_WriteRegister(ATR_CYCLE_H_REGS,(cycle >> 8) & 0xFF);
}
/***********************************************************************************************
 * @brief Enable or Disable ATR function
 * @param NewState: Enable or Disable
 * @retval None
 ***********************************************************************************************/
void BC3603_ATRControl(BC3603_ControlStatus NewState)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(ATR_CONTROL_REGS);

    if(NewState != BC3603_DISABLE)
    {
        reg |= (uint8_t)ATR_ENABLE;
    }
    else
    {
        reg &= (uint8_t)~(ATR_ENABLE|ATR_CTMS);
    }
    BC3603_WriteRegister(ATR_CONTROL_REGS,reg);
}
/***********************************************************************************************
 * @brief Configure the parameter of WOR Rx period function.
* @param RxActive: Selection of WOR Rx active period time(unit:us).
* @param RxExtend: Selection of WOR Rx extend period time(unit:us).
 * @retval None
 ***********************************************************************************************/
void BC3603_SetWORPeriod(uint32_t RxActive,uint32_t RxExtend)
{
    uint8_t		reg;
    float	Unit;

    reg = BC3603_ReadRegister(ATR_CONTROL_REGS);
    Unit = (reg & ATRTU_250US)	? ATR_UNIT_1MS:ATR_UNIT_250US;

    /* WOR Rx active period */
    RxActive = BC3603_ATRConvertTimeUnit(RxActive,ATR_RXACTIVE_MAX,Unit);
    if(RxActive > 0) RxActive--;
    BC3603_WriteRegister(ATR_ACTIVE_L_REGS,RxActive & 0xFF);
    BC3603_WriteRegister(ATR_ACTIVE_H_REGS,(RxActive >> 8) & 0xFF);
    /* WOR Rx extend period */
    RxExtend = BC3603_ATRConvertTimeUnit(RxExtend,ATR_RXEXTEND_MAX,Unit);
    if(RxExtend > 0) RxExtend--;
    BC3603_WriteRegister(ATR_EACTIVE_L_REGS,RxExtend & 0xFF);
    BC3603_WriteRegister(ATR_EACTIVE_H_REGS,(RxExtend >> 8) & 0xFF);
}
/***********************************************************************************************
 * @brief Return the value of ATR cycle counter
 * @param None
 * @retval The value of cycle counter
 ***********************************************************************************************/
uint16_t BC3603_GetATRCycleValue(void)
{
    uint16_t	reg;
    reg = BC3603_ReadRegister(ATR_CYCLE_L_REGS);
    reg += (BC3603_ReadRegister(ATR_CYCLE_H_REGS) << 8);
    return(reg);
}
/***********************************************************************************************
 * @brief Return the value of ATR cycle counter
 * @param None
 * @retval The value of cycle counter
 ***********************************************************************************************/
uint16_t BC3603_GetATRCycleCounter(void)
{
    uint16_t	reg;
    reg = BC3603_ReadRegister(ATRCT_L_REGS);
    reg += (BC3603_ReadRegister(ATRCT_H_REGS) << 8);
    return(reg);
}
/***********************************************************************************************
 * @brief Update ATR cycle counter
 * @param NewCounter: new cycle counter
 * @retval None
 ***********************************************************************************************/
void BC3603_UpdateATRCycleCounter(uint16_t NewCounter)
{
    BC3603_WriteRegister(ATRCT_L_REGS,NewCounter & 0xFF);
    BC3603_WriteRegister(ATRCT_H_REGS,(NewCounter >> 8) & 0xFF);
}
/***********************************************************************************************
 * @brief Enable or Disable ARK function
 * @param NewState: BC3603_ENABLE or BC3603_DISABLE.
 * @retval None
 ***********************************************************************************************/
void BC3603_ARKControl(BC3603_ControlStatus NewState)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(ARK_CONTROL_REGS);
    if(NewState != BC3603_DISABLE)
    {
        reg |= ARK_ENABLE;
    }
    else
    {
        reg &= (uint8_t)~ARK_ENABLE;
    }
    BC3603_WriteRegister(ARK_CONTROL_REGS,reg);
}
/***********************************************************************************************
 * @brief Configure the parameter of ARK function.
 * @param Repeat: Selection of Auto Retransmit Count 0~15.
 * @param Period: Selection of Auto Retransmit Delay Time
 * @retval None
 ***********************************************************************************************/
void BC3603_ARKRepeatPeriod(uint8_t Repeat,uint32_t Period)
{
    uint8_t		reg;
    float	Unit;

    reg = BC3603_ReadRegister(ATR_CONTROL_REGS);
    Unit = (reg & ATRTU_250US)	? ATR_UNIT_1MS:ATR_UNIT_250US;

    reg = BC3603_ReadRegister(ARK_CONTROL_REGS);
    reg &= (uint8_t)~(ARK_RPNM_MASK);
    reg |= (Repeat << 4) & ARK_RPNM_MASK;
    BC3603_WriteRegister(ARK_CONTROL_REGS,reg);
    Period = BC3603_ATRConvertTimeUnit(Period,ARK_RXACTIVE_MAX,Unit);
    if(Period > 0) Period--;
    BC3603_WriteRegister(ARK_ACTIVE_REGS,Period);
}
/***********************************************************************************************
 * @brief Convert period width to time unit.
 * @param Period: Selection of period width
 * @param Max: Selection of convert max number
 * @param Unit: Selection of convert time unit
 * @retval Convert value
 ***********************************************************************************************/
uint32_t BC3603_ATRConvertTimeUnit(uint32_t Period,uint32_t Max,float Unit)
{
    float prd;

    prd = Period;									/* convert to float */
    prd /= Unit;
    if(prd > Max) prd = Max;					/* check max */
    Period = prd;
    if((prd - Period) != 0) Period++;      /* Check the remainder */
    return(Period);
}
/***********************************************************************************************
 * @brief Configure the parameter of OOK duty tune function.
 * @param ODTE: Selection of OOK duty tune(BC3603_ENABLE or BC3603_DISABLE).
 * @param ODTP: Selection of OOK duty tune polarity(BC3603_RESET or BC3603_SET).
 * @param ODTS: Selection of OOK duty tune time(2us~32us).
 * @retval None
 ***********************************************************************************************/
void BC3603_OOKDutyTune(BC3603_ControlStatus ODTE,BC3603_FlagStatus ODTP, uint8_t ODTS)
{
    uint8_t	reg;

    reg = BC3603_ReadRegister(PACKET_CTL15_REGS);
    reg &= ~(OOKDT_ENABLE | OOKDT_POLARITY | OOKDT_TUNE_MASK);
    if(ODTE == BC3603_ENABLE) reg |= OOKDT_ENABLE;
    if(ODTP == BC3603_SET) reg |= OOKDT_POLARITY;
    if(ODTS > 32) ODTS = 32;
    ODTS = (ODTS / 2) - 1;
    reg |= (ODTS << 2) & OOKDT_TUNE_MASK;
    BC3603_WriteRegister(PACKET_CTL15_REGS,reg);
}
/***********************************************************************************************
 * @brief Enable VCO calibration and wait completion.
 * @param None
 * @retval BC3603_SUCCESS or BC3603_ERROR
 ***********************************************************************************************/
BC3603_ErrStatus BC3603_VCOAutoCalibration(void)
{
    uint32_t	ReadyCnt = 0;

    BC3603_WriteRegister(OPERATION_CTL_REGS,BC3603_ReadRegister(OPERATION_CTL_REGS) | OM_ACAL_EN);
    while((BC3603_ReadRegister(OPERATION_CTL_REGS) & OM_ACAL_EN) == OM_ACAL_EN)
    {
        if(++ReadyCnt >= VCAL_READY_TIME) return(BC3603_ERROR);
    }
    return(BC3603_SUCCESS);
}
/***********************************************************************************************
 * @brief Enable LIRC calibration and wait completion..
 * @param None
 * @retval BC3603_SUCCESS or BC3603_ERROR
 ***********************************************************************************************/
BC3603_ErrStatus BC3603_LIRCCalibration(void)
{
    uint32_t	ReadyCnt = 0;

    BC3603_WriteRegister(LIRC_CTL_REGS,BC3603_ReadRegister(LIRC_CTL_REGS) | LIRC_CAL_EN);
    while((BC3603_ReadRegister(LIRC_CTL_REGS) & LIRC_CAL_EN) == LIRC_CAL_EN)
    {
        if(++ReadyCnt >= LCAL_READY_TIME) return(BC3603_ERROR);
    }
    return(BC3603_SUCCESS);
}

/**
  * @}
  */
