1724 lines
48 KiB
C
1724 lines
48 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
***************************************************************************/
|
|
#include "bb_rf_cfg.h"
|
|
#include "bb_cpu_fsm.h"
|
|
#include "iot_config.h"
|
|
#include "iot_utils.h"
|
|
#include "os_types.h"
|
|
#include "plc_const.h"
|
|
#include "plc_protocol.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_oem_api.h"
|
|
#include "rf_hw_tonemap.h"
|
|
#include "bb_rf_hw_tbl.h"
|
|
#include "hw_reg_api.h"
|
|
#include "rfplc_reg_base.h"
|
|
#include "rfplc_general_reg.h"
|
|
#include "wphy_reg.h"
|
|
#include "rf_mac_reg.h"
|
|
#include "iot_clock.h"
|
|
#include "phy_rf_chn.h"
|
|
#include "rf_spi_api.h"
|
|
#include "math_log10.h"
|
|
#include "iot_io.h"
|
|
#include "mac_rf_common_hw.h"
|
|
#include "plc_cert_test.h"
|
|
#include "hw_war.h"
|
|
#include "bb_cpu_utils.h"
|
|
#include "gp_timer.h"
|
|
#include "iot_clock.h"
|
|
#include "bb_cpu_config.h"
|
|
#include "bb_init.h"
|
|
|
|
static uint32_t g_bbcpu_rf_ver = RF_VER_INVAILD;
|
|
|
|
#if RF_VER1_2022_8_15
|
|
/* tx global variable name */
|
|
static uint32_t tx_switch_step1_us = 0;
|
|
static uint32_t tx_switch_step2_us = 0;
|
|
static uint32_t tx_step2_to_aotx_us = 0;
|
|
/* rx global variable name */
|
|
static uint32_t rx_switch_step1_us = 0;
|
|
#endif
|
|
|
|
static void bb_rf_cfg_base_phr_info(bb_rf_hw_info_t *rf_phr)
|
|
{
|
|
IOT_ASSERT(rf_phr);
|
|
WPHY_WRITE_REG(WPHY_PHR_BASIC_CFG_ADDR, rf_phr->codec_cfg);
|
|
|
|
WPHY_WRITE_REG(WPHY_PHR_CHAN_INTL_ADDR, rf_phr->chan_intl);
|
|
|
|
WPHY_WRITE_REG(WPHY_PHR_ROBO_INTL0_ADDR, rf_phr->robo_intl0);
|
|
|
|
WPHY_WRITE_REG(WPHY_PHR_ROBO_INTL1_ADDR, rf_phr->robo_intl1);
|
|
|
|
WPHY_WRITE_REG(WPHY_PHR_ROBO_INTL2_ADDR, rf_phr->robo_intl2);
|
|
}
|
|
|
|
void bb_rf_cfg_tx_phr_info(bb_rf_hw_info_t *rf_phr)
|
|
{
|
|
IOT_ASSERT(rf_phr);
|
|
/* config base phy header info */
|
|
bb_rf_cfg_base_phr_info(rf_phr);
|
|
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLTX_SIG_INFO_ADDR);
|
|
REG_FIELD_SET(TX_SIG_INFO, tmp, rf_phr->mcs_id);
|
|
WPHY_WRITE_REG(WPHY_MLTX_SIG_INFO_ADDR, tmp);
|
|
|
|
WPHY_WRITE_REG(WPHY_MLTX_PHR_CFG_ADDR, rf_phr->modem_cfg);
|
|
}
|
|
|
|
void bb_rf_cfg_rx_phr_info(bb_rf_hw_info_t *rf_phr)
|
|
{
|
|
IOT_ASSERT(rf_phr);
|
|
/* config base phy header info */
|
|
bb_rf_cfg_base_phr_info(rf_phr);
|
|
|
|
WPHY_WRITE_REG(WPHY_MLRX_PHR_CFG_ADDR, rf_phr->modem_cfg);
|
|
}
|
|
|
|
static void bb_rf_cfg_base_pld_info(bb_rf_hw_info_t *rf_pld, uint32_t pb_num)
|
|
{
|
|
IOT_ASSERT(rf_pld);
|
|
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_PLD_PB_NUM_ADDR);
|
|
REG_FIELD_SET(PLD_PB_NUM, tmp, pb_num);
|
|
WPHY_WRITE_REG(WPHY_PLD_PB_NUM_ADDR, tmp);
|
|
|
|
WPHY_WRITE_REG(WPHY_PLD_BASIC_CFG_ADDR, rf_pld->codec_cfg);
|
|
|
|
WPHY_WRITE_REG(WPHY_PLD_CHAN_INTL_ADDR, rf_pld->chan_intl);
|
|
|
|
WPHY_WRITE_REG(WPHY_PLD_ROBO_INTL0_ADDR, rf_pld->robo_intl0);
|
|
|
|
WPHY_WRITE_REG(WPHY_PLD_ROBO_INTL1_ADDR, rf_pld->robo_intl1);
|
|
|
|
WPHY_WRITE_REG(WPHY_PLD_ROBO_INTL2_ADDR, rf_pld->robo_intl2);
|
|
}
|
|
|
|
void bb_rf_cfg_tx_pld_info(bb_rf_hw_info_t *rf_pld, uint32_t pb_num)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
if (pb_num) {
|
|
IOT_ASSERT(rf_pld);
|
|
bb_rf_cfg_base_pld_info(rf_pld, pb_num);
|
|
WPHY_WRITE_REG(WPHY_MLTX_PLD_CFG_ADDR, rf_pld->modem_cfg);
|
|
if (pb_num != 1) {
|
|
tmp = WPHY_READ_REG(WPHY_MLTX_PLD_CFG_ADDR);
|
|
REG_FIELD_SET(TX_PLD_SYMB_NUM, tmp, rf_pld->fec_nsymb * pb_num);
|
|
WPHY_WRITE_REG(WPHY_MLTX_PLD_CFG_ADDR, tmp);
|
|
}
|
|
} else {
|
|
WPHY_WRITE_REG(WPHY_MLTX_PLD_CFG_ADDR, 0);
|
|
WPHY_WRITE_REG(WPHY_PLD_PB_NUM_ADDR, 0);
|
|
}
|
|
}
|
|
|
|
void bb_rf_cfg_rx_pld_info(bb_rf_hw_info_t *rf_pld, uint32_t pb_num)
|
|
{
|
|
IOT_ASSERT(rf_pld);
|
|
uint32_t tmp;
|
|
bb_rf_cfg_base_pld_info(rf_pld, pb_num);
|
|
|
|
WPHY_WRITE_REG(WPHY_MLRX_PLD_CFG_ADDR, rf_pld->modem_cfg);
|
|
|
|
if (pb_num != 1) {
|
|
tmp = WPHY_READ_REG(WPHY_MLRX_PLD_CFG_ADDR);
|
|
REG_FIELD_SET(RX_PLD_SYMB_NUM, tmp, rf_pld->fec_nsymb * pb_num);
|
|
WPHY_WRITE_REG(WPHY_MLRX_PLD_CFG_ADDR, tmp);
|
|
}
|
|
}
|
|
|
|
void bb_rf_set_tx_phr(uint32_t *phr)
|
|
{
|
|
IOT_ASSERT(phr);
|
|
WPHY_WRITE_REG(WPHY_PHR_TX_INFO0_ADDR, phr[0]);
|
|
WPHY_WRITE_REG(WPHY_PHR_TX_INFO1_ADDR, phr[1]);
|
|
WPHY_WRITE_REG(WPHY_PHR_TX_INFO2_ADDR, phr[2]);
|
|
WPHY_WRITE_REG(WPHY_PHR_TX_INFO3_ADDR, phr[3]);
|
|
}
|
|
|
|
void bb_rf_get_tx_phr(uint32_t *phr)
|
|
{
|
|
*(phr + 0) = WPHY_READ_REG(WPHY_PHR_TX_INFO0_ADDR);
|
|
*(phr + 1) = WPHY_READ_REG(WPHY_PHR_TX_INFO1_ADDR);
|
|
*(phr + 2) = WPHY_READ_REG(WPHY_PHR_TX_INFO2_ADDR);
|
|
*(phr + 3) = WPHY_READ_REG(WPHY_PHR_TX_INFO3_ADDR);
|
|
}
|
|
|
|
void bb_rf_get_rx_phr(uint32_t *phr)
|
|
{
|
|
*(phr + 0) = WPHY_READ_REG(WPHY_PHR_RX_INFO0_ADDR);
|
|
*(phr + 1) = WPHY_READ_REG(WPHY_PHR_RX_INFO1_ADDR);
|
|
*(phr + 2) = WPHY_READ_REG(WPHY_PHR_RX_INFO2_ADDR);
|
|
*(phr + 3) = WPHY_READ_REG(WPHY_PHR_RX_INFO3_ADDR);
|
|
}
|
|
|
|
void bb_rf_set_crc32_en(uint32_t enable)
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_CRC32_EN_ADDR);
|
|
REG_FIELD_SET(CRC32_EN, tmp, enable);
|
|
WPHY_WRITE_REG(WPHY_CRC32_EN_ADDR, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_pld_crc32_err()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_DEC_CRC_RDY_ADDR);
|
|
return REG_FIELD_GET(PLD_CRC32_ERR, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_pld_crc24_err()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_DEC_CRC_RDY_ADDR);
|
|
return REG_FIELD_GET(PLD_CRC24_ERR, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_pld_crc_rdy()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_DEC_CRC_RDY_ADDR);
|
|
return REG_FIELD_GET(PLD_RDY, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_phr_crc24_err()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_DEC_CRC_RDY_ADDR);
|
|
return REG_FIELD_GET(PHR_CRC24_ERR, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_phr_crc_rdy()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_DEC_CRC_RDY_ADDR);
|
|
return REG_FIELD_GET(PHR_RDY, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_rx_sig_info()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLRX_SIG_INFO_ADDR);
|
|
return REG_FIELD_GET(RX_SIG_INFO, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_rx_sig_is_ready()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLRX_SIG_INFO_ADDR);
|
|
return REG_FIELD_GET(RX_SIG_RDY, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_rx_sig_is_err()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLRX_SIG_INFO_ADDR);
|
|
return REG_FIELD_GET(RX_SIG_ERR, tmp);
|
|
}
|
|
|
|
void bb_rf_set_rx_state_cont(uint32_t state_cont)
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLRX_STATE_CTRL_ADDR);
|
|
REG_FIELD_SET(RX_STATE_CONT, tmp, state_cont);
|
|
WPHY_WRITE_REG(WPHY_MLRX_STATE_CTRL_ADDR, tmp);
|
|
}
|
|
|
|
void bb_rf_set_dec_cont(uint32_t state_cont)
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_DEC_CTRL_ADDR);
|
|
REG_FIELD_SET(DEC_CONT, tmp, state_cont);
|
|
WPHY_WRITE_REG(WPHY_DEC_CTRL_ADDR, tmp);
|
|
}
|
|
|
|
void bb_rf_clear_tx_info()
|
|
{
|
|
WPHY_WRITE_REG(WPHY_AHB_IF_CFG_ADDR, 0x12020);
|
|
}
|
|
|
|
void bb_rf_clear_rx_info()
|
|
{
|
|
WPHY_WRITE_REG(WPHY_AHB_IF_CFG_ADDR, 0x22020);
|
|
}
|
|
|
|
void bb_rf_tx_timer_en(uint32_t enable)
|
|
{
|
|
if (RF_VER_1 == bb_rf_get_ver()) {
|
|
#if RF_VER1_2022_8_15
|
|
if (enable) {
|
|
/* 100us between bb_rf_tx_switch_step2 and bb_rf_tx_timer_en */
|
|
uint32_t tx_dlt = gp_timer_get_current_val(0) - tx_switch_step2_us;
|
|
if (tx_dlt < tx_step2_to_aotx_us) {
|
|
tx_dlt = tx_step2_to_aotx_us - tx_dlt;
|
|
iot_delay_us(tx_dlt);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
uint32_t tmp;
|
|
tmp = WPHY_READ_REG(WPHY_MLTX_CTRL_ADDR);
|
|
REG_FIELD_SET(SOTX_TTMR_EN, tmp, enable);
|
|
REG_FIELD_SET(AOTX_TTMR_EN, tmp, enable);
|
|
WPHY_WRITE_REG(WPHY_MLTX_CTRL_ADDR, tmp);
|
|
if (!enable) {
|
|
tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(SOTX_TTMR_CLR, tmp, 1);
|
|
REG_FIELD_SET(AOTX_TTMR_CLR, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
}
|
|
}
|
|
|
|
void bb_rf_rx_timer_en(uint32_t enable)
|
|
{
|
|
uint32_t tmp;
|
|
tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(AOCS_TTMR_EN, tmp, enable);
|
|
REG_FIELD_SET(SOCS_TTMR_EN, tmp, enable);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
if (!enable) {
|
|
tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(AOCS_TTMR_CLR, tmp, 1);
|
|
REG_FIELD_SET(SOCS_TTMR_CLR, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
}
|
|
}
|
|
|
|
void bb_rf_stop_listen_timer_en(uint32_t enable)
|
|
{
|
|
uint32_t tmp;
|
|
tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(EOCS_TTMR_EN, tmp, enable);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
if (!enable) {
|
|
tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(EOCS_TTMR_CLR, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
}
|
|
}
|
|
|
|
void bb_rf_debug_tx_immd()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLTX_CTRL_ADDR);
|
|
REG_FIELD_SET(AOTX_IMMD, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLTX_CTRL_ADDR, tmp);
|
|
iot_delay_us(50);
|
|
tmp = WPHY_READ_REG(WPHY_MLTX_CTRL_ADDR);
|
|
REG_FIELD_SET(SOTX_IMMD, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLTX_CTRL_ADDR, tmp);
|
|
}
|
|
|
|
void bb_rf_debug_rx_immd()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(AOCS_IMMD, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
iot_delay_us(50);
|
|
tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(SOCS_IMMD, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
}
|
|
|
|
void bb_rf_debug_stop_listen_immd()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLRX_CTRL_ADDR);
|
|
REG_FIELD_SET(EOCS_IMMD, tmp, 1);
|
|
WPHY_WRITE_REG(WPHY_MLRX_CTRL_ADDR, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_rx_is_busy()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLRX_STAT_ADDR);
|
|
return REG_FIELD_GET(ARX_BUSY, tmp);
|
|
}
|
|
|
|
uint32_t bb_rf_get_tx_is_busy()
|
|
{
|
|
uint32_t tmp = WPHY_READ_REG(WPHY_MLTX_STAT_ADDR);
|
|
return REG_FIELD_GET(ATX_BUSY, tmp);
|
|
}
|
|
|
|
void bb_rf_set_fchz(uint32_t fchz)
|
|
{
|
|
uint32_t mode, reg, val;
|
|
float tmp;
|
|
if (fchz < 400000000) {
|
|
mode = 4;
|
|
} else {
|
|
reg = rf_spi_read(17);
|
|
mode = (reg >> 13);
|
|
}
|
|
|
|
/* val = fchz * mode / 1000 * 335.54432; */
|
|
tmp = fchz * mode;
|
|
tmp = tmp/1000;
|
|
tmp = tmp * 335.54432;
|
|
val = (uint32_t)tmp;
|
|
|
|
rf_spi_write(17, (mode << 13) | ((val >> 16) & 0x1fff));
|
|
rf_spi_write(18, val & 0xffff);
|
|
|
|
return;
|
|
}
|
|
|
|
uint32_t bb_rf_get_fchz(void)
|
|
{
|
|
uint32_t fchz;
|
|
uint16_t reg;
|
|
uint8_t mode;
|
|
uint32_t val;
|
|
float tmp;
|
|
|
|
reg = rf_spi_read(17);
|
|
mode = (reg >> 13);
|
|
|
|
val = (reg & 0x1fff) << 16;
|
|
reg = rf_spi_read(18);
|
|
val |= reg;
|
|
|
|
/* fchz = (val / 335544.32 / mode * 1000000); */
|
|
tmp = (float)val;
|
|
tmp = val / 335544.32;
|
|
tmp = tmp / mode;
|
|
tmp = tmp * 1000000;
|
|
fchz = (uint32_t)tmp;
|
|
|
|
return fchz;
|
|
}
|
|
|
|
#if HPLC_BBCPU_CALC_SNR_RSSI
|
|
|
|
static float bb_rf_get_snr(uint32_t option, uint16_t *raw_snr)
|
|
{
|
|
float snr;
|
|
float rdata = (float)WPHY_INIT_READ_REG(0xf0102c);
|
|
float rawdata = (1<<16)*1.0/(rdata*1.0/((option==3) ? 36 : 96));
|
|
float tmp = rawdata * 10 + 0.5;
|
|
*raw_snr = (uint16_t)(min(0xFFFF, (uint32_t)tmp));
|
|
if (rawdata >= 1) {
|
|
snr = 10*mlog10(rawdata);
|
|
} else {
|
|
snr = 10*na_mlog10(rawdata);
|
|
}
|
|
|
|
return snr;
|
|
}
|
|
|
|
float bb_rf_get_rssi()
|
|
{
|
|
float rdata1 = (float)WPHY_INIT_READ_REG(0xf01330);
|
|
uint32_t rdata2 = WPHY_INIT_READ_REG(0xf01328);
|
|
float rssi = 10*mlog10(rdata1*1.0) - 70 - (rdata2 & 0xFF) -
|
|
((rdata2 >> 8) & 0xFF);
|
|
return rssi;
|
|
}
|
|
|
|
void bb_rf_get_snr_rssi(uint32_t option, int8_t *snr, int8_t *rssi,
|
|
uint8_t *gain, uint16_t *raw_snr)
|
|
{
|
|
/* X can be got by calibration */
|
|
#define X_CALIBRATION 60
|
|
float snr_tmp = bb_rf_get_snr(option, raw_snr);
|
|
|
|
float rdata1 = (float)WPHY_INIT_READ_REG(0xf01330);
|
|
uint32_t rdata2 = WPHY_INIT_READ_REG(0xf01328);
|
|
float rssi_tmp = 10*mlog10(rdata1*1.0) - X_CALIBRATION - (rdata2 & 0xFF) -
|
|
((rdata2 >> 8) & 0xFF) + ((snr_tmp < 0) ? snr_tmp: 0);
|
|
/* 13 - 74 */
|
|
*gain = (uint8_t)((rdata2 & 0xFF) + ((rdata2 >> 8) & 0xFF));
|
|
*snr = (int8_t)snr_tmp;
|
|
*rssi = (int8_t)rssi_tmp;
|
|
}
|
|
|
|
#else /* HPLC_BBCPU_CALC_SNR_RSSI */
|
|
|
|
uint32_t bb_rf_get_raw_snr_rssi_reg1()
|
|
{
|
|
/* snr/rssi/rxgain raw data register 1 */
|
|
return WPHY_INIT_READ_REG(0xf0102c);
|
|
}
|
|
|
|
uint32_t bb_rf_get_raw_snr_rssi_reg2()
|
|
{
|
|
/* snr/rssi/rxgain raw data register 2 */
|
|
return WPHY_INIT_READ_REG(0xf01330);
|
|
}
|
|
|
|
uint32_t bb_rf_get_raw_snr_rssi_reg3()
|
|
{
|
|
/* snr/rssi/rxgain raw data register 3 */
|
|
return WPHY_INIT_READ_REG(0xf01328);
|
|
}
|
|
|
|
#endif /* HPLC_BBCPU_CALC_SNR_RSSI */
|
|
|
|
uint8_t bb_rf_get_cur_gain()
|
|
{
|
|
uint32_t rdata2 = WPHY_INIT_READ_REG(0xf01328);
|
|
uint8_t gain = (uint8_t)((rdata2 & 0xFF) + ((rdata2 >> 8) & 0xFF));
|
|
return gain;
|
|
}
|
|
|
|
int32_t bb_rf_get_evaluate_ppm_hz()
|
|
{
|
|
uint32_t tmp = WPHY_INIT_READ_REG(0xf01448);
|
|
int32_t ppm_hz;
|
|
if (tmp & 0x800000) {
|
|
ppm_hz = (int32_t)(0xFF000000 | (tmp & 0xFFFFFF));
|
|
} else {
|
|
ppm_hz = (int32_t)(tmp & 0xFFFFFF);
|
|
}
|
|
return ppm_hz;
|
|
}
|
|
|
|
uint32_t bb_rf_get_interweave_offset(uint32_t rate, uint8_t blkz)
|
|
{
|
|
switch (rate) {
|
|
case RF_CODING_RATE_1_2:
|
|
{
|
|
switch (blkz) {
|
|
case BLOCK_SIZE_0:
|
|
return RF_INTERWEAVE_OFFSET_16;
|
|
case BLOCK_SIZE_1:
|
|
return RF_INTERWEAVE_OFFSET_40;
|
|
case BLOCK_SIZE_2:
|
|
return RF_INTERWEAVE_OFFSET_72;
|
|
case BLOCK_SIZE_3:
|
|
return RF_INTERWEAVE_OFFSET_136;
|
|
case BLOCK_SIZE_4:
|
|
return RF_INTERWEAVE_OFFSET_264;
|
|
case BLOCK_SIZE_5:
|
|
return RF_INTERWEAVE_OFFSET_520;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case RF_CODING_RATE_4_5:
|
|
{
|
|
switch (blkz) {
|
|
case BLOCK_SIZE_0:
|
|
return RF_INTERWEAVE_OFFSET_4;
|
|
case BLOCK_SIZE_1:
|
|
return RF_INTERWEAVE_OFFSET_10;
|
|
case BLOCK_SIZE_2:
|
|
return RF_INTERWEAVE_OFFSET_18;
|
|
case BLOCK_SIZE_3:
|
|
return RF_INTERWEAVE_OFFSET_34;
|
|
case BLOCK_SIZE_4:
|
|
return RF_INTERWEAVE_OFFSET_66;
|
|
case BLOCK_SIZE_5:
|
|
return RF_INTERWEAVE_OFFSET_130;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t bb_rf_get_interweave_step(uint32_t rate, uint8_t blkz)
|
|
{
|
|
switch (rate) {
|
|
case RF_CODING_RATE_1_2:
|
|
{
|
|
switch (blkz) {
|
|
case BLOCK_SIZE_0:
|
|
case BLOCK_SIZE_1:
|
|
return RF_INTERWEAVE_STEP_4;
|
|
case BLOCK_SIZE_2:
|
|
case BLOCK_SIZE_3:
|
|
case BLOCK_SIZE_4:
|
|
case BLOCK_SIZE_5:
|
|
return RF_INTERWEAVE_STEP_16;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case RF_CODING_RATE_4_5:
|
|
{
|
|
switch (blkz) {
|
|
case BLOCK_SIZE_0:
|
|
return RF_INTERWEAVE_STEP_4;
|
|
case BLOCK_SIZE_1:
|
|
return RF_INTERWEAVE_STEP_5;
|
|
case BLOCK_SIZE_2:
|
|
return RF_INTERWEAVE_STEP_18;
|
|
case BLOCK_SIZE_3:
|
|
return RF_INTERWEAVE_STEP_17;
|
|
case BLOCK_SIZE_4:
|
|
return RF_INTERWEAVE_STEP_12;
|
|
case BLOCK_SIZE_5:
|
|
return RF_INTERWEAVE_STEP_13;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void bb_rf_write_data_to_bb(uint32_t pb_size, uint8_t *buf)
|
|
{
|
|
uint32_t i, j;
|
|
uint32_t tmp, rawdata, real_num, pb_size_word, num;
|
|
IOT_ASSERT(buf && (((uint32_t)buf & 0x03) == 0) && ((pb_size & 0x03) == 0));
|
|
/* uint word */
|
|
pb_size_word = pb_size/4;
|
|
/* get the number of words at a time */
|
|
num = 8;
|
|
/* use copy replace dma */
|
|
for (i = 0; i < pb_size_word; i = i + num) {
|
|
do {
|
|
tmp = RFPLC_GENERAL_READ_REG(CFG_RFPLC_STATUS_ADDR);
|
|
} while(!REG_FIELD_GET(CFG_RFPLC_WPHY_TX_BRDY, tmp));
|
|
|
|
if (pb_size_word - i <= num) {
|
|
real_num = pb_size_word - i;
|
|
} else {
|
|
real_num = num;
|
|
}
|
|
|
|
/* put 8 words at a time */
|
|
for (j = 0; j < real_num; j++) {
|
|
rawdata = *(((uint32_t *)buf) + i + j);
|
|
RF_MAC_TX_DMA_WRITE_REG(((i + j) << 2), rawdata);
|
|
}
|
|
}
|
|
}
|
|
|
|
void bb_rf_read_data_from_bb(uint32_t pb_size, uint8_t *buf)
|
|
{
|
|
uint32_t i, j;
|
|
uint32_t tmp, rawdata, real_num, pb_size_word, num;
|
|
IOT_ASSERT(buf && (((uint32_t)buf & 0x03) == 0) && ((pb_size & 0x03) == 0));
|
|
/* uint word */
|
|
pb_size_word = pb_size/4;
|
|
/* get the number of words at a time */
|
|
num = 8;
|
|
/* use copy replace dma */
|
|
for (i = 0; i < pb_size_word; i = i + num) {
|
|
do {
|
|
tmp = RFPLC_GENERAL_READ_REG(CFG_RFPLC_STATUS_ADDR);
|
|
} while(!REG_FIELD_GET(CFG_RFPLC_WPHY_RX_BRDY, tmp));
|
|
|
|
if (pb_size_word - i <= num) {
|
|
real_num = pb_size_word - i;
|
|
} else {
|
|
real_num = num;
|
|
}
|
|
|
|
/* get 8 words at a time */
|
|
for (j = 0; j < real_num; j++) {
|
|
rawdata = RF_MAC_RX_DMA_READ_REG(((i + j) << 2));
|
|
*(((uint32_t *)buf) + i + j) = rawdata;
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32_t bb_rf_set_pa_ldovs(uint16_t val)
|
|
{
|
|
uint16_t init;
|
|
init = rf_spi_read(5);
|
|
|
|
init &= 0xf803;
|
|
init |= (val << 2);
|
|
|
|
if (rf_spi_write(5, init)) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void bb_rf_set_test_mode(uint32_t rf_outside, uint8_t mode)
|
|
{
|
|
uint16_t special_tx_ldovs, special_tx_scale;
|
|
if (rf_outside) {
|
|
if (mode == 0) {
|
|
rf_spi_write(4, 0xFFC6);
|
|
rf_spi_write(5, 0xA7FE);
|
|
rf_spi_write(24,0xBF7);
|
|
bb_rf_set_pa_ldovs(511);
|
|
WPHY_INIT_WRITE_REG(0xf0101C, 0x30040);
|
|
} else if (mode == 1) {
|
|
rf_spi_write(4, 0xFFCF);
|
|
rf_spi_write(5, 0xA39A);
|
|
rf_spi_write(24,0xBF7);
|
|
special_tx_ldovs = mac_rf_get_tx_special_ldovs();
|
|
if (special_tx_ldovs == 0) {
|
|
special_tx_ldovs = 300;
|
|
}
|
|
special_tx_scale = mac_rf_get_tx_special_scale();
|
|
if (special_tx_scale == 0) {
|
|
special_tx_scale = 0x80;
|
|
}
|
|
bb_rf_set_pa_ldovs(special_tx_ldovs);
|
|
WPHY_INIT_WRITE_REG(0xf0101C, 0x30000 | special_tx_scale);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
} else {
|
|
if (mode == 0) {
|
|
rf_spi_write(4, 0xFFC6);
|
|
rf_spi_write(5, 0xA692);
|
|
rf_spi_write(24,0xBF7);
|
|
bb_rf_set_pa_ldovs(420);
|
|
WPHY_INIT_WRITE_REG(0xf0101C, 0x30040);
|
|
} else if (mode == 1) {
|
|
rf_spi_write(4, 0xFFCF);
|
|
rf_spi_write(5, 0xA322);
|
|
rf_spi_write(24,0xBF7);
|
|
bb_rf_set_pa_ldovs(200);
|
|
WPHY_INIT_WRITE_REG(0xf0101C, 0x30100);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void bb_rf_set_test_mode_v2()
|
|
{
|
|
uint32_t user_type, proto;
|
|
if (!mac_rf_get_cert_16qam_flag()) {
|
|
proto = mac_rf_get_proto();
|
|
if (proto == PLC_PROTO_TYPE_SPG) {
|
|
bb_rf_set_pa(1, 15);
|
|
goto out;
|
|
} else {
|
|
user_type = mac_rf_get_user_type();
|
|
if (user_type == USER_TYPE_STATE_GRID_BJ && mac_rf_is_sta()) {
|
|
bb_rf_set_pa(1, 10);
|
|
goto out;
|
|
} else if (user_type == USER_TYPE_STATE_GRID_XIAN) {
|
|
rf_spi_write(24, 0xBDF);
|
|
bb_rf_set_pa_ldovs(250);
|
|
WPHY_INIT_WRITE_REG(0xf0101C, 0x300A8);
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
bb_rf_set_pa(1, 5);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
void bb_rf_tx_switch_step1()
|
|
{
|
|
if (RF_VER_1 == bb_rf_get_ver()) {
|
|
#if RF_VER1_2022_8_15
|
|
rf_spi_write(0, 0xEBBA);
|
|
tx_switch_step1_us = gp_timer_get_current_val(0);
|
|
/* need delay 100us */
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void bb_rf_tx_switch_step2()
|
|
{
|
|
uint8_t ver = bb_rf_get_ver();
|
|
if (RF_VER_1 == ver) {
|
|
/* version 1 */
|
|
#if RF_VER1_2022_8_15
|
|
/* 100us between bb_rf_tx_switch_step1 and bb_rf_tx_switch_step2 */
|
|
uint32_t tx_switch_dlt = gp_timer_get_current_val(0) - tx_switch_step1_us;
|
|
if (tx_switch_dlt < BB_CPU_TXCFG1_TXCFG2_DELAY_US) {
|
|
tx_switch_dlt = BB_CPU_TXCFG1_TXCFG2_DELAY_US - tx_switch_dlt;
|
|
iot_delay_us(tx_switch_dlt);
|
|
}
|
|
rf_spi_write(0, 0xFBBB);
|
|
tx_switch_step2_us = gp_timer_get_current_val(0);
|
|
/* this position to aotx(bb_cpu_mac_trigger_tx) need some delay time
|
|
* the time is:
|
|
* special mode(hplc2rf cert mode) option2 100us
|
|
* special mode(hplc2rf cert mode) option3 500us
|
|
* normal mode(10dbm) option2 5us
|
|
* normal mode(10dbm) option3 150us
|
|
*/
|
|
#else
|
|
bb_rf_pll_cfg();
|
|
uint16_t init;
|
|
init = rf_spi_read(0);
|
|
init |= 0xf813;
|
|
init &= 0xfbff;
|
|
rf_spi_write(0, init);
|
|
|
|
init = rf_spi_read(1);
|
|
init &= 0xfd3f;
|
|
init |= 0x800;
|
|
rf_spi_write(1, init);
|
|
|
|
iot_delay_us(150);
|
|
|
|
init = rf_spi_read(1);
|
|
init |= 0x2c0;
|
|
init &= 0xf7ff;
|
|
rf_spi_write(1, init);
|
|
#endif
|
|
} else if (RF_VER_2 == ver || RF_VER_3 == ver) {
|
|
/* version 2 & 3 */
|
|
bb_rf_pll_cfg();
|
|
/* set bit[24:23]=2'b10; */
|
|
/* improve tx power */
|
|
uint32_t rdata = WPHY_INIT_READ_REG(0xf01304);
|
|
WPHY_INIT_WRITE_REG(0xf01304, (rdata & 0xfe7fffff) | (2 << 23));
|
|
uint16_t init;
|
|
init = rf_spi_read(0);
|
|
if (RF_VER_2 == ver) {
|
|
init |= 0x1254;
|
|
} else {
|
|
/* tx state config.
|
|
* R0<12> set to 1, PA ldo enable.
|
|
* R0<13> set to 1, TRX Bandgap enable.
|
|
* R0<6> set to 1, GAIN/STOP_AGC switch to STOP_AGC function.
|
|
* R0<4> set to 1, TRX bias enable.
|
|
* R0<2> set to 1, TRX ldo enable.
|
|
*/
|
|
init |= (1 << 12) | (1 << 13) |(1 << 6) | (1 << 4) | (1 << 2);
|
|
}
|
|
rf_spi_write(0, init);
|
|
iot_delay_us(50);
|
|
|
|
/* R0<1> set to 1, switch tx state */
|
|
init |= (1 << 0);
|
|
rf_spi_write(0, init);
|
|
if (RF_VER_3 == ver) {
|
|
init = rf_spi_read(9);
|
|
rf_spi_write(9, init | 0x1);
|
|
}
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
iot_delay_us(5);
|
|
}
|
|
|
|
static void __bb_rf_tx_set_freq_and_filter(uint32_t option, uint32_t fchz)
|
|
{
|
|
uint16_t bw_sel;
|
|
uint8_t en;
|
|
uint8_t ver = bb_rf_get_ver();
|
|
/* set fchz */
|
|
bb_rf_set_fchz(fchz);
|
|
|
|
if (option == PHY_RF_OPTION2_500K
|
|
|| option == PHY_RF_OPTION3_200K) {
|
|
mac_rf_get_tx_filter_cali(option, &en, &bw_sel);
|
|
if (!en) {
|
|
if (option == PHY_RF_OPTION2_500K) {
|
|
if (ver == RF_VER_3) {
|
|
bw_sel = 0x53;
|
|
} else {
|
|
bw_sel = 0x51;
|
|
}
|
|
} else {
|
|
if (ver == RF_VER_3) {
|
|
bw_sel = 0x136;
|
|
} else {
|
|
bw_sel = 0xD1;
|
|
}
|
|
}
|
|
}
|
|
bb_rf_set_filter(bw_sel);
|
|
}
|
|
}
|
|
|
|
static uint32_t cert_special_cfg = !ENA_RF_CERT_SPECIAL_CFG;
|
|
|
|
void bb_rf_tx_set_freq_and_filter(uint32_t option, uint32_t fchz)
|
|
{
|
|
/* set fchz */
|
|
__bb_rf_tx_set_freq_and_filter(option, fchz);
|
|
/* spur and spectrum test */
|
|
if (cert_special_cfg == 0 && mac_rf_get_cert_mode() ==
|
|
CERT_TEST_CMD_ENTER_PHY_HPLC2RF_LP) {
|
|
/* TODO: EVM cert test need use this configuration
|
|
* need add.
|
|
*/
|
|
cert_special_cfg = 1;
|
|
if (RF_VER_2 == bb_rf_get_ver()) {
|
|
bb_rf_set_test_mode_v2();
|
|
} else if (RF_VER_1 == bb_rf_get_ver()) {
|
|
bb_rf_set_pa(1, 5);
|
|
} else if (RF_VER_3 == bb_rf_get_ver()) {
|
|
bb_rf_set_pa(1, 5);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
} else if (cert_special_cfg && mac_rf_get_cert_mode() !=
|
|
CERT_TEST_CMD_ENTER_PHY_HPLC2RF_LP) {
|
|
cert_special_cfg = 0;
|
|
bb_rf_set_pa(1, bb_cpu_get_tx_pwr());
|
|
}
|
|
|
|
if (RF_VER_1 == bb_rf_get_ver()) {
|
|
#if RF_VER1_2022_8_15
|
|
/* record the time of delay bb_rf_tx_switch_step2 and aotx */
|
|
if (cert_special_cfg) {
|
|
if (option == PHY_RF_OPTION3_200K) {
|
|
tx_step2_to_aotx_us = BB_CPU_AOTX_TXCFG_SPC_OP3_DELAY_US;
|
|
} else {
|
|
/* option2 and option1 */
|
|
tx_step2_to_aotx_us = BB_CPU_AOTX_TXCFG_SPC_OP2_DELAY_US;
|
|
}
|
|
} else {
|
|
if (option == PHY_RF_OPTION3_200K) {
|
|
tx_step2_to_aotx_us = BB_CPU_AOTX_TXCFG_OP3_DELAY_US;
|
|
} else {
|
|
tx_step2_to_aotx_us = BB_CPU_AOTX_TXCFG_OP2_DELAY_US;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void bb_rf_tx_cfg(uint32_t option, uint32_t fchz)
|
|
{
|
|
bb_rf_tx_switch_step1();
|
|
bb_rf_tx_switch_step2();
|
|
__bb_rf_tx_set_freq_and_filter(option, fchz);
|
|
}
|
|
|
|
static void bb_rf_rx_switch_step1()
|
|
{
|
|
if (RF_VER_1 == bb_rf_get_ver()) {
|
|
#if RF_VER1_2022_8_15
|
|
rf_spi_write(0, 0xEBBB);
|
|
rx_switch_step1_us = gp_timer_get_current_val(0);
|
|
/* need delay 100us */
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void bb_rf_rx_switch_step2()
|
|
{
|
|
uint8_t ver = bb_rf_get_ver();
|
|
if (RF_VER_1 == ver) {
|
|
/* version 1 */
|
|
#if RF_VER1_2022_8_15
|
|
/* 100us between bb_rf_rx_switch_step1 and bb_rf_rx_switch_step2 */
|
|
uint32_t rx_switch_dlt = gp_timer_get_current_val(0) - rx_switch_step1_us;
|
|
if (rx_switch_dlt < 105) {
|
|
rx_switch_dlt = 105 - rx_switch_dlt;
|
|
iot_delay_us(rx_switch_dlt);
|
|
}
|
|
rf_spi_write(0, 0xEBBA);
|
|
#else
|
|
bb_rf_pll_cfg();
|
|
uint16_t init;
|
|
init = rf_spi_read(0);
|
|
init |= 0xe812;
|
|
init &= 0xebfe;
|
|
rf_spi_write(0, init);
|
|
#endif
|
|
} else if (RF_VER_2 == ver || RF_VER_3 == ver) {
|
|
/* version 2 & 3 */
|
|
bb_rf_pll_cfg();
|
|
/* set bit[24:23]=2'b01; */
|
|
uint32_t rdata = WPHY_INIT_READ_REG(0xf01304);
|
|
WPHY_INIT_WRITE_REG(0xf01304, (rdata & 0xfe7fffff) | (1 << 23));
|
|
uint16_t init;
|
|
init = rf_spi_read(0);
|
|
init |= 0x0014;
|
|
if (RF_VER_3 == ver) {
|
|
init |= (1 << 13);
|
|
}
|
|
init &= 0xffbf;
|
|
rf_spi_write(0, init);
|
|
if (RF_VER_3 == ver) {
|
|
init = rf_spi_read(9);
|
|
rf_spi_write(9, init & (~0x1));
|
|
}
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
/* 2us; */
|
|
iot_delay_us(5);
|
|
}
|
|
|
|
static void bb_rf_rx_set_freq_and_filter(uint32_t option, uint32_t fchz)
|
|
{
|
|
uint16_t bw_sel;
|
|
uint8_t ver = bb_rf_get_ver();
|
|
uint32_t temp;
|
|
if (ver == RF_VER_3 && HPLC_RF_RX_BPF_EN) {
|
|
temp = ((option == PHY_RF_OPTION1_1M) ? 0 :
|
|
(option == PHY_RF_OPTION2_500K) ? RF_OPT2_RX_BPF_CONSTANT_FREQ_HZ :
|
|
RF_OPT3_RX_BPF_CONSTANT_FREQ_HZ);
|
|
} else {
|
|
temp = ((option == PHY_RF_OPTION1_1M) ? 0 :
|
|
(option == PHY_RF_OPTION2_500K) ? RF_OPT2_RX_LPF_CONSTANT_FREQ_HZ :
|
|
RF_OPT3_RX_LPF_CONSTANT_FREQ_HZ);
|
|
}
|
|
/* set fchz */
|
|
bb_rf_set_fchz(fchz + temp);
|
|
if (option == PHY_RF_OPTION2_500K) {
|
|
if (ver == RF_VER_3 && HPLC_RF_RX_BPF_EN) {
|
|
bw_sel = 0x53;
|
|
} else {
|
|
bw_sel = 0x26;
|
|
}
|
|
bb_rf_set_filter(bw_sel);
|
|
} else if (option == PHY_RF_OPTION3_200K) {
|
|
if (ver == RF_VER_3 && HPLC_RF_RX_BPF_EN) {
|
|
bw_sel = 0x136;
|
|
} else {
|
|
bw_sel = 0x51;
|
|
}
|
|
bb_rf_set_filter(bw_sel);
|
|
}
|
|
}
|
|
|
|
void bb_rf_rx_cfg(uint32_t option, uint32_t fchz)
|
|
{
|
|
bb_rf_rx_switch_step1();
|
|
bb_rf_rx_switch_step2();
|
|
bb_rf_rx_set_freq_and_filter(option, fchz);
|
|
}
|
|
|
|
static uint16_t bb_rf_get_pa_ldovs(void)
|
|
{
|
|
uint16_t val;
|
|
val = rf_spi_read(5);
|
|
|
|
return (val & 0x7fc) >> 2;
|
|
}
|
|
|
|
typedef struct scale_dbm_s {
|
|
uint32_t ldovs : 9,
|
|
scale : 12,
|
|
rsvd : 11;
|
|
|
|
uint16_t r24;
|
|
int16_t dbm;
|
|
} scale_dbm_t;
|
|
|
|
#if 0
|
|
|
|
//rf inside
|
|
static const scale_dbm_t pa_in[] = {
|
|
{420, 0x100, 0x0, 0xBFB, 18}, {420, 0x0D0, 0x0, 0xBFB, 17}, {420, 0x0B0, 0x0, 0xBFB, 16},
|
|
{420, 0x0A0, 0x0, 0xBFB, 15}, {420, 0x080, 0x0, 0xBFB, 14}, {420, 0x0f8, 0x0, 0xBF7, 13},
|
|
{420, 0x0D8, 0x0, 0xBF7, 12}, {420, 0x0C0, 0x0, 0xBF7, 11}, {420, 0x0A8, 0x0, 0xBF7, 10},
|
|
{420, 0x098, 0x0, 0xBF7, 9}, {420, 0x088, 0x0, 0xBF7, 8}, {420, 0x078, 0x0, 0xBF7, 7},
|
|
{420, 0x068, 0x0, 0xBF7, 6}, {420, 0x058, 0x0, 0xBF7, 5}, {420, 0x050, 0x0, 0xBF7, 4},
|
|
{420, 0x045, 0x0, 0xBF7, 3}, {420, 0x080, 0x0, 0xBEF, 2}, {420, 0x070, 0x0, 0xBEF, 1},
|
|
{420, 0x060, 0x0, 0xBEF, 0}, {420, 0x058, 0x0, 0xBEF, -1}, {420, 0x048, 0x0, 0xBEF, -2},
|
|
{420, 0x040, 0x0, 0xBEF, -3}, {410, 0x040, 0x0, 0xBEF, -4}, {400, 0x040, 0x0, 0xBEF, -5},
|
|
{390, 0x040, 0x0, 0xBEF, -6}, {380, 0x040, 0x0, 0xBEF, -7}, {370, 0x040, 0x0, 0xBEF, -8},
|
|
{360, 0x040, 0x0, 0xBEF, -9}, {350, 0x040, 0x0, 0xBEF, -10}, {345, 0x040, 0x0, 0xBEF, -11},
|
|
{335, 0x040, 0x0, 0xBEF, -12}, {330, 0x040, 0x0, 0xBEF, -13}, {320, 0x040, 0x0, 0xBEF, -14},
|
|
{310, 0x040, 0x0, 0xBEF, -15}, {300, 0x040, 0x0, 0xBEF, -17}, {200, 0x041, 0x0, 0xBEF, -35.8}
|
|
};
|
|
|
|
#endif
|
|
|
|
//rf outside
|
|
static const scale_dbm_t pa_out[] = {
|
|
{511, 0x100, 0x0, 0xBFB, 20}, {511, 0x0C8, 0x0, 0xBFB, 19}, {511, 0x0B0, 0x0, 0xBFB, 18},
|
|
{511, 0x098, 0x0, 0xBFB, 17}, {511, 0x088, 0x0, 0xBFB, 16}, {511, 0x0f0, 0x0, 0xBF7, 15},
|
|
{511, 0x0E0, 0x0, 0xBF7, 14}, {511, 0x0C8, 0x0, 0xBF7, 13}, {511, 0x0A0, 0x0, 0xBF7, 12},
|
|
{511, 0x090, 0x0, 0xBF7, 11}, {511, 0x080, 0x0, 0xBF7, 10}, {511, 0x070, 0x0, 0xBF7, 9},
|
|
{511, 0x060, 0x0, 0xBF7, 8}, {511, 0x058, 0x0, 0xBF7, 7}, {511, 0x050, 0x0, 0xBF7, 6},
|
|
{511, 0x048, 0x0, 0xBF7, 5}, {420, 0x076, 0x0, 0xBF7, 4}, {420, 0x067, 0x0, 0xBF7, 3},
|
|
{420, 0x057, 0x0, 0xBF7, 2}, {420, 0x050, 0x0, 0xBF7, 1}, {420, 0x048, 0x0, 0xBF7, 0},
|
|
{420, 0x040, 0x0, 0xBF7, -1}, {470, 0x040, 0x0, 0xBEF, -2}, {450, 0x040, 0x0, 0xBEF, -3},
|
|
{430, 0x040, 0x0, 0xBEF, -4}, {420, 0x040, 0x0, 0xBEF, -5}, {400, 0x040, 0x0, 0xBEF, -6},
|
|
{390, 0x040, 0x0, 0xBEF, -7}, {380, 0x040, 0x0, 0xBEF, -8}, {370, 0x040, 0x0, 0xBEF, -9},
|
|
{360, 0x040, 0x0, 0xBEF, -10}, {350, 0x040, 0x0, 0xBEF, -11}, {340, 0x041, 0x0, 0xBEF, -12},
|
|
{330, 0x042, 0x0, 0xBEF, -13}, {320, 0x043, 0x0, 0xBEF, -14}, {310, 0x044, 0x0, 0xBEF, -15},
|
|
{300, 0x045, 0x0, 0xBEF, -17}, {200, 0x046, 0x0, 0xBEF, -35}
|
|
};
|
|
|
|
static const scale_dbm_t pa_v2[] = {
|
|
{511, 0x098, 0x0, 0xBFB, 21}, {511, 0x088, 0x0, 0xBFB, 20}, {511, 0x070, 0x0, 0xBFB, 19},
|
|
{511, 0x060, 0x0, 0xBFB, 18}, {511, 0x050, 0x0, 0xBFB, 17}, {511, 0x088, 0x0, 0xBF7, 16},
|
|
{511, 0x078, 0x0, 0xBF7, 15}, {511, 0x068, 0x0, 0xBF7, 14}, {511, 0x058, 0x0, 0xBF7, 13},
|
|
{511, 0x050, 0x0, 0xBF7, 12}, {511, 0x090, 0x0, 0xBEF, 11}, {511, 0x080, 0x0, 0xBEF, 10},
|
|
{511, 0x070, 0x0, 0xBEF, 9}, {511, 0x060, 0x0, 0xBEF, 8}, {511, 0x058, 0x0, 0xBEF, 7},
|
|
{511, 0x098, 0x0, 0xBDF, 6}, {511, 0x088, 0x0, 0xBDF, 5}, {511, 0x078, 0x0, 0xBDF, 4},
|
|
{511, 0x068, 0x0, 0xBDF, 3}, {511, 0x060, 0x0, 0xBDF, 2}, {511, 0x058, 0x0, 0xBDF, 1},
|
|
{511, 0x0A0, 0x0, 0xBBF, 0}, {511, 0x090, 0x0, 0xBBF, -1}, {511, 0x080, 0x0, 0xBBF, -2},
|
|
{511, 0x070, 0x0, 0xBBF, -3}, {511, 0x068, 0x0, 0xBBF, -4}, {511, 0x060, 0x0, 0xBBF, -5},
|
|
{511, 0x050, 0x0, 0xBBF, -6}, {370, 0x090, 0x0, 0xBBF, -7}, {350, 0x090, 0x0, 0xBBF, -8},
|
|
{330, 0x090, 0x0, 0xBBF, -9}, {320, 0x090, 0x0, 0xBBF, -10}, {310, 0x090, 0x0, 0xBBF, -11},
|
|
{290, 0x090, 0x0, 0xBBF, -12}, {280, 0x090, 0x0, 0xBBF, -13}
|
|
};
|
|
|
|
static const scale_dbm_t pa_v3[] = {
|
|
{511, 0x0a4, 0x0, 0xBFE, 21}, {511, 0x08c, 0x0, 0xBFE, 20}, {511, 0x0ee, 0x0, 0xBFD, 19},
|
|
{511, 0x0ce, 0x0, 0xBFD, 18}, {511, 0x0b8, 0x0, 0xBFD, 17}, {511, 0x09e, 0x0, 0xBFD, 16},
|
|
{511, 0x08c, 0x0, 0xBFD, 15}, {511, 0x07c, 0x0, 0xBFD, 14}, {511, 0x0d9, 0x0, 0xBFB, 13},
|
|
{511, 0x0c5, 0x0, 0xBFB, 12}, {511, 0x0ab, 0x0, 0xBFB, 11}, {511, 0x09d, 0x0, 0xBFB, 10},
|
|
{511, 0x089, 0x0, 0xBFB, 9}, {511, 0x0fa, 0x0, 0xBF7, 8}, {511, 0x0de, 0x0, 0xBF7, 7},
|
|
{511, 0x0c8, 0x0, 0xBF7, 6}, {511, 0x0b0, 0x0, 0xBF7, 5}, {511, 0x09e, 0x0, 0xBF7, 4},
|
|
{511, 0x088, 0x0, 0xBF7, 3}, {511, 0x078, 0x0, 0xBF7, 2}, {511, 0x09f, 0x0, 0xBF7, 1},
|
|
{460, 0x071, 0x0, 0xBF7, 0}, {300, 0x054, 0x0, 0xBFB, -1}, {250, 0x064, 0x0, 0xBFB, -2},
|
|
{250, 0x05a, 0x0, 0xBFB, -3}, {250, 0x052, 0x0, 0xBFB, -4}, {250, 0x048, 0x0, 0xBFB, -5},
|
|
{300, 0x060, 0x0, 0xBF7, -6}, {300, 0x054, 0x0, 0xBF7, -7}, {250, 0x062, 0x0, 0xBF7, -8},
|
|
{250, 0x05a, 0x0, 0xBF7, -9}, {250, 0x050, 0x0, 0xBF7, -10}, {250, 0x048, 0x0, 0xBF7, -11},
|
|
{250, 0x040, 0x0, 0xBF7, -12}, {250, 0x03a, 0x0, 0xBF7, -13}, {250, 0x064, 0x0, 0xBEF, -14},
|
|
{220, 0x032, 0x0, 0xBBF, -35},
|
|
};
|
|
|
|
int32_t bb_rf_get_pa(uint32_t rf_outside)
|
|
{
|
|
uint32_t i;
|
|
float dbm;
|
|
uint16_t r24;
|
|
const scale_dbm_t *p = NULL;
|
|
uint32_t nr = 0;
|
|
uint8_t ver = bb_rf_get_ver();
|
|
|
|
int32_t scale = WPHY_INIT_READ_REG(0xf0101C) & 0xfff;
|
|
uint32_t ldovs = bb_rf_get_pa_ldovs();
|
|
if (RF_VER_1 == ver) {
|
|
if (rf_outside) {
|
|
p = pa_out;
|
|
nr = IOT_ARRAY_CNT(pa_out);
|
|
} else {
|
|
//p = pa_in;
|
|
//nr = IOT_ARRAY_CNT(pa_in);
|
|
p = pa_out;
|
|
nr = IOT_ARRAY_CNT(pa_out);
|
|
}
|
|
} else if (RF_VER_2 == ver) {
|
|
p = pa_v2;
|
|
nr = IOT_ARRAY_CNT(pa_v2);
|
|
} else if (RF_VER_3 == ver) {
|
|
p = pa_v3;
|
|
nr = IOT_ARRAY_CNT(pa_v3);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
r24 = rf_spi_read(24);
|
|
|
|
for (i = 0; i < nr; i++) {
|
|
if (scale == p[i].scale && ldovs == p[i].ldovs && r24 == p[i].r24) {
|
|
dbm = p[i].dbm;
|
|
return (int32_t)dbm;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t bb_rf_set_pa(uint32_t rf_outside, int32_t dbm)
|
|
{
|
|
int i;
|
|
const scale_dbm_t *p = NULL;
|
|
uint32_t nr = 0;
|
|
uint8_t ver = bb_rf_get_ver();
|
|
|
|
if (RF_VER_1 == ver) {
|
|
if (rf_outside) {
|
|
p = pa_out;
|
|
nr = IOT_ARRAY_CNT(pa_out);
|
|
} else {
|
|
//p = pa_in;
|
|
//nr = IOT_ARRAY_CNT(pa_in);
|
|
p = pa_out;
|
|
nr = IOT_ARRAY_CNT(pa_out);
|
|
}
|
|
} else if (RF_VER_2 == ver) {
|
|
p = pa_v2;
|
|
nr = IOT_ARRAY_CNT(pa_v2);
|
|
} else if (RF_VER_3 == ver) {
|
|
p = pa_v3;
|
|
nr = IOT_ARRAY_CNT(pa_v3);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
for (i = 0; i < nr; i++) {
|
|
if (dbm >= p[i].dbm) {
|
|
WPHY_INIT_WRITE_REG(0xf0101C, p[i].scale | 0x30000);
|
|
if (bb_rf_set_pa_ldovs(p[i].ldovs)) {
|
|
return 1;
|
|
}
|
|
if (rf_spi_write(24, p[i].r24)) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void bb_rf_set_tx_iq_mag(uint8_t tx_i_m, uint8_t tx_q_m)
|
|
{
|
|
uint16_t value;
|
|
value = rf_spi_read(9);
|
|
value &= 0xffC3;
|
|
value |= (tx_i_m << 2);
|
|
rf_spi_write(9, value);
|
|
|
|
value = rf_spi_read(10);
|
|
value &= 0xFFF;
|
|
value |= (tx_q_m << 12);
|
|
rf_spi_write(10, value);
|
|
}
|
|
|
|
void bb_rf_set_tx_iq_phase(uint8_t tx_i_p, uint8_t tx_q_p)
|
|
{
|
|
uint16_t value = 0;
|
|
value = rf_spi_read(23);
|
|
value &= ~(0x03ff);
|
|
value |= (tx_q_p | tx_i_p << 5);
|
|
rf_spi_write(23, value);
|
|
}
|
|
|
|
void bb_rf_set_rx_iq_mag(uint8_t i_mag, uint8_t q_mag)
|
|
{
|
|
uint16_t init = rf_spi_read(9);
|
|
uint16_t i_mag_mask = 0xF000;
|
|
uint16_t i_mag_shift = 12;
|
|
uint16_t q_mag_mask = 0x0780;
|
|
uint16_t q_mag_shift = 7;
|
|
init &= ~(i_mag_mask | q_mag_mask);
|
|
init |= ((i_mag << i_mag_shift) & i_mag_mask) | (
|
|
(q_mag << q_mag_shift) & q_mag_mask);
|
|
rf_spi_write(9, init);
|
|
}
|
|
|
|
void bb_rf_set_tx_dc(int8_t tx_i_dc, int8_t tx_q_dc)
|
|
{
|
|
uint16_t value = 0;
|
|
uint8_t temp1, temp2;
|
|
temp1 = IOT_ABS(tx_i_dc);
|
|
temp2 = IOT_ABS(tx_q_dc);
|
|
if (tx_i_dc < 0) {
|
|
value |= 0x8000;
|
|
}
|
|
if (tx_q_dc < 0) {
|
|
value |= 0x4000;
|
|
}
|
|
value |= (temp2 | temp1 << 7);
|
|
rf_spi_write(8, value);
|
|
}
|
|
|
|
void bb_rf_set_filter(uint16_t value)
|
|
{
|
|
uint16_t init;
|
|
init = rf_spi_read(7);
|
|
init &= 0x7f;
|
|
init |= (value << 7);
|
|
rf_spi_write(7, init);
|
|
}
|
|
|
|
void bb_rf_update_cali(uint8_t option)
|
|
{
|
|
uint8_t tx_i_m, tx_q_m, tx_i_p, tx_q_p, tx_i_dc, tx_q_dc;
|
|
uint8_t bw_en;
|
|
uint16_t bw_sel;
|
|
|
|
mac_rf_get_tx_iqm_cali(&tx_i_m, &tx_q_m);
|
|
bb_rf_set_tx_iq_mag(tx_i_m, tx_q_m);
|
|
|
|
mac_rf_get_tx_iqp_cali(&tx_i_p, &tx_q_p);
|
|
bb_rf_set_tx_iq_phase(tx_i_p, tx_q_p);
|
|
|
|
mac_rf_get_tx_dc_cali(&tx_i_dc, &tx_q_dc);
|
|
bb_rf_set_tx_dc((int8_t)tx_i_dc, (int8_t)tx_q_dc);
|
|
mac_rf_get_tx_filter_cali(option, &bw_en, &bw_sel);
|
|
if (bw_en) {
|
|
// 0x1087 & 0x7f -> 7
|
|
bb_rf_set_filter(bw_sel);
|
|
}
|
|
return;
|
|
}
|
|
|
|
static uint32_t bb_rf_judge_ver()
|
|
{
|
|
#define GET_VER_TIMEOUT_100MS 100000
|
|
|
|
uint32_t cur_time;
|
|
uint32_t time_span;
|
|
uint32_t start_us;
|
|
|
|
uint16_t reg0, reg0_tmp;
|
|
uint16_t val;
|
|
val = rf_spi_read(22);
|
|
if ((val & 0xff) == 0x4C) {
|
|
return RF_VER_3;
|
|
}
|
|
reg0 = rf_spi_read(0);
|
|
reg0_tmp = reg0;
|
|
reg0 |= 0x4800;
|
|
reg0 &= 0x7FFF;
|
|
|
|
rf_spi_write(0, reg0); /* bit14 | bit11 */
|
|
|
|
iot_delay_us(200);
|
|
|
|
val = rf_spi_read(20);
|
|
if ((val >> 15) == 0) {
|
|
val = rf_spi_read(12);
|
|
val &= 0xff7f;
|
|
if (rf_spi_write(12, val)) {
|
|
return RF_VER_INVAILD;
|
|
}
|
|
|
|
iot_delay_us(1);
|
|
|
|
val |= 0x80;
|
|
if (rf_spi_write(12, val)) {
|
|
return RF_VER_INVAILD;
|
|
}
|
|
}
|
|
|
|
val = rf_spi_read(20);
|
|
start_us = gp_timer_get_current_val(0);
|
|
while ((val >> 15) == 0) {
|
|
cur_time = gp_timer_get_current_val(0);
|
|
time_span = cur_time - start_us;
|
|
if (time_span > GET_VER_TIMEOUT_100MS*10) {
|
|
bb_cpu_printf("rf version detect failed\n");
|
|
return RF_VER_INVAILD;
|
|
}
|
|
val = rf_spi_read(20);
|
|
iot_delay_us(5);
|
|
}
|
|
|
|
rf_spi_write(0, reg0 | 0x8000);
|
|
|
|
val = rf_spi_read(20);
|
|
start_us = gp_timer_get_current_val(0);
|
|
while ((val >> 15) == 0) {
|
|
cur_time = gp_timer_get_current_val(0);
|
|
time_span = cur_time - start_us;
|
|
if (time_span > GET_VER_TIMEOUT_100MS) {
|
|
rf_spi_write(0, reg0_tmp);
|
|
return RF_VER_2;
|
|
}
|
|
val = rf_spi_read(20);
|
|
iot_delay_us(5);
|
|
}
|
|
|
|
rf_spi_write(0, reg0_tmp);
|
|
|
|
return RF_VER_1; /* rf v1*/
|
|
}
|
|
|
|
uint32_t bb_rf_init_ver()
|
|
{
|
|
uint32_t rf_ver, ret = 1;
|
|
rf_ver = mac_rf_get_rf_ver();
|
|
if (phy_rf_check_rf_version(rf_ver)) {
|
|
ret = 0;
|
|
} else if (rf_ver == RF_VER_UNKNOWN) {
|
|
/* if rf ver is unkonw, set default ver(v1) */
|
|
rf_ver = RF_VER_1;
|
|
ret = 0;
|
|
}
|
|
if (ret == 0) {
|
|
g_bbcpu_rf_ver = rf_ver;
|
|
bb_cpu_printf("get rf ver:%d - %d\n", mac_rf_get_rf_ver(), rf_ver);
|
|
return 0;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < 1; i++) {
|
|
rf_ver = bb_rf_judge_ver();
|
|
if (rf_ver != RF_VER_INVAILD) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* get rf ver fail, default to use v1 configuration */
|
|
if (rf_ver == RF_VER_INVAILD) {
|
|
rf_ver = RF_VER_1;
|
|
mac_rf_set_rf_ver(RF_VER_UNKNOWN);
|
|
} else {
|
|
mac_rf_set_rf_ver(rf_ver);
|
|
}
|
|
|
|
g_bbcpu_rf_ver = rf_ver;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t bb_rf_get_ver()
|
|
{
|
|
return g_bbcpu_rf_ver;
|
|
}
|
|
|
|
void bb_rf_pll_cfg(void)
|
|
{
|
|
uint8_t ver = bb_rf_get_ver();
|
|
if (RF_VER_1 == ver) {
|
|
uint16_t init;
|
|
init = rf_spi_read(0);
|
|
init |= 0xe801;
|
|
init &= 0xebff;
|
|
rf_spi_write(0, init);
|
|
} else if (RF_VER_2 == ver || RF_VER_3 == ver) {
|
|
uint16_t init;
|
|
init = rf_spi_read(0);
|
|
uint16_t flag = init & 0x4000;
|
|
if (RF_VER_3 == ver) {
|
|
/* PLL state config
|
|
* R0<15> set to 0, PFD capless LDO enable
|
|
* R0<14> set to 1, pll ldo enable
|
|
* R0<11> set to 1, pfd vdd select VDD_capless
|
|
* R0<13> set to 0, TRX Bnadgap power down.
|
|
* note:for V1 and V2 chips, TRX Bnadgap is enabled in the PLL
|
|
* state, which can improve the tx success rate
|
|
* R0<12> set to 0, PA ldo power down.
|
|
* R0<2> set to 0, TRX ldo power down.
|
|
*/
|
|
init |= (1 << 11);
|
|
if (!mac_rf_is_rf_in()) {
|
|
init |= (1 << 14);
|
|
}
|
|
init &= ~((1 << 15) | (1 << 13) | (1 << 12) | (1 << 2) | (1 << 0));
|
|
} else {
|
|
init |= 0x6800;
|
|
init &= 0x6bea;
|
|
}
|
|
rf_spi_write(0, init);
|
|
if (flag == 0)
|
|
iot_delay_us(200);
|
|
else
|
|
iot_delay_us(50);
|
|
|
|
init = rf_spi_read(20);
|
|
if ((init >> 15) == 0) {
|
|
init = rf_spi_read(12);
|
|
init &= 0xff7f;
|
|
rf_spi_write(12, init);
|
|
iot_delay_us(1);
|
|
init |= 0x80;
|
|
rf_spi_write(12, init);
|
|
}
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
void bb_rf_standby_cfg(void)
|
|
{
|
|
uint8_t ver = bb_rf_get_ver();
|
|
uint16_t val;
|
|
if (RF_VER_2 == ver || RF_VER_3 == ver) {
|
|
val = rf_spi_read(0);
|
|
/* standby state config
|
|
* R0<15> set to 1, PFD capless LDO power down
|
|
* R0<14> set to 0, pll ldo power down
|
|
* R0<11> set to 1, pfd vdd select VDD_capless
|
|
* R0<13> set to 0, TRX Bnadgap power down.
|
|
* note:for V1 and V2 chips, TRX Bnadgap is enabled in the PLL
|
|
* state, which can improve the tx success rate
|
|
* R0<12> set to 0, PA ldo power down.
|
|
* R0<2> set to 0, TRX ldo power down.
|
|
*/
|
|
val |= (1 << 15) | (1 << 11);
|
|
val &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 2) | (1 << 0));
|
|
rf_spi_write(0, val);
|
|
}
|
|
}
|
|
|
|
static int16_t bb_rf_set_dc_i(uint16_t val)
|
|
{
|
|
uint16_t init;
|
|
|
|
init = rf_spi_read(11);
|
|
init &= 0xc07f;
|
|
init |= (val << 7);
|
|
|
|
if (rf_spi_write(11, init)) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int16_t bb_rf_set_dc_q(uint16_t val)
|
|
{
|
|
uint16_t init;
|
|
|
|
init = rf_spi_read(11);
|
|
|
|
init &= 0xff80;
|
|
init |= val;
|
|
|
|
if (rf_spi_write(11, init)) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint8_t bb_rf_set_lna_pwr(uint8_t mode)
|
|
{
|
|
uint16_t val;
|
|
|
|
val = rf_spi_read(1);
|
|
|
|
val &= 0x7fff;
|
|
val |= (mode << 15);
|
|
|
|
if (rf_spi_write(1, val)) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int16_t bb_rf_set_dc_close(void)
|
|
{
|
|
uint16_t init;
|
|
|
|
init = rf_spi_read(1);
|
|
init |= 0x18;
|
|
|
|
if (rf_spi_write(1, init)) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void bb_rf_clibr_dcr_v2(void)
|
|
{
|
|
uint32_t i, q;
|
|
uint32_t min_i = 0, min_q = 0;
|
|
uint32_t thrd;
|
|
uint32_t gamma;
|
|
uint32_t power = 0;
|
|
uint32_t min = 0xffffffff;
|
|
int16_t im = 0, re = 0;
|
|
uint8_t step = 2;
|
|
|
|
bb_rf_set_dc_close();
|
|
|
|
if (mac_rf_get_rx_dc_loopback_clibr_flag()) {
|
|
uint8_t dc_i, dc_q;
|
|
mac_rf_get_auto_rxdc_iq_value(&dc_i, &dc_q);
|
|
bb_rf_set_dc_i(dc_i);
|
|
bb_rf_set_dc_q(dc_q);
|
|
return;
|
|
}
|
|
/* set flag on first time */
|
|
mac_rf_set_rx_dc_loopback_clibr_flag(1);
|
|
|
|
thrd = bb_wphy_read_fld_reg(0xf01400, 0, 31);
|
|
gamma = bb_wphy_read_fld_reg(0xf01334, 4, 7);
|
|
|
|
bb_rf_set_lna_pwr(1);
|
|
bb_wphy_write_fld_reg(0xf01334, 0, 0, 1);
|
|
bb_wphy_write_fld_reg(0xf01334, 4, 7, 6);
|
|
bb_wphy_write_fld_reg(0xf01400, 0, 31, 0xffffffff);
|
|
bb_rf_debug_rx_immd();
|
|
|
|
for (i = 0; i < 128; i += step) {
|
|
bb_rf_set_dc_i(i);
|
|
for (q = 0; q < 128; q += step) {
|
|
bb_rf_set_dc_q(q);
|
|
|
|
iot_delay_us(30);
|
|
im = ((int16_t)(bb_wphy_read_fld_reg(0xf0133c, 16, 27) << 4) >> 4);
|
|
re = ((int16_t)(bb_wphy_read_fld_reg(0xf0133c, 0, 11) << 4) >> 4);
|
|
power = (im * im) + (re * re);
|
|
|
|
if (min > power) {
|
|
min = power;
|
|
min_i = i;
|
|
min_q = q;
|
|
}
|
|
}
|
|
}
|
|
|
|
bb_rf_set_dc_i(min_i);
|
|
bb_rf_set_dc_q(min_q);
|
|
mac_rf_set_auto_rxdc_iq_value(min_i, min_q);
|
|
bb_cpu_printf("rx dc loop cali i/q/power=[%d, %d, %d]\n", min_i, min_q,
|
|
min);
|
|
|
|
bb_wphy_stop_rx();
|
|
bb_wphy_write_fld_reg(0xf01400, 0, 31, thrd);
|
|
bb_wphy_write_fld_reg(0xf01334, 4, 7, gamma);
|
|
bb_wphy_write_fld_reg(0xf01334, 0, 0, 0);
|
|
bb_rf_set_lna_pwr(0);
|
|
|
|
return;
|
|
}
|
|
|
|
void bb_rf_clibr_dc(uint32_t option)
|
|
{
|
|
if (mac_rf_get_rx_dc_loopback_clibr_en() &&
|
|
RF_VER_2 == bb_rf_get_ver()) {
|
|
bb_wphy_write_fld_reg(0xf01314, 1, 1, 0);
|
|
bb_wphy_write_fld_reg(0xf01320, 8, 11, 6);
|
|
bb_wphy_write_fld_reg(0xf01320, 28, 31, 6);
|
|
bb_wphy_write_fld_reg(0xf01320, 20, 27, 43);
|
|
bb_wphy_write_fld_reg(0xf01324, 16, 23, 31);
|
|
|
|
bb_rf_clibr_dcr_v2();
|
|
|
|
bb_wphy_write_fld_reg(0xf01314, 1, 1, 1);
|
|
}
|
|
bb_rf_clibr_tx_dcoc(option, RF_CHANNEL_DEF_FREQ_HZ, 1, 2, NULL, NULL);
|
|
}
|
|
|
|
static int32_t bb_rf_set_tx_pwr_det(uint8_t en)
|
|
{
|
|
uint16_t init;
|
|
|
|
init = rf_spi_read(24);
|
|
|
|
if (en) {
|
|
init |= 1 << 13;
|
|
} else {
|
|
init &= ~(1 << 13);
|
|
}
|
|
|
|
if (rf_spi_write(24, init))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t bb_rf_set_tx_pwr_adc_det(uint8_t en)
|
|
{
|
|
uint16_t init;
|
|
|
|
init = rf_spi_read(24);
|
|
|
|
if (en) {
|
|
init |= 1 << 12;
|
|
} else {
|
|
init &= ~(1 << 12);
|
|
}
|
|
|
|
if (rf_spi_write(24, init))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint16_t bb_rf_get_adc_power(void)
|
|
{
|
|
uint16_t init;
|
|
|
|
init = rf_spi_read(33);
|
|
|
|
return init & 0xfff;
|
|
}
|
|
|
|
static uint8_t bb_rf_wphy_clibr_tx_dcoc(uint32_t option, uint32_t fchz,
|
|
uint8_t interval, uint8_t step, uint16_t* ldovs, uint8_t* rf_att)
|
|
{
|
|
int16_t best_i = 0, best_q = 0;
|
|
uint32_t min = 0xffffffff, power = 0;
|
|
int16_t dc_i, dc_q;
|
|
uint16_t temp, raw_data;
|
|
|
|
if (ldovs != NULL)
|
|
bb_rf_set_pa_ldovs(*ldovs);
|
|
if (rf_att != NULL)
|
|
rf_spi_write(24, 0xB80 | (*rf_att & 0x7f));
|
|
|
|
bb_rf_jesd_reset();
|
|
|
|
/* tx config */
|
|
bb_rf_tx_cfg(option, fchz);
|
|
|
|
/* clear bit13, set JESD207 ENABLE mode to plus.
|
|
* set bit14, means set ADC/DAC coder to completion.
|
|
*/
|
|
temp = rf_spi_read(30);
|
|
raw_data = temp;
|
|
temp &= ~(0x01 << 13);
|
|
temp |= 0x01 << 14;
|
|
rf_spi_write(30, temp);
|
|
/* the actual value is the complement of the set value */
|
|
mac_rf_tx_dc(512, 512, 1);
|
|
|
|
bb_rf_set_tx_pwr_det(1);
|
|
bb_rf_set_tx_pwr_adc_det(1);
|
|
iot_delay_us(5000);
|
|
|
|
for (dc_i = -127; dc_i <= 127; dc_i += step) {
|
|
for (dc_q = -127; dc_q <= 127; dc_q += step) {
|
|
bb_rf_set_tx_dc(dc_i, dc_q);
|
|
iot_delay_us(interval);
|
|
power = bb_rf_get_adc_power();
|
|
if (min > power) {
|
|
min = power;
|
|
best_i = dc_i;
|
|
best_q = dc_q;
|
|
}
|
|
}
|
|
}
|
|
|
|
bb_rf_set_tx_pwr_det(0);
|
|
bb_rf_set_tx_pwr_adc_det(0);
|
|
|
|
mac_rf_tx_dc(0, 0, 0);
|
|
rf_spi_write(30, raw_data);
|
|
bb_wphy_stop_tx();
|
|
|
|
bb_rf_set_tx_dc(best_i, best_q);
|
|
mac_rf_set_tx_dc_cali(best_i, best_q);
|
|
bb_cpu_printf("tx dc loop cali i/q/power=[%d, %d, %d]\n", best_i, best_q,
|
|
min);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint8_t bb_rf_clibr_tx_dcoc(uint32_t option, uint32_t fchz,
|
|
uint8_t interval, uint8_t step, uint16_t* ldovs, uint8_t* rf_att)
|
|
{
|
|
if (!mac_rf_get_tx_dc_loopback_clibr_en() || RF_VER_2 != bb_rf_get_ver()) {
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
return bb_rf_wphy_clibr_tx_dcoc(option, fchz, interval, step, ldovs,
|
|
rf_att);
|
|
|
|
}
|
|
|
|
void bb_rf_fix_gain(uint8_t en, uint8_t rf_gain, uint8_t if_gain)
|
|
{
|
|
uint16_t init;
|
|
|
|
/* R0b8 R0b6 mode
|
|
* 0 0 RF internal AGC.
|
|
* 1 0 BB AGC_ GAIN signal configuration gain.
|
|
* 1 1 R4 register configuration gain.
|
|
*/
|
|
|
|
init = rf_spi_read(0);
|
|
if (en) {
|
|
/* fix gain */
|
|
init |= (0x01 << 6) | (0x01 << 8);
|
|
} else {
|
|
rf_gain = 15;
|
|
if_gain = 31;
|
|
init &= ~(0x01 << 6);
|
|
}
|
|
|
|
rf_spi_write(0, init);
|
|
init = rf_spi_read(4);
|
|
init &= 0x3f;
|
|
init |= (rf_gain & 0xf) << 12;
|
|
init |= (if_gain & 0x3f) << 6;
|
|
rf_spi_write(4, init);
|
|
}
|