3254 lines
112 KiB
C
3254 lines
112 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 "os_utils.h"
|
|
#include "os_task.h"
|
|
#include "hw_reg_api.h"
|
|
#include "mac_sys_reg.h"
|
|
#include "mac_reset.h"
|
|
#include "mpdu_header.h"
|
|
#include "ahb.h"
|
|
#include "plc_protocol.h"
|
|
#include "dbg_msg_pop.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_clock.h"
|
|
#include "iot_errno.h"
|
|
#include "iot_module.h"
|
|
#include "iot_ftm_msg.h"
|
|
#include "iot_board.h"
|
|
|
|
#if IOT_MP_SUPPORT == 1 && HPLC_RF_DEV_SUPPORT
|
|
|
|
#include "rf_mac_int.h"
|
|
#include "rf_mac_reg.h"
|
|
#include "rfplc_reg_base.h"
|
|
#include "rf_hw_tonemap.h"
|
|
#include "phy_rf_init.h"
|
|
#include "phy_rf_chn.h"
|
|
#include "rf_mac_tx.h"
|
|
#include "mac_rf_isr.h"
|
|
#include "mac_rf_tx_hw.h"
|
|
#include "mac_rf_rx_buf_ring.h"
|
|
#include "mac_rf_common_hw.h"
|
|
#include "mac_rf_txq_hw.h"
|
|
#include "iot_system.h"
|
|
|
|
/* hplc mac and phy Common header */
|
|
#include "phy_txrx_pwr.h"
|
|
#include "phy_chn.h"
|
|
#include "phy_bb.h"
|
|
#include "mac_sys_reg.h"
|
|
#include "mac_rx_descriptor_reg.h"
|
|
#include "rx_desc_reg_api.h"
|
|
#include "mpdu_header.h"
|
|
#include "mac_rx_buf_ring.h"
|
|
#include "tx_entry.h"
|
|
#include "hw_rx.h"
|
|
|
|
#include "bb_init.h"
|
|
#include "bb_rf_cfg.h"
|
|
#include "rf_phy_tx.h"
|
|
#include "rf_phy_rx.h"
|
|
#include "phy_ada_dump.h"
|
|
#include "iot_pt_rf_func.h"
|
|
#include "iot_gpio_api.h"
|
|
#include "iot_led.h"
|
|
#include "iot_board_api.h"
|
|
#include "mp_mode.h"
|
|
#include "math_log10.h"
|
|
#include "iot_crc_api.h"
|
|
#include "iot_bitmap_api.h"
|
|
#include "hw_reg_api.h"
|
|
#include "phy_reg.h"
|
|
|
|
/* define mp rf tx descriptors count */
|
|
#define MP_RF_TX_DESC_CNT 2
|
|
|
|
/* test massage magic number */
|
|
#define MP_RF_TEST_MSG_MAGIC_NUMBER 0x55AA55AA
|
|
|
|
/* define mp rf csr tx max count */
|
|
#define MP_RF_CSR_TX_MAX_COUNT 200
|
|
|
|
/* maximum number of TX EVM samples */
|
|
#define MP_RF_TX_EVM_SMAP_MAX_CNT 1000
|
|
|
|
/* default time limit of CSI test, unit: ms */
|
|
#define MP_RF_TEST_CASE_CSI_TIMEOUT_DEF 1000
|
|
|
|
/* default time limit of CSR test, unit: ms */
|
|
#define MP_RF_TEST_CASE_CSR_TIMEOUT_DEF 1000
|
|
|
|
/* max time limit of CSR test, unit: ms */
|
|
#define MP_RF_TEST_CASE_CSR_TIMEOUT_MAX 5000
|
|
|
|
/* default time limit of TX EVM test, unit: ms */
|
|
#define MP_RF_TEST_CASE_TX_EVM_TIMEOUT_DEF 1000
|
|
|
|
/* default time limit of change phy option test, unit: ms */
|
|
#define MP_RF_TEST_CASE_CHG_PHY_TIMEOUT_DEF 900
|
|
|
|
/* default time delay of change phy option, unit: ms */
|
|
#define MP_RF_TEST_CASE_CHG_PHY_EXEC_DELAY 600
|
|
|
|
/* define the number of times the command is sent repeatedly */
|
|
#define MP_RF_CMD_RETRY_COUNT 4
|
|
|
|
/* define the repeated sending interval of the command */
|
|
#define MP_RF_CMD_RETRY_INTERVAL 100
|
|
|
|
/* define invalid rssi of snr value */
|
|
#define MP_RF_INVAL_RSSI_SNR (-127)
|
|
|
|
/* default snr threshold of CSI test */
|
|
#define MP_RF_CSI_TEST_SNR_THR 10
|
|
|
|
/* default snr threshold of CSI test */
|
|
#define MP_RF_CSI_TEST_RSSI_THR (-110)
|
|
|
|
/* define mp rf golden common timer period, unit:ms*/
|
|
#define MP_RF_GOLDEN_COMMON_TIMER_PERIOD (100)
|
|
|
|
/* default time limit of TX CALI test, unit: ms */
|
|
#define MP_RF_TEST_CASE_TX_CALI_TIMEOUT_DEF 1000
|
|
|
|
/* define rf phy iq phase compensation maximum code */
|
|
#define RF_PHY_IQ_PHASE_COMPEN_CODE_MAX 32
|
|
|
|
/* define rf phy iq magnitude compensation maximum code */
|
|
#define RF_PHY_IQ_MAG_COMPEN_CODE_MAX 16
|
|
|
|
/* define the size of tx cali data array */
|
|
#define MP_RF_TEST_CASE_TX_CALI_SNR_SAMP_BUF_SIZE \
|
|
(RF_PHY_IQ_PHASE_COMPEN_CODE_MAX * RF_PHY_IQ_PHASE_COMPEN_CODE_MAX)
|
|
|
|
/* judge whether the value of phase is within the range */
|
|
#define rf_phy_iq_phase_compen_code_valid(v) (v >= 0 && \
|
|
v < RF_PHY_IQ_PHASE_COMPEN_CODE_MAX)
|
|
|
|
/* judge whether the value of mag is within the range */
|
|
#define rf_phy_iq_mag_compen_code_valid(v) (v >= 0 && \
|
|
v < RF_PHY_IQ_MAG_COMPEN_CODE_MAX)
|
|
|
|
/* The maximum number of best compensation results calculated from snr samples.
|
|
*/
|
|
#define MP_RF_TX_CALI_SNR_BEST_RESULT_MAX 3
|
|
|
|
/* how many i/q combinations of snr data can be recorded */
|
|
#define MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_SIZE 81
|
|
|
|
/* how many sets of data can be recorded for each i/q combination */
|
|
#define MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_DEPTH 30
|
|
|
|
/* define the size of tx cali bitmap array */
|
|
#define MP_RF_TX_CALI_SNR_BM_SIZE 128
|
|
|
|
/* convert the i/q combination to a large number */
|
|
#define MP_RF_IQ_CODE_TO_MAGIC(max_code, i, q) ((i) * (max_code) + (q))
|
|
|
|
/* minimum number of points required for linear fitting */
|
|
#define MP_RF_TX_CALI_SNR_LINER_FIT_VALID_SAMP_NUM 6
|
|
|
|
/* define MP rf test message id */
|
|
#define MP_RF_MSG_ID_CSI 0
|
|
#define MP_RF_MSG_ID_CSR 1
|
|
#define MP_RF_MSG_ID_TX_EVM_SAMP 2
|
|
#define MP_RF_MSG_ID_TX_EVM_STAT_QUERY 3
|
|
#define MP_RF_MSG_ID_CHG_PHY 4
|
|
#define MP_RF_MSG_ID_TX_CALI_STAT_QUERY 5
|
|
|
|
/* define event id */
|
|
#define MP_RF_EVT_ID_RF_RX 0
|
|
#define MP_RF_EVT_ID_PLC_RX 1
|
|
#define MP_RF_EVT_ID_TIMEROUT 2
|
|
|
|
/* enable/disable Calibration measurement data dump */
|
|
#define MP_RF_CAL_MEAS_DUMP_EN 0
|
|
/* define the maximum average number of calibration measurements */
|
|
#define MP_RF_CAL_MEAS_AVG_CNT_MAX 128
|
|
/* define the maximum average number of calibration measurements */
|
|
#define MP_RF_CAL_MEAS_AVG_CNT_DEFAULT 32
|
|
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
|
|
/* define the tmi used for PLC communication with less data */
|
|
#define MP_RF_PLC_NORMAL_PACKET_TMI MAC_TMI_6
|
|
/* define the tmi used for PLC communication with more data */
|
|
#define MP_RF_PLC_LARGE_PACKET_TMI MAC_TMI_0
|
|
/* define plc init band */
|
|
#define MP_RF_PLC_INIT_BAND IOT_SUPPORT_TONE_100_230
|
|
|
|
#else /* SUPPORT_SOUTHERN_POWER_GRID */
|
|
|
|
/* define the tmi used for PLC communication with less data */
|
|
#define MP_RF_PLC_NORMAL_PACKET_TMI MAC_TMI_13
|
|
/* define the tmi used for PLC communication with more data */
|
|
#define MP_RF_PLC_LARGE_PACKET_TMI MAC_TMI_12
|
|
/* define plc init band */
|
|
#define MP_RF_PLC_INIT_BAND IOT_SUPPORT_TONE_240_370
|
|
|
|
#endif
|
|
|
|
#pragma pack(push) /* save the pack status */
|
|
#pragma pack(1) /* 1 byte align */
|
|
|
|
/* command message layout, from dut to golden */
|
|
typedef struct {
|
|
/* magic number, fixed as MP_RF_TEST_MSG_MAGIC_NUMBER */
|
|
uint32_t magic;
|
|
/* message id, see MP_RF_MSG_ID_XXX */
|
|
uint8_t msg_id;
|
|
/* golden tx phr mcs, see MCS_ID_X */
|
|
uint8_t phr_mcs;
|
|
/* golden tx payload mcs, see MCS_ID_X */
|
|
uint8_t pld_mcs;
|
|
/* golden tx pb block size, see BLOCK_SIZE_XXX */
|
|
uint8_t pld_blkz;
|
|
/* golden tx power, uint is dbm */
|
|
int8_t power;
|
|
/* data payload label*/
|
|
uint8_t data[0];
|
|
} mp_rf_test_cmd_hdr_t;
|
|
|
|
/* CSR cmd payload layout */
|
|
typedef struct {
|
|
/* packet count */
|
|
uint16_t packet_num;
|
|
/* mac address of dut */
|
|
uint8_t mac_addr[IOT_MAC_ADDR_LEN];
|
|
/* generation timestamp of the command */
|
|
uint32_t ts;
|
|
/* if set, golden uses test mode power configuration. */
|
|
uint8_t is_test_mode : 1,
|
|
/* reserved field 0 for further use */
|
|
rsvd0 : 7;
|
|
/* time interval when Golden sending packets, unit: us. */
|
|
uint16_t interval;
|
|
/* reserved field 1 for further use */
|
|
uint8_t rsvd1[5];
|
|
} mp_rf_test_cmd_csr_t;
|
|
|
|
/* TX EVM cmd payload layout */
|
|
typedef struct {
|
|
/* mac address of dut */
|
|
uint8_t mac_addr[IOT_MAC_ADDR_LEN];
|
|
/* generation timestamp of the command */
|
|
uint32_t ts;
|
|
/* reserved for further use */
|
|
uint8_t rsvd[8];
|
|
} mp_rf_test_cmd_tx_evm_t;
|
|
|
|
/* change phy cmd payload layout */
|
|
typedef struct {
|
|
/* rf option, see RF_OPTION_XXX */
|
|
uint8_t option;
|
|
/* rf channel, RF_CHANNEL_ID_XXX */
|
|
uint8_t channel;
|
|
} mp_rf_test_cmd_chg_phy_t;
|
|
|
|
/* TX CALI cmd payload layout */
|
|
typedef struct {
|
|
/* magic number of dev_id */
|
|
uint16_t dev_id_magic;
|
|
/* tx cali type, see RF_TEST_TX_CALI_REG_IQ_XXX */
|
|
uint8_t type;
|
|
/* flag to mark whether to use original data */
|
|
uint8_t liner_fit_en;
|
|
/* reserved for further use */
|
|
uint8_t rsvd[8];
|
|
} mp_rf_test_cmd_tx_cali_stat_qr_t;
|
|
|
|
/* response message layout, from golden to dut */
|
|
typedef struct {
|
|
/* magic number, fixed as MP_RF_TEST_MSG_MAGIC_NUMBER */
|
|
uint32_t magic;
|
|
/* message id, see MP_RF_MSG_ID_XXX */
|
|
uint8_t msg_id;
|
|
/* rssi for received from dut packets */
|
|
int8_t tx_rssi;
|
|
/* snr for received from dut packets */
|
|
int8_t tx_snr;
|
|
/* ppm for received from dut packets */
|
|
int8_t tx_ppm;
|
|
/* adc gain for received from dut packets */
|
|
uint8_t tx_gain;
|
|
/* data payload label */
|
|
uint8_t data[0];
|
|
} mp_rf_test_rsp_t;
|
|
|
|
/* TX EVM response payload layout, from golden to dut */
|
|
typedef struct {
|
|
/* rx success count */
|
|
uint16_t rx_cnt;
|
|
/* 10 times the average RSSI of DUT tx evaluated by golden */
|
|
int16_t avg_rssi;
|
|
/* 10 times the average snr of DUT tx evaluated by golden */
|
|
int16_t avg_snr;
|
|
} mp_rf_rsp_tx_evm_t;
|
|
|
|
/* TX CALI result structure */
|
|
typedef struct {
|
|
/* rf phy i value of MAG/PHASE register */
|
|
int8_t i;
|
|
/* rf phy q value of MAG/PHASE register */
|
|
int8_t q;
|
|
/* snr */
|
|
float snr;
|
|
} tx_cali_comen_result_t;
|
|
|
|
/* TX CALI response payload layout, from golden to dut */
|
|
typedef struct {
|
|
/* bitmap representing iq combination */
|
|
uint8_t bm[MP_RF_TX_CALI_SNR_BM_SIZE];
|
|
/* indicates how many sets of iq data are available next */
|
|
uint8_t cnt;
|
|
/* TX CALI result payload */
|
|
tx_cali_comen_result_t result[0];
|
|
} mp_rf_rsp_tx_cali_t;
|
|
|
|
/* csr response payload layout, from golden to dut */
|
|
typedef struct {
|
|
/* packet serial number */
|
|
uint16_t sn;
|
|
} mp_rf_rsp_csr_t;
|
|
|
|
/* define MP rf calibration message id */
|
|
#define MP_RF_CAL_MSG_ID_MEAS_CFG 0
|
|
#define MP_RF_CAL_MSG_ID_MEAS_REQ 1
|
|
#define MP_RF_CAL_MSG_ID_GET_SNR 2
|
|
|
|
/* rf calibration response message header layout */
|
|
typedef struct {
|
|
/* magic number, fixed as MP_RF_TEST_MSG_MAGIC_NUMBER */
|
|
uint32_t magic;
|
|
/* message id, see MP_RF_CAL_MSG_ID_XXX */
|
|
uint8_t msg_id;
|
|
/* dut address */
|
|
uint8_t dut_addr[IOT_MAC_ADDR_LEN];
|
|
/* Measurement sequence number */
|
|
uint32_t sn;
|
|
/* 1. When the direction DUT-->golden, it is an invalid field.
|
|
* 2. When the direction gold -->DUT, it is an error code, see ERR_XX
|
|
*/
|
|
uint8_t option;
|
|
/* payload label */
|
|
uint8_t data[0];
|
|
} mp_rf_cal_msg_hdr_t;
|
|
|
|
/* rf calibration config message layout, DUT --> golden */
|
|
typedef struct {
|
|
/* configure golden to measurement mode, 1 - enable / 0 - disable */
|
|
uint8_t meas_en;
|
|
/* rf option */
|
|
uint8_t option;
|
|
/* rf channel */
|
|
uint8_t ch;
|
|
/* communication power between DUT and golden (HPLC), uint is dBuV */
|
|
uint8_t comm_pwr;
|
|
/* communication power between DUT and golden (HPLC), see MAC_TMI_XX */
|
|
uint8_t comm_tmi;
|
|
/* reserved for further use */
|
|
uint8_t rsvd[8];
|
|
} mp_rf_cal_meas_cfg_t;
|
|
|
|
/* rf calibration measurement req msg layout, including measurement,
|
|
* DUT --> golden.
|
|
*/
|
|
typedef struct {
|
|
/* receiving LO frequency used in measurement, uint is Hz */
|
|
uint32_t lo_freq;
|
|
/* index of dc signal in fft result */
|
|
uint16_t dc_idx;
|
|
/* index of img signal in fft result */
|
|
uint16_t img_idx;
|
|
/* index of tone signal in fft result */
|
|
uint16_t tone_idx;
|
|
/* measurements average number */
|
|
uint8_t avg_cnt;
|
|
/* reserved for further use */
|
|
uint8_t rsvd[7];
|
|
} mp_rf_cal_meas_req_t;
|
|
|
|
/* rf calibration measurement response msg layout, including measurement result
|
|
* info, golden --> DUT.
|
|
*/
|
|
typedef struct {
|
|
/* dut address */
|
|
uint8_t dut_addr[IOT_MAC_ADDR_LEN];
|
|
/* Measurement sequence number */
|
|
uint32_t sn;
|
|
/* tone signal power, no gain compensation */
|
|
uint32_t tone_pwr;
|
|
/* dc signal power, no gain compensation */
|
|
uint32_t dc_pwr;
|
|
/* img signal power, no gain compensation */
|
|
uint32_t img_pwr;
|
|
/* receive gain */
|
|
uint8_t gain;
|
|
/* receive gain after 100x amplification */
|
|
uint16_t gain_x100;
|
|
/* eserved for further use */
|
|
uint8_t rsvd[6];
|
|
} mp_rf_cal_meas_rsp_t;
|
|
|
|
/* rf tx cali info. */
|
|
typedef struct {
|
|
/* rf tx calibration register type, see RF_TEST_TX_CALI_REG_XXX */
|
|
uint8_t reg_type;
|
|
/* rf phy i value of MAG/PHASE register */
|
|
int8_t i;
|
|
/* rf phy q value of MAG/PHASE register */
|
|
int8_t q;
|
|
/* dvice id magic number */
|
|
uint16_t dev_id_magic;
|
|
/* raw snr */
|
|
uint16_t raw_snr;
|
|
} mp_rf_tx_cali_samp_desc_t;
|
|
|
|
#pragma pack(pop) /* restore the pack status */
|
|
|
|
/* NTB timestamp span calculation */
|
|
#define mp_rf_ntb_span_calc(ntb1, ntb2) ((uint32_t)((int32_t)(ntb1) - \
|
|
(int32_t)(ntb2)))
|
|
|
|
/* rf tx cali real snr data */
|
|
typedef struct {
|
|
/* i/q combination number */
|
|
uint16_t magic;
|
|
/* how many groups of snr data have been stored */
|
|
uint8_t cnt;
|
|
/* record real snr data */
|
|
uint16_t snr[MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_DEPTH];
|
|
} snr_record_desc_t;
|
|
|
|
/* mp rf tx descriptor */
|
|
typedef struct {
|
|
rf_tx_mpdu_start mpdu_start;
|
|
rf_tx_mpdu_end mpdu_end;
|
|
rf_tx_pb_start pb_start;
|
|
rf_tx_dummy_node tx_dummy;
|
|
} mp_rf_tx_desc_t;
|
|
|
|
/* mp rf test context structure */
|
|
typedef struct {
|
|
/* mp rf tx descriptor */
|
|
mp_rf_tx_desc_t tx_desc_buf[MP_RF_TX_DESC_CNT];
|
|
/* pointer to tx desc currently being sent */
|
|
mp_rf_tx_desc_t *cur_tx_desc;
|
|
/* plc irq0 handle */
|
|
iot_irq_t plc_isr_0_h;
|
|
/* plc irq1 handle */
|
|
iot_irq_t plc_isr_1_h;
|
|
/* plc irq2 handle */
|
|
iot_irq_t plc_isr_2_h;
|
|
/* rf irq handle */
|
|
iot_irq_t rf_isr_h;
|
|
/* common timer */
|
|
timer_id_t common_timer;
|
|
/* timer timeout times */
|
|
uint8_t timeout_count;
|
|
/* option, see RF_OPTION_XXX */
|
|
uint8_t option;
|
|
/* channel numbel */
|
|
uint8_t channel;
|
|
/* target option, see RF_OPTION_XXX */
|
|
uint8_t target_option;
|
|
/* target channel numbel */
|
|
uint8_t target_channel;
|
|
/* phy header mcs, see MCS_ID_XXX */
|
|
uint8_t phr_mcs;
|
|
/* payload mcs, see MCS_ID_XXX */
|
|
uint8_t pld_mcs;
|
|
/* payload block size, see BLOCK_SIZE_XXX */
|
|
uint8_t pld_blkz;
|
|
/* next allocable tx descriptor index */
|
|
uint8_t tx_desc_idx;
|
|
/* flag to mark if rf phy has been initialized */
|
|
volatile uint32_t rf_phy_inited : 1,
|
|
/* flag to mark if rf phy changing */
|
|
rf_phy_changing : 1,
|
|
/* flag to mark if golden is in calibration mode */
|
|
is_cal_mode : 1,
|
|
/* flag to mark if current device is golden */
|
|
is_golden : 1,
|
|
/* flag to mark if led status of goolden */
|
|
led_status : 1,
|
|
/* flag to mark if tx done */
|
|
tx_done : 1,
|
|
/* flag to mark if rx done */
|
|
rx_done : 1,
|
|
/* reserved for further use */
|
|
rsvd : 25;
|
|
/* timestamp of rf phy change */
|
|
uint32_t rf_phy_chg_ts;
|
|
/* rf receive ring buf config structure */
|
|
rx_buf_ring_t rx_ring;
|
|
/* the dut address of the last tx evm test */
|
|
uint8_t dut_addr_in_tx_evm[IOT_MAC_ADDR_LEN];
|
|
/* generation timestamp of the last TX EVM command from DUT */
|
|
uint32_t tx_evm_ts;
|
|
/* the dut address of the last CSR test */
|
|
uint8_t dut_addr_in_csr[IOT_MAC_ADDR_LEN];
|
|
/* generation timestamp of the last CSR command from DUT */
|
|
uint32_t csr_cmd_ts;
|
|
/* marks the amount of data received in the TX EVM test */
|
|
uint16_t recv_data_cnt;
|
|
/* record the SNR of the signal received in the TX EVM or CSR test */
|
|
int8_t snr_buf[max(MP_RF_CSR_TX_MAX_COUNT, \
|
|
MP_RF_TX_EVM_SMAP_MAX_CNT)];
|
|
/* record the RSSI of the signal received in the TX EVM or CSR test */
|
|
int8_t rssi_buf[max(MP_RF_CSR_TX_MAX_COUNT, \
|
|
MP_RF_TX_EVM_SMAP_MAX_CNT)];
|
|
uint8_t dut_addr_in_cal[IOT_MAC_ADDR_LEN];
|
|
/* measured buffer for tone power */
|
|
uint32_t tone_pwr_buf[MP_RF_CAL_MEAS_AVG_CNT_MAX];
|
|
/* measured buffer for dc power */
|
|
uint32_t dc_pwr_buf[MP_RF_CAL_MEAS_AVG_CNT_MAX];
|
|
/* measured buffer for inmage power */
|
|
uint32_t img_pwr_buf[MP_RF_CAL_MEAS_AVG_CNT_MAX];
|
|
/* measured buffer for rx gain */
|
|
uint8_t gain_buf[MP_RF_CAL_MEAS_AVG_CNT_MAX];
|
|
/* power information of the last golden measurement */
|
|
uint32_t last_meas_sn;
|
|
uint32_t last_tone_pwr;
|
|
uint32_t last_dc_pwr;
|
|
uint32_t last_img_pwr;
|
|
float last_gain;
|
|
/* led gpio */
|
|
int led_gpio;
|
|
/* tx pb buffer */
|
|
uint8_t rf_pb_buf[520];
|
|
/* rf tx packet count */
|
|
uint32_t tx_done_cnt;
|
|
/* rf rx packet count */
|
|
uint32_t rx_done_cnt;
|
|
/* store data generated after curve fitting */
|
|
float snr_fit_buf[MP_RF_TEST_CASE_TX_CALI_SNR_SAMP_BUF_SIZE];
|
|
/* array y for curve fitting */
|
|
float fit_y[RF_PHY_IQ_PHASE_COMPEN_CODE_MAX];
|
|
/* array x for curve fitting */
|
|
float fit_x[RF_PHY_IQ_PHASE_COMPEN_CODE_MAX];
|
|
/* the bit mapping of the i/q combination indicates whether the
|
|
* corresponding i/q combination has received enough data packets
|
|
* in the tx snr calibration test.
|
|
*/
|
|
uint8_t snr_samp_bitmap[MP_RF_TX_CALI_SNR_BM_SIZE];
|
|
/* temporarily save the maximum value */
|
|
tx_cali_comen_result_t max_snr_buf[MP_RF_TX_CALI_SNR_BEST_RESULT_MAX];
|
|
/* record up to 81 i/q combinations of snr data */
|
|
snr_record_desc_t real_snr[MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_SIZE];
|
|
/* magic number of current tx cali device */
|
|
uint16_t cur_tx_cali_dev;
|
|
/* rf test tx calibration register type */
|
|
uint8_t cur_tx_cali_reg_type;
|
|
} mp_rf_ctxt_t;
|
|
|
|
/* global variable for mp rf ctxt */
|
|
static mp_rf_ctxt_t* g_mp_rf_ctxt = NULL;
|
|
|
|
/* variable and function declarations */
|
|
extern os_task_h _init_handle;
|
|
|
|
#if MP_RF_CAL_MEAS_DUMP_EN
|
|
|
|
static void mp_rf_cal_meas_dump(const char *label, void *buf, uint32_t len,
|
|
uint32_t elm_size)
|
|
{
|
|
uint32_t i, *p_uint32 = buf;
|
|
uint16_t *p_uint16 = buf;
|
|
uint8_t *p_uint8 = buf;
|
|
uint32_t temp;
|
|
uint8_t start = 0;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (0 == (i % 64)) {
|
|
iot_printf("%s", label);
|
|
start = 1;
|
|
}
|
|
if (sizeof(uint32_t) == elm_size) {
|
|
temp = *p_uint32++;
|
|
} else if (sizeof(uint16_t) == elm_size) {
|
|
temp = (uint32_t)*p_uint16++;
|
|
} else {
|
|
temp = (uint32_t)*p_uint8++;
|
|
}
|
|
iot_printf("%lu,", temp);
|
|
if (0 == ((i + 1) % 64)) {
|
|
start = 0;
|
|
iot_printf("\n");
|
|
}
|
|
}
|
|
if (start) {
|
|
iot_printf("\n");
|
|
}
|
|
return;
|
|
}
|
|
|
|
#else /* MP_RF_CAL_MEAS_DUMP_EN */
|
|
|
|
#define mp_rf_cal_meas_dump(label, buf, len, elm_size)
|
|
|
|
#endif /* MP_RF_CAL_MEAS_DUMP_EN */
|
|
|
|
static uint32_t IRAM_ATTR mp_rf_isr(uint32_t vector, iot_addrword_t data)
|
|
{
|
|
(void)vector;
|
|
(void)data;
|
|
uint32_t hwq_id;
|
|
uint32_t irq_sts, txq_map = 0, ring_map = 0;
|
|
uint32_t sw_sts = RF_MAC_READ_REG(CFG_RF_MAC_COMMON_INT_REG_26_ADDR);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_24_ADDR, sw_sts);
|
|
if (sw_sts & (1 << RF_MAC_SW_ISR_TX_MPDU_COMPLETE)) {
|
|
irq_sts = RF_MAC_READ_REG(CFG_RF_MAC_COMMON_INT_REG_16_ADDR);
|
|
txq_map = irq_sts & RF_MAC_INT_HWQ_BIT_MASK;
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_14_ADDR, txq_map);
|
|
for (hwq_id = 0; txq_map && hwq_id < 7; hwq_id++) {
|
|
if ((0x1 << hwq_id) & txq_map) {
|
|
if (hwq_id == 0) {
|
|
g_mp_rf_ctxt->tx_done = 1;
|
|
g_mp_rf_ctxt->tx_done_cnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sw_sts & (1 << RF_MAC_SW_ISR_RX_MPDU_COMPLETE)) {
|
|
irq_sts = RF_MAC_READ_REG(CFG_RF_MAC_COMMON_INT_REG_16_ADDR);
|
|
ring_map = irq_sts & RF_MAC_INT_RX_RING_BIT_MASK;
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_14_ADDR, ring_map);
|
|
g_mp_rf_ctxt->rx_done_cnt++;
|
|
if (g_mp_rf_ctxt->is_golden) {
|
|
os_set_task_event_with_v_from_isr(_init_handle,
|
|
1 << MP_RF_EVT_ID_RF_RX);
|
|
} else {
|
|
g_mp_rf_ctxt->rx_done = 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void mp_rf_isr_start()
|
|
{
|
|
g_mp_rf_ctxt->rf_isr_h = iot_interrupt_create(HAL_VECTOR_RFMAC_INT0,
|
|
HAL_INTR_PRI_7, (iot_addrword_t)NULL, mp_rf_isr);
|
|
iot_interrupt_attach(g_mp_rf_ctxt->rf_isr_h);
|
|
iot_interrupt_unmask(g_mp_rf_ctxt->rf_isr_h);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_10_ADDR, 0xffffffff);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_14_ADDR, 0xffffffff);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_18_ADDR, 0xffffffff);
|
|
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_20_ADDR, 0xffffffff);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_24_ADDR, 0xffffffff);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_COMMON_INT_REG_28_ADDR, 0xffffffff);
|
|
}
|
|
|
|
static void mp_rf_txq_init(void)
|
|
{
|
|
uint32_t tmp;
|
|
tmp = RF_MAC_READ_REG(CFG_RF_MAC_DEBUG_CFG_ADDR);
|
|
REG_FIELD_SET(RF_MAC_DEBUG_EN, tmp, 1);
|
|
REG_FIELD_SET(RF_MAC_DEBUG_START, tmp, 1);
|
|
REG_FIELD_SET(RF_MAC_DEBUG_TXQ_BITMAP, tmp, 1);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_DEBUG_CFG_ADDR, tmp);
|
|
}
|
|
|
|
static void mp_rf_recv_ring_clear()
|
|
{
|
|
iot_pkt_t *iot_pkt_array[1] = { 0 };
|
|
|
|
/* clear invalid data */
|
|
while(rf_pop_buf_from_ring(&g_mp_rf_ctxt->rx_ring, 1, iot_pkt_array)) {
|
|
iot_pkt_free(iot_pkt_array[0]);
|
|
}
|
|
g_mp_rf_ctxt->rx_done = 0;
|
|
g_mp_rf_ctxt->rx_done_cnt = 0;
|
|
}
|
|
|
|
static uint8_t mp_rf_check_rf_rx_done()
|
|
{
|
|
uint8_t temp;
|
|
/* disable irq */
|
|
if (!g_mp_rf_ctxt->rx_done) {
|
|
return 0;
|
|
}
|
|
os_disable_irq();
|
|
temp = g_mp_rf_ctxt->rx_done;
|
|
g_mp_rf_ctxt->rx_done = 0;
|
|
os_enable_irq();
|
|
return temp;
|
|
}
|
|
|
|
static uint8_t mp_rf_recv_ring_init()
|
|
{
|
|
uint8_t ret = 0;
|
|
|
|
if (!g_mp_rf_ctxt->rx_ring.cfg_enabled) {
|
|
ring_config config_sof[] =
|
|
{
|
|
{ CONFIG_RX_ATTENTION, RF_RX_ATTENTION_OFFSET, 0},
|
|
{ CONFIG_RX_MPDU_START, 0, 0 },
|
|
{ CONFIG_RX_MPDU_END, 0, 0 },
|
|
{ CONFIG_RX_PB_START, 0, 0 },
|
|
{ CONFIG_RX_PB_END, 0, 0 },
|
|
{ CONFIG_FC, 0, 0 },
|
|
{ CONFIG_PAYLOAD, RF_RX_PB_PAYLOAD_OFFSET, 0},
|
|
};
|
|
ret = rf_rx_buf_ring_init(&g_mp_rf_ctxt->rx_ring,
|
|
RF_RING_0, PLC_SHORT_RX_BUF_COUNT, PLC_SHORT_BUF_SIZE, NULL, config_sof,
|
|
0, 0);
|
|
if (ERR_OK == ret) {
|
|
mac_rf_rx_ring_enable(&g_mp_rf_ctxt->rx_ring, true);
|
|
iot_printf("enable rf ring id %d\n", RF_RING_0);
|
|
return ERR_OK;
|
|
}
|
|
} else {
|
|
iot_printf("rf ring id %d re enable\n", RF_RING_0);
|
|
rf_rx_ring_fill_hw_cfg(&g_mp_rf_ctxt->rx_ring);
|
|
mac_rf_rx_ring_enable(&g_mp_rf_ctxt->rx_ring, true);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void mp_rf_clear_rf_common()
|
|
{
|
|
uint32_t tmp;
|
|
|
|
if (!g_mp_rf_ctxt)
|
|
return;
|
|
|
|
mac_rf_txq_force_disable(0);
|
|
mac_rf_rx_ring_enable(&g_mp_rf_ctxt->rx_ring, 0);
|
|
tmp = RF_MAC_READ_REG(CFG_RF_MAC_DEBUG_CFG_ADDR);
|
|
REG_FIELD_SET(RF_MAC_DEBUG_EN, tmp, 0);
|
|
REG_FIELD_SET(RF_MAC_DEBUG_START, tmp, 0);
|
|
REG_FIELD_SET(RF_MAC_DEBUG_TXQ_BITMAP, tmp, 0);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_DEBUG_CFG_ADDR, tmp);
|
|
|
|
/* if receiving a packet, wait for the last packet to be received */
|
|
os_delay(100);
|
|
mp_rf_recv_ring_clear();
|
|
g_mp_rf_ctxt->rf_phy_inited = 0;
|
|
}
|
|
|
|
static void mp_rf_common_init(uint8_t option, uint8_t channel)
|
|
{
|
|
if (!PLC_RF_OPTION_IS_VALID(option)) {
|
|
iot_printf("%s fail, invalid option %lu\n", __FUNCTION__, option);
|
|
goto out;
|
|
}
|
|
/* check channel */
|
|
if (channel >= phy_rf_get_channel_id_max(option) ||
|
|
channel < RF_CHANNEL_ID_1) {
|
|
iot_printf("%s fail, invalid channel %lu\n", __FUNCTION__, channel);
|
|
goto out;
|
|
}
|
|
if (g_mp_rf_ctxt->rf_phy_inited) {
|
|
if (option == g_mp_rf_ctxt->option &&
|
|
channel == g_mp_rf_ctxt->channel) {
|
|
mac_rf_rx_ring_enable(&g_mp_rf_ctxt->rx_ring, 1);
|
|
goto out;
|
|
} else {
|
|
mp_rf_clear_rf_common();
|
|
}
|
|
}
|
|
uint32_t proto = phy_proto_type_get();
|
|
/* plc cpu and bbcpu sync init, rf rxdc disable */
|
|
phy_rf_init(proto, option, channel, 1, 0, 0);
|
|
mp_rf_recv_ring_init();
|
|
mp_rf_isr_start();
|
|
mp_rf_txq_init();
|
|
g_mp_rf_ctxt->option = option;
|
|
g_mp_rf_ctxt->channel = channel;
|
|
g_mp_rf_ctxt->phr_mcs = MCS_ID_0;
|
|
g_mp_rf_ctxt->pld_mcs = MCS_ID_2;
|
|
g_mp_rf_ctxt->pld_blkz = BLOCK_SIZE_3;
|
|
g_mp_rf_ctxt->cur_tx_desc = NULL;
|
|
g_mp_rf_ctxt->tx_desc_idx = 0;
|
|
g_mp_rf_ctxt->rf_phy_inited = 1;
|
|
iot_printf("%s ok, option %lu, channel %lu\n", __FUNCTION__, option,
|
|
channel);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static mp_rf_tx_desc_t *mp_rf_alloc_tx_desc()
|
|
{
|
|
mp_rf_tx_desc_t *tx_desc = NULL;
|
|
tx_desc = &g_mp_rf_ctxt->tx_desc_buf[g_mp_rf_ctxt->tx_desc_idx];
|
|
g_mp_rf_ctxt->tx_desc_idx++;
|
|
if (g_mp_rf_ctxt->tx_desc_idx >= MP_RF_TX_DESC_CNT) {
|
|
g_mp_rf_ctxt->tx_desc_idx = 0;
|
|
}
|
|
mac_rf_tx_mpdu_fill_dummy(&tx_desc->tx_dummy);
|
|
os_mem_set(&tx_desc->mpdu_end, 0x0, sizeof(tx_desc->mpdu_end));
|
|
mac_rf_tx_mpdu_fill_pb_start(&tx_desc->pb_start, g_mp_rf_ctxt->rf_pb_buf,
|
|
0, 1, 1, PHY_PROTO_TYPE_GET());
|
|
return tx_desc;
|
|
}
|
|
|
|
static void mp_rf_tx_mpdu_with_tx_cali_samp(RF_TEST_TX_CALI_REG_T type,
|
|
uint16_t i_reg, uint16_t q_reg, uint16_t dev_id_magic)
|
|
{
|
|
iot_ftm_mp_rf_tx_cal_update_t cal_update = { 0 };
|
|
|
|
uint32_t tmp;
|
|
mp_rf_tx_desc_t *tx_desc;
|
|
tx_desc = mp_rf_alloc_tx_desc();
|
|
/* reinit tx dummy node */
|
|
mac_rf_tx_mpdu_fill_macinfo(
|
|
&tx_desc->mpdu_start,
|
|
(rf_tx_mpdu_start*)&tx_desc->tx_dummy,
|
|
NULL,
|
|
&tx_desc->mpdu_end,
|
|
PHY_PROTO_TYPE_GET(), /* protocol type */
|
|
0, /* need ack */
|
|
0, /* retry cnt */
|
|
0, /* tx power */
|
|
0, /* retry bit en */
|
|
0, /* is msdu */
|
|
0, /* pb buf reuse */
|
|
0, /* tx desc reuse */
|
|
0, /* sw buf offset */
|
|
0, /* is list start */
|
|
0, /* is list end */
|
|
g_mp_rf_ctxt->phr_mcs, /* payload hdr mcs */
|
|
0, /* pts */
|
|
0, /* pts off */
|
|
0, /* payload mcs */
|
|
0, /* payload block size */
|
|
0, /* crc32 en */
|
|
0, /* crc32 ofs */
|
|
0, /* hwq id */
|
|
g_mp_rf_ctxt->option, /* option */
|
|
0, /* pb num */
|
|
0); /* tx frame len */
|
|
/* fill phyinfo */
|
|
mac_rf_tx_mpdu_fill_phyinfo(&tx_desc->mpdu_start, 0);
|
|
|
|
/* fill tx cal update info */
|
|
if (type == RF_TEST_TX_CALI_REG_IQ_MAG) {
|
|
cal_update.tx_iq_mag_update = 1;
|
|
cal_update.tx_i_mag = i_reg;
|
|
cal_update.tx_q_mag = q_reg;
|
|
} else if (type == RF_TEST_TX_CALI_REG_IQ_PHASE) {
|
|
cal_update.tx_iq_phase_update = 1;
|
|
cal_update.tx_i_phase = i_reg;
|
|
cal_update.tx_q_phase = q_reg;
|
|
} else if (type == RF_TEST_TX_CALI_REG_IQ_DC) {
|
|
cal_update.tx_iq_dc_update = 1;
|
|
cal_update.tx_i_dc = i_reg;
|
|
cal_update.tx_q_dc = q_reg;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
mp_rf_dut_cal_reg_update(&cal_update);
|
|
|
|
mac_rf_fill_rftest_txcali_phrinfo(&tx_desc->mpdu_start,
|
|
PHY_PROTO_TYPE_GET(), glb_cfg.nid, type, dev_id_magic,
|
|
i_reg | q_reg << 16);
|
|
if (g_mp_rf_ctxt->cur_tx_desc == NULL) {
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_TXQ0_PTR_ADDR,
|
|
(uint32_t)&tx_desc->mpdu_start);
|
|
tmp = RF_MAC_READ_REG(CFG_RF_MAC_TXQ_ENABLE_LOAD_REG_ADDR);
|
|
REG_FIELD_SET(RF_MAC_TXQ_LOAD, tmp, 1);
|
|
REG_FIELD_SET(RF_MAC_TXQ_ENABLE, tmp, 1);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_TXQ_ENABLE_LOAD_REG_ADDR, tmp);
|
|
} else {
|
|
g_mp_rf_ctxt->cur_tx_desc->tx_dummy.next = &tx_desc->mpdu_start;
|
|
}
|
|
g_mp_rf_ctxt->cur_tx_desc = tx_desc;
|
|
iot_printf("--tx cali phr,mcs:%lu,reg_type:%lu,tx_cali_reg:[%d %d]"
|
|
",tx_done_cnt:%lu\n", g_mp_rf_ctxt->phr_mcs, type,
|
|
(int16_t)i_reg, (int16_t)q_reg, g_mp_rf_ctxt->tx_done_cnt);
|
|
while (g_mp_rf_ctxt->tx_done == 0);
|
|
g_mp_rf_ctxt->tx_done = 0;
|
|
}
|
|
|
|
static void mp_rf_tx_mpdu(void)
|
|
{
|
|
uint32_t tmp;
|
|
mp_rf_tx_desc_t *tx_desc;
|
|
tx_desc = mp_rf_alloc_tx_desc();
|
|
/* reinit tx dummy node */
|
|
mac_rf_tx_mpdu_fill_macinfo(
|
|
&tx_desc->mpdu_start,
|
|
(rf_tx_mpdu_start*)&tx_desc->tx_dummy,
|
|
&tx_desc->pb_start,
|
|
&tx_desc->mpdu_end,
|
|
PHY_PROTO_TYPE_GET(), /* protocol type */
|
|
0, /* need ack */
|
|
0, /* retry cnt */
|
|
0, /* tx power */
|
|
0, /* retry bit en */
|
|
0, /* is msdu */
|
|
0, /* pb buf reuse */
|
|
0, /* tx desc reuse */
|
|
0, /* sw buf offset */
|
|
1, /* is list start */
|
|
1, /* is list end */
|
|
g_mp_rf_ctxt->phr_mcs, /* payload hdr mcs */
|
|
0, /* pts */
|
|
0, /* pts off */
|
|
g_mp_rf_ctxt->pld_mcs, /* payload mcs */
|
|
g_mp_rf_ctxt->pld_blkz, /* payload block size */
|
|
1, /* crc32 en */
|
|
0, /* crc32 ofs */
|
|
0, /* hwq id */
|
|
g_mp_rf_ctxt->option, /* option */
|
|
1, /* pb num */
|
|
0); /* tx frame len */
|
|
/* fill phyinfo */
|
|
mac_rf_tx_mpdu_fill_phyinfo(&tx_desc->mpdu_start, 0);
|
|
/* fill fc */
|
|
mac_rf_tx_mpdu_fill_phrinfo(&tx_desc->mpdu_start,
|
|
PHY_PROTO_TYPE_GET(), /* protocol type */
|
|
FC_DELIM_SOF, /* delimiter type */
|
|
0, /* network */
|
|
glb_cfg.nid, /* nid */
|
|
0, /* bcn_period_cnt */
|
|
0, /* src tei */
|
|
PLC_TEI_BCAST, /* dst tei */
|
|
g_mp_rf_ctxt->pld_mcs, /* payload mcs */
|
|
0, /* link id */
|
|
g_mp_rf_ctxt->pld_blkz, /* payload pb size */
|
|
0, /* is retry */
|
|
0, /* is enrcy */
|
|
1); /* is bcast */
|
|
if (g_mp_rf_ctxt->cur_tx_desc == NULL) {
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_TXQ0_PTR_ADDR,
|
|
(uint32_t)&tx_desc->mpdu_start);
|
|
tmp = RF_MAC_READ_REG(CFG_RF_MAC_TXQ_ENABLE_LOAD_REG_ADDR);
|
|
REG_FIELD_SET(RF_MAC_TXQ_LOAD, tmp, 1);
|
|
REG_FIELD_SET(RF_MAC_TXQ_ENABLE, tmp, 1);
|
|
RF_MAC_WRITE_REG(CFG_RF_MAC_TXQ_ENABLE_LOAD_REG_ADDR, tmp);
|
|
} else {
|
|
g_mp_rf_ctxt->cur_tx_desc->tx_dummy.next = &tx_desc->mpdu_start;
|
|
}
|
|
g_mp_rf_ctxt->cur_tx_desc = tx_desc;
|
|
iot_printf("--tx sof,mcs:%lu-%lu,pbsz:%lu,ts:%lu,tx_done_cnt:%lu\n",
|
|
g_mp_rf_ctxt->phr_mcs, g_mp_rf_ctxt->pld_mcs, g_mp_rf_ctxt->pld_blkz,
|
|
RGF_MAC_READ_REG(CFG_RD_NTB_ADDR), g_mp_rf_ctxt->tx_done_cnt);
|
|
while (g_mp_rf_ctxt->tx_done == 0);
|
|
g_mp_rf_ctxt->tx_done = 0;
|
|
}
|
|
|
|
static void mp_rf_tx_packet(uint32_t interval)
|
|
{
|
|
mp_rf_tx_mpdu();
|
|
if (interval) {
|
|
iot_delay_us(interval);
|
|
}
|
|
}
|
|
|
|
static uint8_t mp_rf_check_rx_packet(iot_pkt_t *pkt_buf)
|
|
{
|
|
IOT_ASSERT(pkt_buf);
|
|
rf_rx_buf_hdr_t *rx_buf;
|
|
rf_rx_attention *att;
|
|
rf_rx_pb_end *pb_ed;
|
|
|
|
rx_buf = (rf_rx_buf_hdr_t *)iot_pkt_data(pkt_buf);
|
|
att = &(rx_buf->att);
|
|
pb_ed = &(rx_buf->pb_ed);
|
|
|
|
if (!mac_rf_rx_pb_end_get_rx_pb_done(pb_ed)) {
|
|
iot_printf("%s not done PB\n", __FUNCTION__);
|
|
return 1;
|
|
}
|
|
if (!mac_rf_rx_att_get_rx_mpdu_done(att)) {
|
|
iot_printf("%s not done RX MPDU\n", __FUNCTION__);
|
|
return 1;
|
|
}
|
|
if (mac_rf_rx_att_get_rx_status(att)) {
|
|
iot_printf("%s RX STATUS err=%d\n", __FUNCTION__,
|
|
mac_rf_rx_att_get_rx_status(att));
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static uint8_t mp_rf_test_tx_cali_info_parse(rf_rx_mpdu_start *rx_mpdu,
|
|
uint32_t proto, mp_rf_tx_cali_samp_desc_t *cali_info)
|
|
{
|
|
int8_t i = 0, q = 0;
|
|
uint8_t reg_type = 0, test_type, ret = ERR_OK;
|
|
uint16_t dev_id_magic = 0;
|
|
|
|
switch (proto) {
|
|
#if SUPPORT_SMART_GRID
|
|
case PLC_PROTO_TYPE_SG:
|
|
{
|
|
frame_control_t *sg_fc;
|
|
sg_fc = (frame_control_t *)mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu);
|
|
test_type = sg_fc->vf.rf_test_tx_cali.test_type;
|
|
if (test_type != RF_TEST_TYPE_TX_CALI) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
dev_id_magic = sg_fc->vf.rf_test_tx_cali.dev_id_magic;
|
|
reg_type = sg_fc->vf.rf_test_tx_cali.reg_type;
|
|
i = (int8_t)(sg_fc->vf.rf_test_tx_cali.reg_magic & 0xFF);
|
|
q = (int8_t)((sg_fc->vf.rf_test_tx_cali.reg_magic >> 16) & 0xFF);
|
|
break;
|
|
}
|
|
#endif
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
case PLC_PROTO_TYPE_SPG:
|
|
{
|
|
spg_frame_control_t *spg_fc;
|
|
spg_fc = (spg_frame_control_t *)mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu);
|
|
test_type = spg_fc->vf.rf_test_tx_cali.test_type;
|
|
if (test_type != RF_TEST_TYPE_TX_CALI) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
dev_id_magic = spg_fc->vf.rf_test_tx_cali.dev_id_magic;
|
|
reg_type = spg_fc->vf.rf_test_tx_cali.reg_type;
|
|
i = (int8_t)(spg_fc->vf.rf_test_tx_cali.reg_magic & 0xFF);
|
|
q = (int8_t)((spg_fc->vf.rf_test_tx_cali.reg_magic >> 16) & 0xFF);
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
{
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (reg_type) {
|
|
case RF_TEST_TX_CALI_REG_IQ_MAG:
|
|
{
|
|
if (!rf_phy_iq_mag_compen_code_valid(i) ||
|
|
!rf_phy_iq_mag_compen_code_valid(q)) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
break;
|
|
}
|
|
case RF_TEST_TX_CALI_REG_IQ_PHASE:
|
|
{
|
|
if (!rf_phy_iq_phase_compen_code_valid(i) ||
|
|
!rf_phy_iq_phase_compen_code_valid(q)) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
cali_info->reg_type = reg_type;
|
|
cali_info->i = i;
|
|
cali_info->q = q;
|
|
cali_info->dev_id_magic = dev_id_magic;
|
|
cali_info->raw_snr = mac_rf_rx_mpdu_st_get_raw_snr(rx_mpdu);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void mp_rf_rx_show_message_info(iot_pkt_t *pkt_buf)
|
|
{
|
|
IOT_ASSERT(pkt_buf);
|
|
int8_t rssi, snr, i;
|
|
uint8_t rx_gain;
|
|
uint8_t *data;
|
|
int16_t dlt;
|
|
int32_t ppm;
|
|
/* mac proto */
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
rf_rx_buf_hdr_t *rx_buf =
|
|
(rf_rx_buf_hdr_t *)iot_pkt_data(pkt_buf);
|
|
rf_rx_attention *rx_att = &(rx_buf->att);
|
|
rf_rx_mpdu_start *rx_mpdu = &(rx_buf->mpdu_st);
|
|
rf_rx_pb_start *pb_st = &(rx_buf->pb_st);
|
|
rf_rx_pb_end *pb_end = &(rx_buf->pb_ed);
|
|
/* get rx fc message */
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
mac_rf_get_rx_frm_msg_from_fc(proto,
|
|
mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu),
|
|
&rx_fc_msg);
|
|
|
|
rssi = mac_rf_rx_mpdu_st_get_rssi(rx_mpdu);
|
|
snr = mac_rf_rx_mpdu_st_get_avg_snr(rx_mpdu);
|
|
rx_gain = mac_rf_rx_mpdu_st_get_rx_gain(rx_mpdu);
|
|
dlt = mac_rf_rx_pb_end_get_mismatch_dlt(pb_end);
|
|
ppm = mac_rf_rx_mpdu_st_get_rx_ppmhz(rx_mpdu);
|
|
|
|
switch(rx_fc_msg.delimiter) {
|
|
case FC_DELIM_BEACON:
|
|
{
|
|
iot_printf("rx_bcn nid:0x%x, stei:%d, dtei:%d, phr_mcs:%d, "
|
|
"pld_mcs:%d, gain:%d, rssi:%d, snr:%d, dlt:%d, ppm:%d, "
|
|
"pb_crc_err:%lu\n", rx_fc_msg.nid, rx_fc_msg.src_tei,
|
|
rx_fc_msg.dst_tei, rx_att->phr_mcs, rx_fc_msg.rf_mcs,
|
|
rx_gain, rssi, snr, dlt, ppm, pb_end->rx_beacon_pld_crc_err);
|
|
break;
|
|
}
|
|
case FC_DELIM_SOF:
|
|
{
|
|
iot_printf("rx_sof nid:0x%x, stei:%d, dtei:%d, phr_mcs:%d"
|
|
", pld_mcs:%d, ssn:%d, gain:%d, rssi:%d, "
|
|
"snr:%d, dlt:%d, ppm:%d, pb_crc_err:%lu\n", rx_fc_msg.nid,
|
|
rx_fc_msg.src_tei, rx_fc_msg.dst_tei,
|
|
rx_att->phr_mcs, rx_fc_msg.rf_mcs, pb_st->ssn, rx_gain, rssi,
|
|
snr, dlt, ppm, pb_end->rx_pb_crc_err);
|
|
break;
|
|
}
|
|
case FC_DELIM_RF_TEST:
|
|
{
|
|
iot_printf("rx_rf_test nid:0x%x, phr_mcs:%d, gain:%d, rssi:%d,"
|
|
" snr:%d, ppm:%d, phr_info:", rx_fc_msg.nid, rx_att->phr_mcs,
|
|
rx_gain, rssi, snr, ppm);
|
|
data = (uint8_t *)mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu);
|
|
for (i = 0; i < 16; i++)
|
|
iot_printf("%x ", data[i]);
|
|
iot_printf("\n");
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void mp_rf_recover_def_rate()
|
|
{
|
|
if (g_mp_rf_ctxt->option == RF_OPTION_3) {
|
|
g_mp_rf_ctxt->phr_mcs = MCS_ID_2;
|
|
g_mp_rf_ctxt->pld_mcs = MCS_ID_2;
|
|
g_mp_rf_ctxt->pld_blkz = BLOCK_SIZE_1;
|
|
} else {
|
|
g_mp_rf_ctxt->phr_mcs = MCS_ID_0;
|
|
g_mp_rf_ctxt->pld_mcs = MCS_ID_1;
|
|
g_mp_rf_ctxt->pld_blkz = BLOCK_SIZE_1;
|
|
}
|
|
}
|
|
|
|
static int16_t mp_rf_calc_avg_value(int8_t *data, uint16_t cnt)
|
|
{
|
|
uint16_t i;
|
|
int32_t sum = 0, avg;
|
|
|
|
if (!cnt) {
|
|
avg = 0;
|
|
goto ret;
|
|
}
|
|
|
|
if (cnt <= 6) {
|
|
for (i = 0; i < cnt; i++) {
|
|
sum += data[i];
|
|
}
|
|
avg = 10 * sum / cnt;
|
|
goto ret;
|
|
}
|
|
|
|
iot_bubble_sort_int8(data, cnt, 1);
|
|
for (i = 2; i < cnt - 2; i++) {
|
|
sum += data[i];
|
|
}
|
|
avg = 10 * sum / (cnt - 4);
|
|
|
|
ret:
|
|
return (int16_t)avg;
|
|
}
|
|
|
|
static uint32_t mp_rf_calc_avg_u32(uint32_t *data, uint8_t cnt)
|
|
{
|
|
uint8_t i;
|
|
uint64_t sum = 0;
|
|
for (i = 0; i < cnt; i++) {
|
|
sum += (uint64_t)data[i];
|
|
}
|
|
return (uint32_t)((float)sum / cnt + 0.5);
|
|
}
|
|
|
|
static float mp_rf_calc_avg_u8(uint8_t *data, uint8_t cnt)
|
|
{
|
|
uint8_t i;
|
|
uint32_t sum = 0;
|
|
for (i = 0; i < cnt; i++) {
|
|
sum += (uint32_t)data[i];
|
|
}
|
|
return (float)sum / cnt;
|
|
}
|
|
|
|
static void mp_rf_add_tx_evm_samp(mp_rf_test_cmd_tx_evm_t *dut,
|
|
int8_t snr, int8_t rssi)
|
|
{
|
|
if (g_mp_rf_ctxt->tx_evm_ts != dut->ts ||
|
|
!iot_mac_addr_cmp(g_mp_rf_ctxt->dut_addr_in_tx_evm, dut->mac_addr)) {
|
|
g_mp_rf_ctxt->tx_evm_ts = dut->ts;
|
|
iot_mac_addr_cpy(g_mp_rf_ctxt->dut_addr_in_tx_evm, dut->mac_addr);
|
|
g_mp_rf_ctxt->recv_data_cnt = 0;
|
|
}
|
|
|
|
g_mp_rf_ctxt->snr_buf[g_mp_rf_ctxt->recv_data_cnt] = snr;
|
|
g_mp_rf_ctxt->rssi_buf[g_mp_rf_ctxt->recv_data_cnt] = rssi;
|
|
g_mp_rf_ctxt->recv_data_cnt++;
|
|
}
|
|
|
|
static void mp_rf_get_tx_evm_res(mp_rf_test_cmd_tx_evm_t *dut,
|
|
mp_rf_rsp_tx_evm_t *resp)
|
|
{
|
|
if (g_mp_rf_ctxt->tx_evm_ts != dut->ts ||
|
|
!iot_mac_addr_cmp(g_mp_rf_ctxt->dut_addr_in_tx_evm, dut->mac_addr)) {
|
|
g_mp_rf_ctxt->tx_evm_ts = dut->ts;
|
|
iot_mac_addr_cpy(g_mp_rf_ctxt->dut_addr_in_tx_evm, dut->mac_addr);
|
|
g_mp_rf_ctxt->recv_data_cnt = 0;
|
|
resp->rx_cnt = 0;
|
|
resp->avg_snr = 0;
|
|
resp->avg_rssi = 0;
|
|
return;
|
|
}
|
|
|
|
resp->rx_cnt = g_mp_rf_ctxt->recv_data_cnt;
|
|
resp->avg_snr = mp_rf_calc_avg_value(g_mp_rf_ctxt->snr_buf,
|
|
g_mp_rf_ctxt->recv_data_cnt);
|
|
resp->avg_rssi = mp_rf_calc_avg_value(g_mp_rf_ctxt->rssi_buf,
|
|
g_mp_rf_ctxt->recv_data_cnt);
|
|
}
|
|
|
|
static void mp_rf_add_tx_cali_samp(mp_rf_tx_cali_samp_desc_t *cali_info)
|
|
{
|
|
uint16_t i, q, pos, max_code;
|
|
snr_record_desc_t *record;
|
|
|
|
i = cali_info->i;
|
|
q = cali_info->q;
|
|
|
|
if (g_mp_rf_ctxt->cur_tx_cali_dev != cali_info->dev_id_magic ||
|
|
g_mp_rf_ctxt->cur_tx_cali_reg_type != cali_info->reg_type) {
|
|
os_mem_set(g_mp_rf_ctxt->real_snr, 0,
|
|
sizeof(g_mp_rf_ctxt->real_snr));
|
|
iot_printf("%s data buf clear\n", __FUNCTION__);
|
|
g_mp_rf_ctxt->cur_tx_cali_dev = cali_info->dev_id_magic;
|
|
g_mp_rf_ctxt->cur_tx_cali_reg_type = cali_info->reg_type;
|
|
}
|
|
iot_printf("%s reg_type=%d, i=%d, q=%d, snr=%d\n", __FUNCTION__,
|
|
cali_info->reg_type, i, q, cali_info->raw_snr);
|
|
|
|
max_code = (cali_info->reg_type == RF_TEST_TX_CALI_REG_IQ_MAG) ?
|
|
RF_PHY_IQ_MAG_COMPEN_CODE_MAX : RF_PHY_IQ_PHASE_COMPEN_CODE_MAX;
|
|
pos = MP_RF_IQ_CODE_TO_MAGIC(max_code, i, q);
|
|
record = g_mp_rf_ctxt->real_snr;
|
|
for (i = 0; i < MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_SIZE; i++) {
|
|
if (record[i].magic == pos || record[i].cnt == 0) {
|
|
record[i].magic = pos;
|
|
if (record[i].cnt < MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_DEPTH) {
|
|
record[i].snr[record[i].cnt] = cali_info->raw_snr;
|
|
record[i].cnt++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* polynomial fitting, y=a0 + a1*x + a2*x*x */
|
|
void mp_rf_least_squarel_liner_fit(float *x, float *y, uint8_t n,
|
|
float *a0, float *a1, float *a2)
|
|
{
|
|
float temp = 0;
|
|
float x0 = n, x1 = 0, x2 = 0, x3 = 0, x4 = 0, x0y1 = 0, x1y1 = 0, x2y1 = 0;
|
|
float x0x2, x0x3, x0x4, x1x1, x1x2, x1x3, x1x4, x2x2, x2x3, x2x4, x3x3;
|
|
float a_banshui[3][3], a_ni[3][3];
|
|
float a_abs;
|
|
uint8_t i, j;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
x0y1 += *(y + i);
|
|
temp = *(x + i);
|
|
x1 += temp;
|
|
x1y1 += temp*(*(y + i));
|
|
temp *= *(x + i);
|
|
x2 += temp;
|
|
x2y1 += temp*(*(y + i));
|
|
temp *= *(x + i);
|
|
x3 += temp;
|
|
temp *= *(x + i);
|
|
x4 += temp;
|
|
}
|
|
x0x2 = x0 * x2;
|
|
x0x3 = x0 * x3;
|
|
x0x4 = x0 * x4;
|
|
x1x1 = x1 * x1;
|
|
x1x2 = x1 * x2;
|
|
x1x3 = x1 * x3;
|
|
x1x4 = x1 * x4;
|
|
x2x2 = x2 * x2;
|
|
x2x3 = x2 * x3;
|
|
x2x4 = x2 * x4;
|
|
x3x3 = x3 * x3;
|
|
a_banshui[0][0] = (x2x4 - x3x3);
|
|
a_banshui[0][1] = -(x1x4 - x2x3);
|
|
a_banshui[0][2] = (x1x3 - x2x2);
|
|
a_banshui[1][0] = -(x1x4 - x2x3);
|
|
a_banshui[1][1] = (x0x4 - x2x2);
|
|
a_banshui[1][2] = -(x0x3 - x1x2);
|
|
a_banshui[2][0] = (x1x3 - x2x2);
|
|
a_banshui[2][1] = -(x0x3 - x1x2);
|
|
a_banshui[2][2] = (x0x2 - x1x1);
|
|
a_abs = (x0 * a_banshui[0][0] + x1 * a_banshui[0][1] + x2 * a_banshui[0][2]);
|
|
for (i = 0; i < 3; i++) {
|
|
for (j = 0; j < 3; j++) {
|
|
a_ni[i][j] = a_banshui[i][j] / a_abs;
|
|
}
|
|
}
|
|
*a0 = a_ni[0][0] * x0y1 + a_ni[0][1] * x1y1 + a_ni[0][2] * x2y1;
|
|
*a1 = a_ni[1][0] * x0y1 + a_ni[1][1] * x1y1 + a_ni[1][2] * x2y1;
|
|
*a2 = a_ni[2][0] * x0y1 + a_ni[2][1] * x1y1 + a_ni[2][2] * x2y1;
|
|
iot_printf("%s a0:%f a1:%f a2:%f\n", __FUNCTION__, *a0, *a1, *a2);
|
|
}
|
|
|
|
static int32_t mp_rf_calculate_expection(int32_t *data, uint8_t cnt)
|
|
{
|
|
uint8_t i;
|
|
int32_t sum = 0, avg;
|
|
|
|
if (!cnt) {
|
|
avg = 0;
|
|
goto ret;
|
|
}
|
|
|
|
if (cnt <= 10) {
|
|
for (i = 0; i < cnt; i++) {
|
|
sum += data[i];
|
|
}
|
|
avg = sum / cnt;
|
|
goto ret;
|
|
}
|
|
|
|
iot_bubble_sort_int32(data, cnt, 1);
|
|
for (i = 3; i < cnt - 3; i++) {
|
|
sum += data[i];
|
|
}
|
|
avg = sum / (cnt - 6);
|
|
ret:
|
|
return (int16_t)avg;
|
|
}
|
|
|
|
static uint8_t mp_rf_tx_cali_update_best_iq(int8_t max_code)
|
|
{
|
|
int8_t i, q;
|
|
uint16_t pos, count = 0, k, j, max_pos;
|
|
float max_snr;
|
|
|
|
for(i = 0; i < MP_RF_TX_CALI_SNR_BEST_RESULT_MAX; i++) {
|
|
g_mp_rf_ctxt->max_snr_buf[i].snr = MP_RF_INVAL_RSSI_SNR;
|
|
g_mp_rf_ctxt->max_snr_buf[i].i = RF_PHY_IQ_PHASE_COMPEN_CODE_MAX;
|
|
g_mp_rf_ctxt->max_snr_buf[i].q = RF_PHY_IQ_PHASE_COMPEN_CODE_MAX;
|
|
}
|
|
|
|
for(i = 0; i < max_code; i++) {
|
|
pos = i * max_code;
|
|
max_snr = MP_RF_INVAL_RSSI_SNR;
|
|
for (q = 0, max_pos = 0; q < max_code; q++) {
|
|
if (iot_bitmap_is_set(g_mp_rf_ctxt->snr_samp_bitmap,
|
|
MP_RF_TX_CALI_SNR_BM_SIZE, pos + q + 1) && max_snr <
|
|
g_mp_rf_ctxt->snr_fit_buf[pos + q]) {
|
|
max_pos = q;
|
|
max_snr = g_mp_rf_ctxt->snr_fit_buf[pos + q];
|
|
}
|
|
}
|
|
|
|
if (max_snr == MP_RF_INVAL_RSSI_SNR) {
|
|
continue;
|
|
}
|
|
|
|
for (k = 0; k < MP_RF_TX_CALI_SNR_BEST_RESULT_MAX; k++) {
|
|
if (max_snr > g_mp_rf_ctxt->max_snr_buf[k].snr) {
|
|
count++;
|
|
for (j = MP_RF_TX_CALI_SNR_BEST_RESULT_MAX - 1; j > k; j--) {
|
|
g_mp_rf_ctxt->max_snr_buf[j].snr =
|
|
g_mp_rf_ctxt->max_snr_buf[j - 1].snr;
|
|
g_mp_rf_ctxt->max_snr_buf[j].i =
|
|
g_mp_rf_ctxt->max_snr_buf[j - 1].i;
|
|
g_mp_rf_ctxt->max_snr_buf[j].q =
|
|
g_mp_rf_ctxt->max_snr_buf[j - 1].q;
|
|
}
|
|
g_mp_rf_ctxt->max_snr_buf[k].snr = max_snr;
|
|
g_mp_rf_ctxt->max_snr_buf[k].i = i;
|
|
g_mp_rf_ctxt->max_snr_buf[k].q = max_pos;
|
|
iot_printf("%s pos=%d, i=%d, q=%d, snr=%f, count=%d\n",
|
|
__FUNCTION__, k, i, max_pos, max_snr, count);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
count = min(count, MP_RF_TX_CALI_SNR_BEST_RESULT_MAX);
|
|
|
|
return count;
|
|
}
|
|
|
|
static void mp_rf_get_tx_cali_res(mp_rf_test_cmd_tx_cali_stat_qr_t *rf_cmd,
|
|
mp_rf_rsp_tx_cali_t *rsp)
|
|
{
|
|
int8_t i = 0, q = 0, max_code, loop;
|
|
uint8_t m, n, cnt;
|
|
uint8_t *bm;
|
|
uint16_t pos, bm_size = MP_RF_TX_CALI_SNR_BM_SIZE;
|
|
float a0, a1, a2, *fit_x, *fit_y, *fit_buf;
|
|
uint32_t timer_start, time_span;
|
|
int32_t snr[MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_DEPTH];
|
|
|
|
iot_printf("%s tx cali type:%d liner_fit_en:%d\n", __FUNCTION__,
|
|
rf_cmd->type, rf_cmd->liner_fit_en);
|
|
|
|
switch (rf_cmd->type) {
|
|
case RF_TEST_TX_CALI_REG_IQ_MAG:
|
|
{
|
|
max_code = RF_PHY_IQ_MAG_COMPEN_CODE_MAX;
|
|
break;
|
|
}
|
|
case RF_TEST_TX_CALI_REG_IQ_PHASE:
|
|
{
|
|
max_code = RF_PHY_IQ_PHASE_COMPEN_CODE_MAX;
|
|
break;
|
|
}
|
|
default:
|
|
return;
|
|
}
|
|
|
|
/* at least half of the packets received can be considered valid */
|
|
n = rf_cmd->liner_fit_en ? 2 : 10;
|
|
|
|
fit_x = g_mp_rf_ctxt->fit_x;
|
|
fit_y = g_mp_rf_ctxt->fit_y;
|
|
fit_buf = g_mp_rf_ctxt->snr_fit_buf;
|
|
os_mem_set(fit_buf, 0, sizeof(g_mp_rf_ctxt->snr_fit_buf));
|
|
|
|
bm = g_mp_rf_ctxt->snr_samp_bitmap;
|
|
os_mem_set(bm, 0, bm_size);
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
for (i = 0; i < MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_SIZE; i++) {
|
|
if (g_mp_rf_ctxt->real_snr[i].cnt <= n)
|
|
continue;
|
|
/* calculate the mathematical expectation of snr */
|
|
for (m = 0; m < g_mp_rf_ctxt->real_snr[i].cnt; m++) {
|
|
snr[m] = g_mp_rf_ctxt->real_snr[i].snr[m];
|
|
}
|
|
pos = g_mp_rf_ctxt->real_snr[i].magic;
|
|
iot_bitmap_set(bm, bm_size, pos + 1);
|
|
fit_buf[pos] = mp_rf_calculate_expection(snr,
|
|
g_mp_rf_ctxt->real_snr[i].cnt);
|
|
}
|
|
|
|
if (!rf_cmd->liner_fit_en) {
|
|
goto get_res;
|
|
}
|
|
|
|
/* smooth curve, at least twice */
|
|
for(loop = 0; loop < 2; loop++) {
|
|
/* keep i unchanged, fit the q curve, and record the fitted data */
|
|
for (i = 0; i < max_code; i++) {
|
|
for (q = 0, cnt = 0; q < max_code; q++) {
|
|
pos = MP_RF_IQ_CODE_TO_MAGIC(max_code, i, q);
|
|
if (iot_bitmap_is_set(bm, bm_size, pos + 1)) {
|
|
fit_y[cnt] = fit_buf[pos];
|
|
fit_x[cnt] = q;
|
|
cnt++;
|
|
}
|
|
}
|
|
if (cnt) {
|
|
iot_printf("%s i:%d, cnt:%d, fit_x[%d, %d]\n", __FUNCTION__, i,
|
|
cnt, (uint8_t)fit_x[0], (uint8_t)fit_x[cnt - 1]);
|
|
}
|
|
/* curve fitting, required data points cannot be too few */
|
|
if (cnt >= MP_RF_TX_CALI_SNR_LINER_FIT_VALID_SAMP_NUM) {
|
|
mp_rf_least_squarel_liner_fit(fit_x, fit_y, cnt, &a0, &a1, &a2);
|
|
/* Generate new data according to fitting parameters */
|
|
for (q = fit_x[0]; q <= fit_x[cnt - 1]; q++) {
|
|
pos = MP_RF_IQ_CODE_TO_MAGIC(max_code, i, q);
|
|
if (iot_bitmap_is_set(bm, bm_size, pos + 1)) {
|
|
fit_buf[pos] = a0 + a1 * q + a2 * q * q;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* keep q unchanged, fit the i curve, and record the fitted data */
|
|
for (q = 0; q < max_code; q++) {
|
|
for (i = 0, cnt = 0; i < max_code; i++) {
|
|
pos = MP_RF_IQ_CODE_TO_MAGIC(max_code, i, q);
|
|
if (iot_bitmap_is_set(bm, bm_size, pos + 1)) {
|
|
fit_y[cnt] = fit_buf[pos];
|
|
fit_x[cnt] = i;
|
|
cnt++;
|
|
}
|
|
}
|
|
|
|
if (cnt) {
|
|
iot_printf("%s q:%d, cnt:%d, fit_x[%d, %d]\n", __FUNCTION__, q,
|
|
cnt, (uint8_t)fit_x[0], (uint8_t)fit_x[cnt - 1]);
|
|
}
|
|
if (cnt >= MP_RF_TX_CALI_SNR_LINER_FIT_VALID_SAMP_NUM) {
|
|
mp_rf_least_squarel_liner_fit(fit_x, fit_y, cnt, &a0, &a1, &a2);
|
|
for (i = fit_x[0]; i < fit_x[cnt - 1]; i++) {
|
|
pos = MP_RF_IQ_CODE_TO_MAGIC(max_code, i, q);
|
|
if (iot_bitmap_is_set(bm, bm_size, pos + 1)) {
|
|
fit_buf[pos] = a0 + a1 * i + a2 * i * i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
get_res:
|
|
cnt = rf_cmd->liner_fit_en ? MP_RF_TX_CALI_SNR_BEST_RESULT_MAX : 1;
|
|
rsp->cnt = mp_rf_tx_cali_update_best_iq(max_code);
|
|
rsp->cnt = min(cnt, rsp->cnt);
|
|
os_mem_cpy(rsp->bm, bm, bm_size);
|
|
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
timer_start);
|
|
time_span = MAC_NTB_TO_MS(time_span);
|
|
iot_printf("%s time consuming is %d, best_result:", __FUNCTION__,
|
|
time_span);
|
|
|
|
for (i = 0; i < rsp->cnt; i++) {
|
|
rsp->result[i].i = g_mp_rf_ctxt->max_snr_buf[i].i;
|
|
rsp->result[i].q = g_mp_rf_ctxt->max_snr_buf[i].q;
|
|
rsp->result[i].snr = g_mp_rf_ctxt->max_snr_buf[i].snr / 10.0;
|
|
iot_printf("[%f, %d, %d], ", rsp->result[i].snr, rsp->result[i].i,
|
|
rsp->result[i].q);
|
|
}
|
|
iot_printf("\n");
|
|
}
|
|
|
|
static void mp_rf_golden_rf_rx()
|
|
{
|
|
int8_t rssi, snr;
|
|
uint16_t num, i;
|
|
iot_pkt_t *iot_pkt_array[1] = { 0 };
|
|
mp_rf_test_cmd_hdr_t *test_cmd;
|
|
mp_rf_test_cmd_chg_phy_t *phy_para;
|
|
rf_rx_pb_end *pb_end;
|
|
rf_rx_buf_hdr_t *rx_buf;
|
|
mp_rf_test_rsp_t* golden_rsp;
|
|
rf_rx_mpdu_start *rx_mpdu;
|
|
/* rx fc message */
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
mp_rf_test_cmd_csr_t* csr_cmd;
|
|
mp_rf_rsp_csr_t* csr_rsp;
|
|
mp_rf_tx_cali_samp_desc_t cali_info = { 0 };
|
|
|
|
golden_rsp = (mp_rf_test_rsp_t *)g_mp_rf_ctxt->rf_pb_buf;
|
|
golden_rsp->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
golden_rsp->tx_ppm = 0;
|
|
for (; ;) {
|
|
if (0 == rf_pop_buf_from_ring(&g_mp_rf_ctxt->rx_ring, 1,
|
|
iot_pkt_array)) {
|
|
break;
|
|
}
|
|
if (mp_rf_check_rx_packet(iot_pkt_array[0]))
|
|
goto free_packet;
|
|
mp_rf_rx_show_message_info(iot_pkt_array[0]);
|
|
rx_buf = (rf_rx_buf_hdr_t *)iot_pkt_data(iot_pkt_array[0]);
|
|
test_cmd = (mp_rf_test_cmd_hdr_t *)((uint8_t *)rx_buf +
|
|
PB_PAYLOAD_OFFSET);
|
|
rx_mpdu = &rx_buf->mpdu_st;
|
|
mac_rf_get_rx_frm_msg_from_fc(PHY_PROTO_TYPE_GET(),
|
|
mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu), &rx_fc_msg);
|
|
pb_end = &rx_buf->pb_ed;
|
|
snr = mac_rf_rx_mpdu_st_get_avg_snr(rx_mpdu);
|
|
rssi = mac_rf_rx_mpdu_st_get_rssi(rx_mpdu);
|
|
|
|
if (rx_fc_msg.delimiter == FC_DELIM_RF_TEST &&
|
|
rx_fc_msg.nid == glb_cfg.nid) {
|
|
if (mp_rf_test_tx_cali_info_parse(rx_mpdu, PHY_PROTO_TYPE_GET(),
|
|
&cali_info) == ERR_OK) {
|
|
mp_rf_add_tx_cali_samp(&cali_info);
|
|
}
|
|
goto free_packet;
|
|
}
|
|
|
|
if (rx_fc_msg.delimiter != FC_DELIM_SOF
|
|
|| pb_end->rx_pb_crc_err
|
|
|| test_cmd->magic != MP_RF_TEST_MSG_MAGIC_NUMBER
|
|
|| rx_fc_msg.nid != glb_cfg.nid) {
|
|
goto free_packet;
|
|
}
|
|
if (g_mp_rf_ctxt->rf_phy_changing &&
|
|
test_cmd->msg_id != MP_RF_MSG_ID_CHG_PHY) {
|
|
goto free_packet;
|
|
}
|
|
switch (test_cmd->msg_id) {
|
|
case MP_RF_MSG_ID_CSR:
|
|
{
|
|
csr_cmd = (mp_rf_test_cmd_csr_t*)test_cmd->data;
|
|
/* do not execute duplicate csr commands */
|
|
if (iot_mac_addr_cmp(g_mp_rf_ctxt->dut_addr_in_csr,
|
|
csr_cmd->mac_addr) && g_mp_rf_ctxt->csr_cmd_ts ==
|
|
csr_cmd->ts) {
|
|
iot_printf("%s discard the same csr command received\n",
|
|
__FUNCTION__);
|
|
break;
|
|
}
|
|
iot_mac_addr_cpy(g_mp_rf_ctxt->dut_addr_in_csr, csr_cmd->mac_addr);
|
|
g_mp_rf_ctxt->csr_cmd_ts = csr_cmd->ts;
|
|
golden_rsp->msg_id = MP_RF_MSG_ID_CSR;
|
|
golden_rsp->tx_snr = snr;
|
|
golden_rsp->tx_rssi = rssi;
|
|
golden_rsp->tx_gain = 0;
|
|
|
|
g_mp_rf_ctxt->phr_mcs = test_cmd->phr_mcs;
|
|
g_mp_rf_ctxt->pld_mcs = test_cmd->pld_mcs;
|
|
g_mp_rf_ctxt->pld_blkz = test_cmd->pld_blkz;
|
|
if (csr_cmd->is_test_mode) {
|
|
/* use the cert test mode power configuration */
|
|
mac_rf_set_cert_mode(CERT_TEST_CMD_ENTER_PHY_HPLC2RF_LP);
|
|
if (g_mp_rf_ctxt->phr_mcs == MCS_ID_5 ||
|
|
g_mp_rf_ctxt->phr_mcs == MCS_ID_6 ||
|
|
g_mp_rf_ctxt->pld_mcs == MCS_ID_5 ||
|
|
g_mp_rf_ctxt->pld_mcs == MCS_ID_6) {
|
|
/* mcs 5/6 need special config */
|
|
mac_rf_set_cert_16qam_flag(1);
|
|
} else {
|
|
mac_rf_set_cert_16qam_flag(0);
|
|
}
|
|
} else {
|
|
/* cfg tx power */
|
|
mac_rf_set_target_tx_power(test_cmd->power);
|
|
}
|
|
csr_rsp = (mp_rf_rsp_csr_t*)golden_rsp->data;
|
|
num = min(MP_RF_CSR_TX_MAX_COUNT, csr_cmd->packet_num);
|
|
for (i = 0; i < num; i++) {
|
|
csr_rsp->sn = i;
|
|
mp_rf_tx_packet(csr_cmd->interval);
|
|
}
|
|
if (csr_cmd->is_test_mode) {
|
|
/* after sending samples, restore the power config. */
|
|
mac_rf_set_cert_mode(0);
|
|
mac_rf_set_cert_16qam_flag(0);
|
|
mac_rf_set_target_tx_power(test_cmd->power);
|
|
}
|
|
break;
|
|
}
|
|
case MP_RF_MSG_ID_CSI:
|
|
{
|
|
g_mp_rf_ctxt->phr_mcs = test_cmd->phr_mcs;
|
|
g_mp_rf_ctxt->pld_mcs = test_cmd->pld_mcs;
|
|
g_mp_rf_ctxt->pld_blkz = test_cmd->pld_blkz;
|
|
/* cfg tx power */
|
|
mac_rf_set_target_tx_power(test_cmd->power);
|
|
|
|
golden_rsp->msg_id = MP_RF_MSG_ID_CSI;
|
|
golden_rsp->tx_snr = snr;
|
|
golden_rsp->tx_rssi = rssi;
|
|
golden_rsp->tx_gain = mac_rf_rx_mpdu_st_get_rx_gain(rx_mpdu);
|
|
mp_rf_tx_packet(0);
|
|
break;
|
|
}
|
|
case MP_RF_MSG_ID_TX_EVM_SAMP:
|
|
{
|
|
mp_rf_add_tx_evm_samp((mp_rf_test_cmd_tx_evm_t *)test_cmd->data,
|
|
snr, rssi);
|
|
break;
|
|
}
|
|
case MP_RF_MSG_ID_TX_EVM_STAT_QUERY:
|
|
{
|
|
golden_rsp->msg_id = MP_RF_MSG_ID_TX_EVM_STAT_QUERY;
|
|
mp_rf_get_tx_evm_res((mp_rf_test_cmd_tx_evm_t *)test_cmd->data,
|
|
(mp_rf_rsp_tx_evm_t *)golden_rsp->data);
|
|
|
|
/* cfg tx power */
|
|
mac_rf_set_target_tx_power(test_cmd->power);
|
|
mp_rf_recover_def_rate();
|
|
for (i = 0; i < 3; i++)
|
|
mp_rf_tx_packet(0);
|
|
break;
|
|
}
|
|
case MP_RF_MSG_ID_CHG_PHY:
|
|
{
|
|
phy_para = (mp_rf_test_cmd_chg_phy_t *)test_cmd->data;
|
|
golden_rsp->msg_id = MP_RF_MSG_ID_CHG_PHY;
|
|
golden_rsp->tx_snr = 0;
|
|
golden_rsp->tx_rssi = 0;
|
|
golden_rsp->tx_gain = 0;
|
|
/* cfg tx power */
|
|
mac_rf_set_target_tx_power(test_cmd->power);
|
|
mp_rf_recover_def_rate();
|
|
mp_rf_tx_packet(0);
|
|
g_mp_rf_ctxt->rf_phy_changing = 1;
|
|
g_mp_rf_ctxt->rf_phy_chg_ts = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
g_mp_rf_ctxt->target_option = phy_para->option;
|
|
g_mp_rf_ctxt->target_channel = phy_para->channel;
|
|
iot_printf("%s -- current phy para[option:%d channel:%d],"
|
|
" target phy para[option:%d channel:%d]\n",
|
|
__FUNCTION__, g_mp_rf_ctxt->option, g_mp_rf_ctxt->channel,
|
|
phy_para->option, phy_para->channel);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
free_packet:
|
|
iot_pkt_free(iot_pkt_array[0]);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void mp_rf_plc_massage_show(uint8_t *rx_buf)
|
|
{
|
|
/* mac proto */
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
/* rx fc message */
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
rx_buf_hdr_t *rx_buf_t = (rx_buf_hdr_t *)rx_buf;
|
|
rx_mpdu_start *rx_mpdu = &(rx_buf_t->mpdu_st);
|
|
rx_pb_start *pb_st = &(rx_buf_t->pb_st);
|
|
rx_pb_end *pb_end = &(rx_buf_t->pb_ed);
|
|
if (mac_rx_att_get_is_fcserr(&rx_buf_t->att) == 1) {
|
|
return;
|
|
}
|
|
mac_get_rx_frm_msg_from_fc(proto, mac_rx_mpdu_st_get_fc_addr(rx_mpdu),
|
|
&rx_fc_msg);
|
|
switch(rx_fc_msg.delimiter){
|
|
case FC_DELIM_BEACON:
|
|
{
|
|
iot_printf("rx bcn nid:0x%x,stei:%d,tmi:%d-%d,fc_phase:%d,"
|
|
"rx_phase:%d,rssi:%d,gain:%d,snr:%d,pb_crc:%lu\n",
|
|
rx_fc_msg.nid, rx_fc_msg.src_tei, rx_fc_msg.tmi,rx_fc_msg.tmi_ext,
|
|
rx_fc_msg.phase, mac_rx_mpdu_st_get_rx_phase(rx_mpdu),
|
|
PHY_RSSI_FROM_RMI_GAIN(mac_rx_mpdu_st_get_adc_power(rx_mpdu),
|
|
mac_rx_mpdu_st_get_agc_gain_entry(rx_mpdu)),
|
|
PHY_GET_AGC_POWER(mac_rx_mpdu_st_get_agc_gain_entry(rx_mpdu)),
|
|
mac_rx_mpdu_st_get_avg_snr(rx_mpdu),
|
|
pb_end->rx_pb_crc_err);
|
|
break;
|
|
}
|
|
case FC_DELIM_SOF:
|
|
{
|
|
iot_printf("rx sof nid:0x%x,stei:%lu,dtei:%lu,tmi:%d-%d,"
|
|
"rx_phase:%d,pb_num:%lu,ssn:%lu,rssi:%d,gain:%d,snr:%d,pb_crc:%lu\n",
|
|
rx_fc_msg.nid, rx_fc_msg.src_tei, rx_fc_msg.dst_tei, rx_fc_msg.tmi,
|
|
rx_fc_msg.tmi_ext, mac_rx_mpdu_st_get_rx_phase(rx_mpdu),
|
|
mac_rx_mpdu_st_get_rx_pb_num(rx_mpdu),
|
|
mac_rx_pb_st_get_ssn(pb_st),
|
|
PHY_RSSI_FROM_RMI_GAIN(mac_rx_mpdu_st_get_adc_power(rx_mpdu),
|
|
mac_rx_mpdu_st_get_agc_gain_entry(rx_mpdu)),
|
|
PHY_GET_AGC_POWER(mac_rx_mpdu_st_get_agc_gain_entry(rx_mpdu)),
|
|
mac_rx_mpdu_st_get_avg_snr(rx_mpdu),
|
|
pb_end->rx_pb_crc_err);
|
|
break;
|
|
}
|
|
case FC_DELIM_SACK:
|
|
{
|
|
iot_printf("rx a ack,stei:%d,dtei:%d,nid:0x%x,result:%d,status:%x\n",
|
|
rx_fc_msg.src_tei, rx_fc_msg.dst_tei, rx_fc_msg.nid,
|
|
rx_fc_msg.result_in_sack, rx_fc_msg.bitmap_in_sack);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
iot_printf("rx other frame type: %d\n", rx_fc_msg.delimiter);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mp_rf_comm_test_info_clear()
|
|
{
|
|
g_mp_rf_ctxt->csr_cmd_ts = 0;
|
|
g_mp_rf_ctxt->tx_evm_ts = 0;
|
|
g_mp_rf_ctxt->rf_phy_changing = 0;
|
|
g_mp_rf_ctxt->rf_phy_chg_ts = 0;
|
|
g_mp_rf_ctxt->recv_data_cnt = 0;
|
|
os_mem_set(g_mp_rf_ctxt->dut_addr_in_tx_evm, 0x0, IOT_MAC_ADDR_LEN);
|
|
os_mem_set(g_mp_rf_ctxt->dut_addr_in_csr, 0x0, IOT_MAC_ADDR_LEN);
|
|
os_mem_set(g_mp_rf_ctxt->dut_addr_in_cal, 0x0, IOT_MAC_ADDR_LEN);
|
|
g_mp_rf_ctxt->last_meas_sn = 0;
|
|
g_mp_rf_ctxt->option = RF_OPTION_INVALID;
|
|
g_mp_rf_ctxt->channel = RF_CHANNEL_ID_INVALID;
|
|
g_mp_rf_ctxt->target_option = MP_RF_GOLDEN_DEF_OPTION;
|
|
g_mp_rf_ctxt->target_channel = MP_RF_GOLDEN_DEF_CHANNEL;
|
|
}
|
|
|
|
static void mp_rf_cal_mode_enter(uint8_t option, uint8_t ch,
|
|
uint8_t comm_pwr, uint8_t comm_tmi)
|
|
{
|
|
uint32_t freq;
|
|
if (!g_mp_rf_ctxt->is_cal_mode) {
|
|
/* phy tx common init interface */
|
|
rf_phy_tx_init(phy_rf_get_band_sel(), option);
|
|
freq = phy_rf_get_channel_freq_by_id(option, ch);
|
|
/* phy channel setting */
|
|
bb_rf_reset();
|
|
bb_rf_set_tx_dc(0, 0);
|
|
bb_rf_set_tx_iq_mag(0, 0);
|
|
bb_rf_set_tx_iq_phase(0, 0);
|
|
|
|
bb_rf_rx_cfg(option, freq);
|
|
/* Note: here is to increase the rx filter bandwidth, which can improve
|
|
* the accuracy of golden measurement power.
|
|
*/
|
|
bb_rf_set_filter(0x10);
|
|
bb_rf_debug_rx_immd();
|
|
g_mp_rf_ctxt->is_cal_mode = 1;
|
|
mp_rf_comm_test_info_clear();
|
|
}
|
|
phy_pwr_adjust_set(comm_pwr);
|
|
glb_cfg.tmi = comm_tmi;
|
|
iot_printf("%s - option:%lu, ch:%lu, pwr:%lu, tmi:%lu\n", __FUNCTION__,
|
|
option, ch, comm_pwr, comm_tmi);
|
|
}
|
|
|
|
static uint32_t mp_rf_cal_mode_exit()
|
|
{
|
|
if (g_mp_rf_ctxt->is_cal_mode) {
|
|
iot_printf("%s\n", __FUNCTION__);
|
|
g_mp_rf_ctxt->is_cal_mode = 0;
|
|
return ERR_OK;
|
|
}
|
|
return ERR_EXIST;
|
|
}
|
|
|
|
static uint8_t mp_rf_cal_pwr_meas(uint8_t *dut_addr, uint32_t sn,
|
|
uint32_t lo_freq, uint16_t tone_idx,
|
|
uint16_t dc_idx, uint16_t img_idx, uint32_t *tone_pwr,
|
|
uint32_t *dc_pwr, uint32_t *img_pwr, float *gain, uint8_t try_cnt)
|
|
{
|
|
uint32_t dump_addr;
|
|
uint32_t dump_len;
|
|
uint32_t sample_cnt = 1024 * 8;
|
|
uint32_t *fft_raw;
|
|
uint32_t start_ntb, end_ntb;
|
|
uint8_t i, fix_gain;
|
|
if (!g_mp_rf_ctxt->is_cal_mode) {
|
|
/* golden is not in calibration mode, not ready, and returns
|
|
* error code to DUT.
|
|
*/
|
|
iot_printf("%s error golden not ready!!!\n", __FUNCTION__);
|
|
return ERR_NOT_READY;
|
|
}
|
|
start_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
if (iot_mac_addr_cmp(dut_addr, g_mp_rf_ctxt->dut_addr_in_cal) == 1
|
|
&& g_mp_rf_ctxt->last_meas_sn == sn) {
|
|
/* repeated measurement request from DUT, directly returning the
|
|
* latest test results.
|
|
*/
|
|
iot_printf("%s repeat req-dut[%02x:%02x:%02x:%02x:%02x:%02x], sn:%lu\n",
|
|
__FUNCTION__, dut_addr[0], dut_addr[1], dut_addr[2], dut_addr[3],
|
|
dut_addr[4], dut_addr[5], sn);
|
|
goto out;
|
|
}
|
|
bb_rf_rx_reset();
|
|
bb_rf_set_fchz(lo_freq);
|
|
fix_gain = rf_phy_rx_gain_lock(-1);
|
|
bb_rf_debug_rx_immd();
|
|
try_cnt = min(try_cnt, MP_RF_CAL_MEAS_AVG_CNT_MAX);
|
|
if (try_cnt == 0) {
|
|
try_cnt = MP_RF_CAL_MEAS_AVG_CNT_DEFAULT;
|
|
}
|
|
dump_len = phy_ada_dump_addr_get(&dump_addr);
|
|
IOT_ASSERT((sample_cnt << 2) <= dump_len);
|
|
|
|
for (i = 0; i < try_cnt; i++) {
|
|
g_mp_rf_ctxt->gain_buf[i] = fix_gain;
|
|
rf_phy_ada_dump_entry(dump_addr, sample_cnt << 2);
|
|
fft_raw = rf_phy_ada_dump_fft_cal((uint32_t *)dump_addr, sample_cnt,
|
|
512, tone_idx, dc_idx, img_idx);
|
|
g_mp_rf_ctxt->tone_pwr_buf[i] = fft_raw[tone_idx];
|
|
g_mp_rf_ctxt->dc_pwr_buf[i] = fft_raw[dc_idx];
|
|
g_mp_rf_ctxt->img_pwr_buf[i] = fft_raw[img_idx];
|
|
}
|
|
|
|
mp_rf_cal_meas_dump("golden_meas gain:", g_mp_rf_ctxt->gain_buf,
|
|
(uint32_t)try_cnt, sizeof(g_mp_rf_ctxt->gain_buf[0]));
|
|
mp_rf_cal_meas_dump("golden_meas pwr1:", g_mp_rf_ctxt->tone_pwr_buf,
|
|
(uint32_t)try_cnt, sizeof(g_mp_rf_ctxt->tone_pwr_buf[0]));
|
|
mp_rf_cal_meas_dump("golden_meas pwr2:", g_mp_rf_ctxt->dc_pwr_buf,
|
|
(uint32_t)try_cnt, sizeof(g_mp_rf_ctxt->dc_pwr_buf[0]));
|
|
mp_rf_cal_meas_dump("golden_meas pwr3:", g_mp_rf_ctxt->img_pwr_buf,
|
|
(uint32_t)try_cnt, sizeof(g_mp_rf_ctxt->img_pwr_buf[0]));
|
|
iot_mac_addr_cpy(g_mp_rf_ctxt->dut_addr_in_cal, dut_addr);
|
|
|
|
g_mp_rf_ctxt->last_meas_sn = sn;
|
|
g_mp_rf_ctxt->last_tone_pwr = mp_rf_calc_avg_u32(g_mp_rf_ctxt->tone_pwr_buf,
|
|
try_cnt);
|
|
g_mp_rf_ctxt->last_dc_pwr = mp_rf_calc_avg_u32(g_mp_rf_ctxt->dc_pwr_buf,
|
|
try_cnt);
|
|
g_mp_rf_ctxt->last_img_pwr = mp_rf_calc_avg_u32(g_mp_rf_ctxt->img_pwr_buf,
|
|
try_cnt);
|
|
g_mp_rf_ctxt->last_gain = mp_rf_calc_avg_u8(g_mp_rf_ctxt->gain_buf,
|
|
try_cnt);
|
|
out:
|
|
*tone_pwr = g_mp_rf_ctxt->last_tone_pwr;
|
|
*dc_pwr = g_mp_rf_ctxt->last_dc_pwr;
|
|
*img_pwr = g_mp_rf_ctxt->last_img_pwr;
|
|
*gain = g_mp_rf_ctxt->last_gain;
|
|
end_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
iot_printf("%s - lo_freq:%luHz, idx:[%d,%d,%d], power[%d,%d,%d],"
|
|
"gain %f, cons:%lums\n", __FUNCTION__, lo_freq, tone_idx, dc_idx,
|
|
img_idx, *tone_pwr, *dc_pwr, *img_pwr, *gain,
|
|
MAC_NTB_TO_MS(mp_rf_ntb_span_calc(end_ntb, start_ntb)));
|
|
rf_phy_rx_gain_unlock();
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint32_t IRAM_ATTR mp_plc_isr_handler(uint32_t vector, iot_addrword_t data)
|
|
{
|
|
|
|
uint32_t int_status, tmp;
|
|
(void)vector;
|
|
(void)data;
|
|
|
|
/* read pending interrupt status */
|
|
int_status = RGF_MAC_READ_REG(CFG_MAC_INT_STS_ADDR);
|
|
int_status >>= MAC_INT_STATUS_OFFSET;
|
|
/* clear pending interrupt status */
|
|
RGF_MAC_WRITE_REG(CFG_MAC_INT_CLR_ADDR,
|
|
(int_status << MAC_INT_CLR_0_OFFSET));
|
|
tmp = RGF_MAC_READ_REG(CFG_RX_INT_CLR_ADDR);
|
|
REG_FIELD_SET(CFG_RX_MPDU_INT_CLR_0, tmp, 1);
|
|
RGF_MAC_WRITE_REG(CFG_RX_INT_CLR_ADDR, tmp);
|
|
if (int_status & (1 << MAC_ISR_MPDU_RX_ID)) {
|
|
os_set_task_event_with_v_from_isr(_init_handle,
|
|
1 << MP_RF_EVT_ID_PLC_RX);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void mp_plc_isr_reset()
|
|
{
|
|
uint32_t prio_mask;
|
|
|
|
/* disable all mac interrupt and clean up any pending interrupt */
|
|
RGF_MAC_WRITE_REG(CFG_INT_ENA_MASK_ADDR, 0);
|
|
|
|
/* clean up all pending interrupt */
|
|
RGF_MAC_WRITE_REG(CFG_MAC_INT_CLR_ADDR, CFG_INT_ENABLE_MASK_MASK);
|
|
/* assign priority 0 interrupts, CPU0 & CPU1 use the interrupt */
|
|
prio_mask = 1 << (MAC_ISR_MPDU_RX_ID + CFG_INT_PRI0_MASK_OFFSET);
|
|
RGF_MAC_WRITE_REG(CFG_INT_PRI0_MASK_ADDR, prio_mask);
|
|
}
|
|
|
|
void mp_plc_isr_init(void)
|
|
{
|
|
/* allocate soc irq resource */
|
|
g_mp_rf_ctxt->plc_isr_0_h = iot_interrupt_create(HAL_VECTOR_MAC_0,
|
|
HAL_INTR_PRI_7, (iot_addrword_t)NULL, mp_plc_isr_handler);
|
|
g_mp_rf_ctxt->plc_isr_1_h = iot_interrupt_create(HAL_VECTOR_MAC_1,
|
|
HAL_INTR_PRI_7, (iot_addrword_t)NULL, mp_plc_isr_handler);
|
|
g_mp_rf_ctxt->plc_isr_2_h = iot_interrupt_create(HAL_VECTOR_MAC_2,
|
|
HAL_INTR_PRI_7, (iot_addrword_t)NULL, mp_plc_isr_handler);
|
|
|
|
/* attach soc irq resource */
|
|
iot_interrupt_attach(g_mp_rf_ctxt->plc_isr_0_h);
|
|
iot_interrupt_attach(g_mp_rf_ctxt->plc_isr_1_h);
|
|
iot_interrupt_attach(g_mp_rf_ctxt->plc_isr_2_h);
|
|
/* enable soc irq */
|
|
iot_interrupt_unmask(g_mp_rf_ctxt->plc_isr_0_h);
|
|
iot_interrupt_unmask(g_mp_rf_ctxt->plc_isr_1_h);
|
|
iot_interrupt_unmask(g_mp_rf_ctxt->plc_isr_2_h);
|
|
|
|
/* enable interrupt: MAC_ISR_MPDU_RX_ID */
|
|
RGF_MAC_WRITE_REG(CFG_INT_ENA_MASK_ADDR, 1 << MAC_ISR_MPDU_RX_ID);
|
|
}
|
|
|
|
static uint8_t mp_rf_golden_plc_rx(void)
|
|
{
|
|
uint8_t *rx_buf = NULL, *rx_pb_buf, *tx_pb_buf, *data;
|
|
uint8_t ret = ERR_OK;
|
|
uint8_t reinit = 0;
|
|
float gain = 0.0;
|
|
mp_rf_cal_msg_hdr_t *cmd_hdr, *rsp_hdr;
|
|
mp_rf_cal_meas_cfg_t *meas_cfg;
|
|
mp_rf_cal_meas_req_t *meas_req;
|
|
mp_rf_cal_meas_rsp_t *meas_rsp;
|
|
uint32_t tone_pwr, dc_pwr, img_pwr;
|
|
rx_buf_hdr_t *hdr = NULL;
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
mp_rf_rsp_tx_cali_t* tx_cali_res;
|
|
while (!is_rx_ring0_empty()) {
|
|
rx_buf = pop_rx_buf_from_ring(0);
|
|
if (!rx_buf) {
|
|
continue;
|
|
}
|
|
|
|
mp_rf_plc_massage_show(rx_buf);
|
|
hdr = (rx_buf_hdr_t *)rx_buf;
|
|
rx_pb_buf = (uint8_t *)(rx_buf + PB_PAYLOAD_OFFSET);
|
|
|
|
data = rx_pb_buf;
|
|
cmd_hdr = (mp_rf_cal_msg_hdr_t *)data;
|
|
data += sizeof(*cmd_hdr);
|
|
mac_get_rx_frm_msg_from_fc(PHY_PROTO_TYPE_GET(),
|
|
mac_rx_mpdu_st_get_fc_addr(&hdr->mpdu_st), &rx_fc_msg);
|
|
if (rx_fc_msg.delimiter != FC_DELIM_SOF ||
|
|
rx_fc_msg.nid != glb_cfg.nid
|
|
|| cmd_hdr->magic != MP_RF_TEST_MSG_MAGIC_NUMBER) {
|
|
continue;
|
|
}
|
|
tx_pb_buf = (uint8_t *)phy_get_pb_buf_ptr_from_mpdu(mpdu_start);
|
|
rsp_hdr = (mp_rf_cal_msg_hdr_t *)tx_pb_buf;
|
|
rsp_hdr->msg_id = cmd_hdr->msg_id;
|
|
rsp_hdr->magic = cmd_hdr->magic;
|
|
iot_mac_addr_cpy(rsp_hdr->dut_addr, cmd_hdr->dut_addr);
|
|
rsp_hdr->sn = cmd_hdr->sn;
|
|
|
|
switch (cmd_hdr->msg_id) {
|
|
case MP_RF_CAL_MSG_ID_MEAS_CFG:
|
|
{
|
|
meas_cfg = (mp_rf_cal_meas_cfg_t *)data;
|
|
if (meas_cfg->meas_en) {
|
|
mp_rf_cal_mode_enter(meas_cfg->option, meas_cfg->ch,
|
|
meas_cfg->comm_pwr, meas_cfg->comm_tmi);
|
|
} else {
|
|
ret = mp_rf_cal_mode_exit();
|
|
if (ret == ERR_OK) {
|
|
/* golden exit calibration mode */
|
|
reinit = 1;
|
|
}
|
|
}
|
|
rsp_hdr->option = ERR_OK;
|
|
tx_send_packet_interval(10);
|
|
break;
|
|
}
|
|
case MP_RF_CAL_MSG_ID_MEAS_REQ:
|
|
{
|
|
meas_req = (mp_rf_cal_meas_req_t *)data;
|
|
meas_rsp = (mp_rf_cal_meas_rsp_t *)rsp_hdr->data;
|
|
ret = mp_rf_cal_pwr_meas(cmd_hdr->dut_addr, cmd_hdr->sn,
|
|
meas_req->lo_freq, meas_req->tone_idx,
|
|
meas_req->dc_idx, meas_req->img_idx,
|
|
&tone_pwr, &dc_pwr, &img_pwr, &gain, meas_req->avg_cnt);
|
|
rsp_hdr->option = ret;
|
|
if (ret == ERR_OK) {
|
|
meas_rsp->tone_pwr = tone_pwr;
|
|
meas_rsp->dc_pwr = dc_pwr;
|
|
meas_rsp->img_pwr = img_pwr;
|
|
meas_rsp->gain = (uint8_t)(gain + 0.5);
|
|
meas_rsp->gain_x100 = (uint16_t)(gain * 100.0 + 0.5);
|
|
os_mem_set(meas_rsp->rsvd, 0, sizeof(meas_rsp->rsvd));
|
|
} else {
|
|
os_mem_set(meas_rsp, 0x0, sizeof(*meas_rsp));
|
|
}
|
|
tx_send_packet_interval(10);
|
|
break;
|
|
}
|
|
case MP_RF_MSG_ID_TX_CALI_STAT_QUERY:
|
|
{
|
|
tx_cali_res = (mp_rf_rsp_tx_cali_t*)rsp_hdr->data;
|
|
mp_rf_get_tx_cali_res((mp_rf_test_cmd_tx_cali_stat_qr_t *)data,
|
|
tx_cali_res);
|
|
glb_cfg.tmi = MP_RF_PLC_LARGE_PACKET_TMI;
|
|
tx_send_packet_interval(10);
|
|
glb_cfg.tmi = MP_RF_PLC_NORMAL_PACKET_TMI;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return reinit;
|
|
}
|
|
|
|
static void mp_rf_cal_plc_comm_init(uint8_t band)
|
|
{
|
|
uint32_t tmp;
|
|
static uint8_t first_flag = 0;
|
|
if (!first_flag) {
|
|
g_phy_cpu_share_ctxt.pt_mode_entry = 1;
|
|
dut_flag_set(!g_mp_rf_ctxt->is_golden);
|
|
/* mac rx common init interface */
|
|
rx_common_init(band);
|
|
/* mac tx common init interface */
|
|
tx_common_init(band);
|
|
/* setup the rx ring */
|
|
rx_ring_setup_hw(0, NULL);
|
|
/* enable the rx ring */
|
|
rx_ring_enable(0, true);
|
|
mp_plc_isr_reset();
|
|
if (g_mp_rf_ctxt->is_golden) {
|
|
mp_plc_isr_init();
|
|
phy_rxfd_pkt_det_thd_set(32, 32);
|
|
}
|
|
/* update flag */
|
|
first_flag = 1;
|
|
glb_cfg.p_type = FC_DELIM_SOF;
|
|
glb_cfg.tmi = MP_RF_PLC_NORMAL_PACKET_TMI;
|
|
glb_cfg.ack_en = false;
|
|
|
|
tmp = PHY_READ_REG(CFG_BB_DBG_BUS_SEL_ADDR);
|
|
REG_FIELD_SET(SW_TX_PILOT_PSS_OVR_EN, tmp, 1);
|
|
REG_FIELD_SET(SW_RX_PILOT_PSS_OVR_EN, tmp, 1);
|
|
REG_FIELD_SET(SW_TX_PILOT_PSS, tmp, 6);
|
|
REG_FIELD_SET(SW_RX_PILOT_PSS, tmp, 6);
|
|
PHY_WRITE_REG(CFG_BB_DBG_BUS_SEL_ADDR, tmp);
|
|
}
|
|
}
|
|
|
|
static uint8_t mp_rf_dut_test_case_csr(iot_ftm_mp_rf_cmd_hdr_t *cmd,
|
|
void *rsp)
|
|
{
|
|
rf_rx_pb_end *pb_end;
|
|
rf_rx_buf_hdr_t *rx_buf;
|
|
mp_rf_test_cmd_hdr_t *hdr;
|
|
mp_rf_test_rsp_t* golden_rsp;
|
|
mp_rf_test_cmd_csr_t* cmd_csr;
|
|
iot_ftm_mp_rf_cmd_csr_t* test_csr_cmd;
|
|
rf_rx_mpdu_start *rx_mpdu = NULL;
|
|
iot_pkt_t *iot_pkt_array[1] = { 0 };
|
|
uint32_t time_span, timeout, timer_start, count = 0;
|
|
iot_ftm_mp_rf_rsp_csr_t *csr_rsp = (iot_ftm_mp_rf_rsp_csr_t *)rsp;
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
/* get rx fc message */
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
uint8_t ret = ERR_TIMEOVER, done = 0, rx_done_tmp = 0;
|
|
mp_rf_rsp_csr_t* csr_info;
|
|
uint32_t time0, package_dur;
|
|
|
|
/* cfg DUT tx power */
|
|
mac_rf_set_target_tx_power(cmd->dut_power);
|
|
|
|
os_mem_set(csr_rsp, 0, sizeof(*csr_rsp));
|
|
mp_rf_recover_def_rate();
|
|
|
|
hdr = (mp_rf_test_cmd_hdr_t *)g_mp_rf_ctxt->rf_pb_buf;
|
|
hdr->msg_id = MP_RF_MSG_ID_CSR;
|
|
hdr->power = cmd->golden_power;
|
|
hdr->pld_blkz = cmd->pld_blkz;
|
|
hdr->phr_mcs = cmd->phr_mcs;
|
|
hdr->pld_mcs = cmd->pld_mcs;
|
|
hdr->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
cmd_csr = (mp_rf_test_cmd_csr_t*)hdr->data;
|
|
test_csr_cmd = (iot_ftm_mp_rf_cmd_csr_t*)cmd->data;
|
|
cmd_csr->packet_num = min(test_csr_cmd->packet_num, MP_RF_CSR_TX_MAX_COUNT);
|
|
cmd_csr->is_test_mode = test_csr_cmd->is_test_mode;
|
|
cmd_csr->interval = test_csr_cmd->interval;
|
|
iot_chip_get_mac_addr(cmd_csr->mac_addr);
|
|
cmd_csr->ts = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
cmd_csr->rsvd0 = 0;
|
|
os_mem_set(cmd_csr->rsvd1, 0, sizeof(cmd_csr->rsvd1));
|
|
|
|
package_dur = phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl() +
|
|
phy_rf_get_g_phr_fl(hdr->phr_mcs) + phy_rf_get_g_psdu_fl(hdr->pld_mcs,
|
|
hdr->pld_blkz);
|
|
iot_printf("%s start -- phr_mcs:%lu, pld_mcs:%lu, pld_blkz:%lu, pwr:%d,"
|
|
" is_tets_mode:%lu, packet_num:%lu, package_dur:%luus, interval:%lu\n",
|
|
__FUNCTION__, hdr->phr_mcs, hdr->pld_mcs, hdr->pld_blkz, hdr->power,
|
|
cmd_csr->is_test_mode, cmd_csr->packet_num, package_dur,
|
|
cmd_csr->interval);
|
|
|
|
timeout = min(max(test_csr_cmd->timeout, MP_RF_TEST_CASE_CSR_TIMEOUT_DEF),
|
|
MP_RF_TEST_CASE_CSR_TIMEOUT_MAX);
|
|
mp_rf_tx_packet(0);
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
time0 = timer_start;
|
|
do {
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
timer_start);
|
|
time_span = MAC_NTB_TO_MS(time_span);
|
|
if (!csr_rsp->rx_cnt && time_span >= MP_RF_CMD_RETRY_INTERVAL &&
|
|
count < MP_RF_CMD_RETRY_COUNT) {
|
|
count++;
|
|
mp_rf_tx_packet(0);
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
timeout -= MP_RF_CMD_RETRY_INTERVAL;
|
|
}
|
|
if (!rx_done_tmp) {
|
|
rx_done_tmp = mp_rf_check_rf_rx_done();
|
|
if (!rx_done_tmp) {
|
|
continue;
|
|
}
|
|
}
|
|
if (0 == rf_pop_buf_from_ring(&g_mp_rf_ctxt->rx_ring, 1,
|
|
iot_pkt_array)) {
|
|
rx_done_tmp = 0;
|
|
continue;
|
|
}
|
|
if (mp_rf_check_rx_packet(iot_pkt_array[0]))
|
|
goto free_packet;
|
|
mp_rf_rx_show_message_info(iot_pkt_array[0]);
|
|
rx_buf = (rf_rx_buf_hdr_t *)iot_pkt_data(iot_pkt_array[0]);
|
|
golden_rsp = (mp_rf_test_rsp_t *)((uint8_t *)rx_buf +
|
|
PB_PAYLOAD_OFFSET);
|
|
pb_end = &rx_buf->pb_ed;
|
|
rx_mpdu = &rx_buf->mpdu_st;
|
|
mac_rf_get_rx_frm_msg_from_fc(proto,
|
|
mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu), &rx_fc_msg);
|
|
|
|
csr_info = (mp_rf_rsp_csr_t*)golden_rsp->data;
|
|
if ((rx_fc_msg.delimiter == FC_DELIM_SOF) && (!pb_end->rx_pb_crc_err) &&
|
|
(rx_fc_msg.nid == glb_cfg.nid) &&
|
|
(golden_rsp->magic == MP_RF_TEST_MSG_MAGIC_NUMBER) &&
|
|
(golden_rsp->msg_id == MP_RF_MSG_ID_CSR)) {
|
|
g_mp_rf_ctxt->snr_buf[csr_rsp->rx_cnt] =
|
|
mac_rf_rx_mpdu_st_get_avg_snr(rx_mpdu);
|
|
g_mp_rf_ctxt->rssi_buf[csr_rsp->rx_cnt] =
|
|
mac_rf_rx_mpdu_st_get_rssi(rx_mpdu);
|
|
/* estimate the remaining time for golden to send data. */
|
|
if (!csr_rsp->rx_cnt && csr_info->sn < cmd_csr->packet_num) {
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
time_span = 0;
|
|
/* each package plus 3ms fixed consumption */
|
|
timeout = (package_dur + 3000 + cmd_csr->interval) *
|
|
(cmd_csr->packet_num - csr_info->sn) / 1000;
|
|
}
|
|
csr_rsp->rx_cnt++;
|
|
if (csr_rsp->rx_cnt >= cmd_csr->packet_num ||
|
|
csr_info->sn >= cmd_csr->packet_num - 1) {
|
|
done = 1;
|
|
}
|
|
}
|
|
free_packet:
|
|
iot_pkt_free(iot_pkt_array[0]);
|
|
} while (time_span < timeout && !done);
|
|
|
|
if (csr_rsp->rx_cnt) {
|
|
ret = ERR_OK;
|
|
csr_rsp->avg_snr = mp_rf_calc_avg_value(g_mp_rf_ctxt->snr_buf,
|
|
csr_rsp->rx_cnt) / 10;
|
|
csr_rsp->avg_rssi = mp_rf_calc_avg_value(g_mp_rf_ctxt->rssi_buf,
|
|
csr_rsp->rx_cnt) / 10;
|
|
}
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR), time0);
|
|
time_span = MAC_NTB_TO_MS(time_span);
|
|
iot_printf("%s csr_rsp: rx_cnt=%lu avg_rssi=%d avg_snr=%d consumed=%lums\n",
|
|
__FUNCTION__, csr_rsp->rx_cnt, csr_rsp->avg_rssi, csr_rsp->avg_snr,
|
|
time_span);
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t mp_rf_dut_test_case_csi(iot_ftm_mp_rf_cmd_hdr_t *cmd,
|
|
void *rsp)
|
|
{
|
|
rf_rx_pb_end *pb_end;
|
|
rf_rx_buf_hdr_t *rx_buf;
|
|
rf_rx_mpdu_start *rx_mpdu;
|
|
mp_rf_test_cmd_hdr_t *hdr;
|
|
mp_rf_test_rsp_t* golden_rsp;
|
|
iot_pkt_t *iot_pkt_array[1] = { 0 };
|
|
uint32_t timer_start, time_span, timeout, count = 0, done = 0;
|
|
iot_ftm_mp_rf_rsp_csi_t *csi_rsp = (iot_ftm_mp_rf_rsp_csi_t *)rsp;
|
|
uint32_t package_dur, proto = PHY_PROTO_TYPE_GET();
|
|
iot_ftm_mp_rf_cmd_csi_t *csi_cmd;
|
|
/* get rx fc message */
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
uint8_t ret = ERR_TIMEOVER, rx_count = 0, rx_done_tmp = 0;;
|
|
int8_t tx_rssi_thr, rx_rssi_thr, tx_snr_thr, rx_snr_thr;
|
|
/* cfg DUT tx power */
|
|
mac_rf_set_target_tx_power(cmd->dut_power);
|
|
|
|
g_mp_rf_ctxt->phr_mcs = cmd->phr_mcs;
|
|
g_mp_rf_ctxt->pld_mcs = cmd->pld_mcs;
|
|
g_mp_rf_ctxt->pld_blkz = cmd->pld_blkz;
|
|
hdr = (mp_rf_test_cmd_hdr_t *)g_mp_rf_ctxt->rf_pb_buf;
|
|
hdr->msg_id = MP_RF_MSG_ID_CSI;
|
|
hdr->power = cmd->golden_power;
|
|
hdr->pld_blkz = g_mp_rf_ctxt->pld_blkz;
|
|
hdr->phr_mcs = g_mp_rf_ctxt->phr_mcs;
|
|
hdr->pld_mcs = g_mp_rf_ctxt->pld_mcs;
|
|
hdr->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
csi_cmd = (iot_ftm_mp_rf_cmd_csi_t *)cmd->data;
|
|
package_dur = phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl() +
|
|
phy_rf_get_g_phr_fl(hdr->phr_mcs) + phy_rf_get_g_psdu_fl(hdr->pld_mcs,
|
|
hdr->pld_blkz);
|
|
iot_printf("%s start -- phr_mcs:%lu, pld_mcs:%lu, pld_blkz:%lu, pwr:%d, "
|
|
"package_dur:%luus, tx_rssi_thr=%d, rx_rssi_thr=%d, tx_snr_thr=%d, "
|
|
"rx_snr_thr=%d\n", __FUNCTION__, hdr->phr_mcs, hdr->pld_mcs,
|
|
hdr->pld_blkz, hdr->power, package_dur, csi_cmd->tx_rssi_thr,
|
|
csi_cmd->rx_rssi_thr, csi_cmd->tx_snr_thr, csi_cmd->rx_snr_thr);
|
|
|
|
timeout = MP_RF_TEST_CASE_CSI_TIMEOUT_DEF;
|
|
mp_rf_tx_packet(0);
|
|
os_mem_set(csi_rsp, 0, sizeof(*csi_rsp));
|
|
csi_rsp->tx_rssi = MP_RF_INVAL_RSSI_SNR;
|
|
csi_rsp->rx_rssi = MP_RF_INVAL_RSSI_SNR;
|
|
csi_rsp->tx_snr = MP_RF_INVAL_RSSI_SNR;
|
|
csi_rsp->rx_snr = MP_RF_INVAL_RSSI_SNR;
|
|
tx_rssi_thr = csi_cmd->tx_rssi_thr == MP_RF_INVAL_RSSI_SNR ?
|
|
MP_RF_CSI_TEST_RSSI_THR : csi_cmd->tx_rssi_thr;
|
|
rx_rssi_thr = csi_cmd->rx_rssi_thr == MP_RF_INVAL_RSSI_SNR ?
|
|
MP_RF_CSI_TEST_RSSI_THR : csi_cmd->rx_rssi_thr;
|
|
tx_snr_thr = csi_cmd->tx_snr_thr == MP_RF_INVAL_RSSI_SNR ?
|
|
MP_RF_CSI_TEST_SNR_THR : csi_cmd->tx_snr_thr;
|
|
rx_snr_thr = csi_cmd->rx_snr_thr == MP_RF_INVAL_RSSI_SNR ?
|
|
MP_RF_CSI_TEST_SNR_THR : csi_cmd->rx_snr_thr;
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
do {
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
timer_start);
|
|
time_span = MAC_NTB_TO_MS(time_span);
|
|
if (time_span >= MP_RF_CMD_RETRY_INTERVAL &&
|
|
count < MP_RF_CMD_RETRY_COUNT) {
|
|
count++;
|
|
mp_rf_tx_packet(0);
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
timeout -= MP_RF_CMD_RETRY_INTERVAL;
|
|
}
|
|
|
|
if (!rx_done_tmp) {
|
|
rx_done_tmp = mp_rf_check_rf_rx_done();
|
|
if (!rx_done_tmp) {
|
|
continue;
|
|
}
|
|
}
|
|
if (0 == rf_pop_buf_from_ring(&g_mp_rf_ctxt->rx_ring, 1,
|
|
iot_pkt_array)) {
|
|
rx_done_tmp = 0;
|
|
continue;
|
|
}
|
|
if (mp_rf_check_rx_packet(iot_pkt_array[0]))
|
|
goto free_packet;
|
|
mp_rf_rx_show_message_info(iot_pkt_array[0]);
|
|
rx_buf = (rf_rx_buf_hdr_t *)iot_pkt_data(iot_pkt_array[0]);
|
|
golden_rsp = (mp_rf_test_rsp_t *)((uint8_t *)rx_buf +
|
|
PB_PAYLOAD_OFFSET);
|
|
pb_end = &rx_buf->pb_ed;
|
|
rx_mpdu = &rx_buf->mpdu_st;
|
|
mac_rf_get_rx_frm_msg_from_fc(proto,
|
|
mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu), &rx_fc_msg);
|
|
|
|
if ((rx_fc_msg.delimiter == FC_DELIM_SOF) && (!pb_end->rx_pb_crc_err) &&
|
|
(rx_fc_msg.nid == glb_cfg.nid) &&
|
|
(golden_rsp->magic == MP_RF_TEST_MSG_MAGIC_NUMBER) &&
|
|
(golden_rsp->msg_id == MP_RF_MSG_ID_CSI)) {
|
|
csi_rsp->tx_rssi = max(csi_rsp->tx_rssi, golden_rsp->tx_rssi);
|
|
csi_rsp->tx_snr = max(csi_rsp->tx_snr, golden_rsp->tx_snr);
|
|
csi_rsp->tx_gain = max(golden_rsp->tx_gain, csi_rsp->tx_gain);
|
|
csi_rsp->rx_snr = max(csi_rsp->rx_snr,
|
|
mac_rf_rx_mpdu_st_get_avg_snr(rx_mpdu));
|
|
csi_rsp->rx_rssi = max(csi_rsp->rx_rssi,
|
|
mac_rf_rx_mpdu_st_get_rssi(rx_mpdu));
|
|
csi_rsp->rx_gain = max(csi_rsp->rx_gain,
|
|
mac_rf_rx_mpdu_st_get_rx_gain(rx_mpdu));
|
|
rx_count++;
|
|
if (rx_count >= 3 || (csi_rsp->tx_rssi >= tx_rssi_thr &&
|
|
csi_rsp->rx_rssi >= rx_rssi_thr &&
|
|
csi_rsp->tx_snr >= tx_snr_thr &&
|
|
csi_rsp->rx_snr >= rx_snr_thr)) {
|
|
done = 1;
|
|
}
|
|
ret = ERR_OK;
|
|
iot_printf("csi_recv: tx_rssi=%d, rx_rssi=%d, tx_snr=%d,"
|
|
" rx_snr=%d, tx_gain=%d, rx_gain=%d\n", csi_rsp->tx_rssi,
|
|
csi_rsp->rx_rssi, csi_rsp->tx_snr, csi_rsp->rx_snr,
|
|
csi_rsp->tx_gain, csi_rsp->rx_gain);
|
|
}
|
|
free_packet:
|
|
iot_pkt_free(iot_pkt_array[0]);
|
|
} while (time_span < timeout && !done);
|
|
if (!done) {
|
|
iot_printf("%s fail....\n", __FUNCTION__);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t mp_rf_dut_test_case_tx_evm(iot_ftm_mp_rf_cmd_hdr_t *cmd,
|
|
void *rsp)
|
|
{
|
|
rf_rx_pb_end *pb_end;
|
|
rf_rx_buf_hdr_t *rx_buf;
|
|
rf_rx_mpdu_start *rx_mpdu;
|
|
mp_rf_test_cmd_hdr_t *hdr;
|
|
iot_ftm_mp_rf_rsp_tx_evm_t *dut_rsp = (iot_ftm_mp_rf_rsp_tx_evm_t *)rsp;
|
|
mp_rf_test_cmd_tx_evm_t *tx_evm_cmd;
|
|
iot_ftm_mp_rf_cmd_tx_evm_t *test_cmd;
|
|
mp_rf_rsp_tx_evm_t *tx_evm_rsp;
|
|
mp_rf_test_rsp_t* golden_rsp;
|
|
iot_pkt_t *iot_pkt_array[1] = { 0 };
|
|
uint32_t timer_start, time_span, timeout, count = 0, done = 0;
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
/* get rx fc message */
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
uint8_t ret = ERR_TIMEOVER, rx_done_tmp = 0;
|
|
uint16_t packet_num, i;
|
|
|
|
hdr = (mp_rf_test_cmd_hdr_t *)g_mp_rf_ctxt->rf_pb_buf;
|
|
hdr->pld_blkz = 0;
|
|
hdr->phr_mcs = 0;
|
|
hdr->pld_mcs = 0;
|
|
hdr->power = cmd->golden_power;
|
|
hdr->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
hdr->msg_id = MP_RF_MSG_ID_TX_EVM_SAMP;
|
|
tx_evm_cmd = (mp_rf_test_cmd_tx_evm_t *)hdr->data;
|
|
iot_chip_get_mac_addr(tx_evm_cmd->mac_addr);
|
|
tx_evm_cmd->ts = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
|
|
test_cmd = (iot_ftm_mp_rf_cmd_tx_evm_t *)cmd->data;
|
|
packet_num = test_cmd->packet_num;
|
|
packet_num = min(MP_RF_TX_EVM_SMAP_MAX_CNT, packet_num);
|
|
iot_printf("%s start -- phr_mcs:%lu, pld_mcs:%lu, pld_blkz:%lu, "
|
|
"is_nor_pwr:%lu, dut_pwr:%d, golden_pwr:%d, packet_num:%lu, "
|
|
"no_req_flag:%d, interval:%lu\n", __FUNCTION__, cmd->phr_mcs,
|
|
cmd->pld_mcs, cmd->pld_blkz, test_cmd->is_nor_pwr, cmd->dut_power,
|
|
cmd->golden_power, packet_num, test_cmd->no_req_flag,
|
|
test_cmd->interval);
|
|
|
|
/* step1: send tx evm sample data to golden */
|
|
if (!test_cmd->is_nor_pwr) {
|
|
/* use the cert test mode power configuration */
|
|
mac_rf_set_cert_mode(CERT_TEST_CMD_ENTER_PHY_HPLC2RF_LP);
|
|
if (cmd->phr_mcs == MCS_ID_5 || cmd->phr_mcs == MCS_ID_6 ||
|
|
cmd->pld_mcs == MCS_ID_5 || cmd->pld_mcs == MCS_ID_6) {
|
|
/* mcs 5/6 need special config */
|
|
mac_rf_set_cert_16qam_flag(1);
|
|
} else {
|
|
mac_rf_set_cert_16qam_flag(0);
|
|
}
|
|
} else {
|
|
/* use the power configuration specified by the test script. */
|
|
mac_rf_set_target_tx_power(cmd->dut_power);
|
|
}
|
|
g_mp_rf_ctxt->phr_mcs = cmd->phr_mcs;
|
|
g_mp_rf_ctxt->pld_mcs = cmd->pld_mcs;
|
|
g_mp_rf_ctxt->pld_blkz = cmd->pld_blkz;
|
|
for (i = 0; i < packet_num; i++) {
|
|
mp_rf_tx_packet(test_cmd->interval);
|
|
}
|
|
|
|
/* step2: send command MP_RF_MSG_ID_TX_EVM_STAT_QUERY to get results from
|
|
* golden and wait for a response.
|
|
*/
|
|
timeout = MP_RF_TEST_CASE_TX_EVM_TIMEOUT_DEF;
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
mp_rf_recover_def_rate();
|
|
if (!test_cmd->is_nor_pwr) {
|
|
/* after sending the evm samples, restore the power configuration.
|
|
* for some DUT, the success rate of query results can be improved.
|
|
*/
|
|
mac_rf_set_cert_mode(0);
|
|
mac_rf_set_cert_16qam_flag(0);
|
|
mac_rf_set_target_tx_power(cmd->dut_power);
|
|
}
|
|
|
|
if (test_cmd->no_req_flag) {
|
|
return ERR_OK;
|
|
}
|
|
|
|
hdr->msg_id = MP_RF_MSG_ID_TX_EVM_STAT_QUERY;
|
|
mp_rf_tx_packet(0);
|
|
|
|
do {
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
timer_start);
|
|
time_span = MAC_NTB_TO_MS(time_span);
|
|
if (time_span >= MP_RF_CMD_RETRY_INTERVAL &&
|
|
count < MP_RF_CMD_RETRY_COUNT) {
|
|
count++;
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
timeout -= MP_RF_CMD_RETRY_INTERVAL;
|
|
mp_rf_tx_packet(0);
|
|
}
|
|
|
|
if (!rx_done_tmp) {
|
|
rx_done_tmp = mp_rf_check_rf_rx_done();
|
|
if (!rx_done_tmp) {
|
|
continue;
|
|
}
|
|
}
|
|
if (0 == rf_pop_buf_from_ring(&g_mp_rf_ctxt->rx_ring, 1,
|
|
iot_pkt_array)) {
|
|
rx_done_tmp = 0;
|
|
continue;
|
|
}
|
|
if (mp_rf_check_rx_packet(iot_pkt_array[0]))
|
|
goto free_packet;
|
|
mp_rf_rx_show_message_info(iot_pkt_array[0]);
|
|
rx_buf = (rf_rx_buf_hdr_t *)iot_pkt_data(iot_pkt_array[0]);
|
|
golden_rsp = (mp_rf_test_rsp_t *)((uint8_t *)rx_buf +
|
|
PB_PAYLOAD_OFFSET);
|
|
pb_end = &rx_buf->pb_ed;
|
|
rx_mpdu = &rx_buf->mpdu_st;
|
|
mac_rf_get_rx_frm_msg_from_fc(proto,
|
|
mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu), &rx_fc_msg);
|
|
|
|
if ((rx_fc_msg.delimiter == FC_DELIM_SOF) && (!pb_end->rx_pb_crc_err) &&
|
|
(rx_fc_msg.nid == glb_cfg.nid) &&
|
|
(golden_rsp->msg_id == MP_RF_MSG_ID_TX_EVM_STAT_QUERY) &&
|
|
(golden_rsp->magic == MP_RF_TEST_MSG_MAGIC_NUMBER)) {
|
|
|
|
tx_evm_rsp = (mp_rf_rsp_tx_evm_t *)golden_rsp->data;
|
|
dut_rsp->avg_rssi = tx_evm_rsp->avg_rssi;
|
|
dut_rsp->avg_snr = tx_evm_rsp->avg_snr;
|
|
dut_rsp->rx_cnt = tx_evm_rsp->rx_cnt;
|
|
os_mem_set(dut_rsp->rsvd, 0, sizeof(dut_rsp->rsvd));
|
|
iot_printf("%s rx_count=%lu, rssi=%f, snr=%f\n", __FUNCTION__,
|
|
tx_evm_rsp->rx_cnt, (float)tx_evm_rsp->avg_rssi / 10,
|
|
(float)tx_evm_rsp->avg_snr / 10);
|
|
ret = ERR_OK;
|
|
done = 1;
|
|
}
|
|
free_packet:
|
|
iot_pkt_free(iot_pkt_array[0]);
|
|
} while (time_span < timeout && !done);
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t mp_rf_cal_rsp_poll(uint8_t msg_id, uint8_t **buf,
|
|
uint32_t timeout, mp_rf_cal_msg_hdr_t *req_hdr)
|
|
{
|
|
uint8_t *rx_buf, *rx_pb_buf, *data;
|
|
rx_buf_hdr_t *hdr = NULL;
|
|
mp_rf_cal_msg_hdr_t *rsp_hdr;
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
uint32_t start_ntb, time_sapn;
|
|
rx_pb_end *pb_end;
|
|
start_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
for (; ;) {
|
|
if (is_rx_ring0_empty()) {
|
|
goto next;
|
|
}
|
|
rx_buf = pop_rx_buf_from_ring(0);
|
|
if (!rx_buf) {
|
|
goto next;
|
|
}
|
|
mp_rf_plc_massage_show(rx_buf);
|
|
hdr = (rx_buf_hdr_t *)rx_buf;
|
|
rx_pb_buf = (uint8_t *)(rx_buf + PB_PAYLOAD_OFFSET);
|
|
pb_end = &(hdr->pb_ed);
|
|
data = rx_pb_buf;
|
|
rsp_hdr = (mp_rf_cal_msg_hdr_t *)data;
|
|
data += sizeof(*rsp_hdr);
|
|
mac_get_rx_frm_msg_from_fc(PHY_PROTO_TYPE_GET(),
|
|
mac_rx_mpdu_st_get_fc_addr(&hdr->mpdu_st), &rx_fc_msg);
|
|
|
|
if (rx_fc_msg.delimiter == FC_DELIM_SOF && !pb_end->rx_pb_crc_err
|
|
&& rx_fc_msg.nid == glb_cfg.nid
|
|
&& rsp_hdr->magic == MP_RF_TEST_MSG_MAGIC_NUMBER
|
|
&& rsp_hdr->msg_id == msg_id) {
|
|
if (iot_mac_addr_cmp(req_hdr->dut_addr, rsp_hdr->dut_addr) == 1
|
|
&& req_hdr->sn == rsp_hdr->sn) {
|
|
*buf = rx_pb_buf;
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
next:
|
|
time_sapn = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
start_ntb);
|
|
if (MAC_NTB_TO_MS(time_sapn) > timeout) {
|
|
break;
|
|
}
|
|
}
|
|
return ERR_TIMEOVER;
|
|
}
|
|
|
|
static uint8_t mp_rf_dut_test_case_tx_cali_exec(
|
|
iot_ftm_mp_rf_cmd_tx_cali_t* test_cmd, uint8_t** buf, uint16_t dev_id_magic)
|
|
{
|
|
uint32_t pos;
|
|
mp_rf_test_cmd_tx_cali_stat_qr_t *rf_cmd;
|
|
/* get rx fc message */
|
|
int8_t i, q, ret = ERR_TIMEOVER;
|
|
uint8_t *tx_pb_buf;
|
|
uint8_t repeat_cnt, max_code;
|
|
mp_rf_cal_msg_hdr_t *rsp_hdr;
|
|
mp_rf_cal_msg_hdr_t *req_hdr;
|
|
uint8_t *bm = g_mp_rf_ctxt->snr_samp_bitmap;
|
|
uint8_t bm_size = MP_RF_TX_CALI_SNR_BM_SIZE;
|
|
|
|
max_code = (test_cmd->type == RF_TEST_TX_CALI_REG_IQ_MAG) ?
|
|
RF_PHY_IQ_MAG_COMPEN_CODE_MAX : RF_PHY_IQ_PHASE_COMPEN_CODE_MAX;
|
|
repeat_cnt = test_cmd->repeat_cnt;
|
|
while (repeat_cnt-- > 0) {
|
|
for (i = 0; i < max_code; i++) {
|
|
for (q = 0; q < max_code; q++) {
|
|
pos = MP_RF_IQ_CODE_TO_MAGIC(max_code, i, q);
|
|
if (iot_bitmap_is_set(bm, bm_size, pos + 1)) {
|
|
mp_rf_tx_mpdu_with_tx_cali_samp(test_cmd->type, i, q,
|
|
dev_id_magic);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* step 2: query result */
|
|
tx_pb_buf = (uint8_t *)phy_get_pb_buf_ptr_from_mpdu(mpdu_start);
|
|
req_hdr = (mp_rf_cal_msg_hdr_t *)tx_pb_buf;
|
|
req_hdr->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
req_hdr->msg_id = MP_RF_MSG_ID_TX_CALI_STAT_QUERY;
|
|
req_hdr->sn = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
iot_chip_get_mac_addr(req_hdr->dut_addr);
|
|
rf_cmd = (mp_rf_test_cmd_tx_cali_stat_qr_t*)req_hdr->data;
|
|
rf_cmd->dev_id_magic = dev_id_magic;
|
|
rf_cmd->type = test_cmd->type;
|
|
rf_cmd->liner_fit_en = test_cmd->liner_fit_en;
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
tx_send_packet_interval(10);
|
|
ret = mp_rf_cal_rsp_poll(MP_RF_MSG_ID_TX_CALI_STAT_QUERY, buf, 50,
|
|
req_hdr);
|
|
if (ret == ERR_OK) {
|
|
rsp_hdr = (mp_rf_cal_msg_hdr_t *)(*buf);
|
|
*buf = rsp_hdr->data;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t mp_rf_dut_test_case_tx_cali(iot_ftm_mp_rf_cmd_hdr_t *cmd,
|
|
void *rsp, uint8_t *len)
|
|
{
|
|
iot_ftm_mp_rf_cmd_tx_cali_t *test_cmd;
|
|
uint8_t ret = ERR_TIMEOVER, step;
|
|
int8_t i, q, min_i, max_i, min_q, max_q, min_code, max_code, code;
|
|
uint16_t dev_id_magic, j;
|
|
uint8_t buf[IOT_MAC_ADDR_LEN + 4];
|
|
uint8_t i_sweep_list[RF_PHY_IQ_PHASE_COMPEN_CODE_MAX];
|
|
uint8_t q_sweep_list[RF_PHY_IQ_PHASE_COMPEN_CODE_MAX], i_cnt = 0, q_cnt = 0;
|
|
uint8_t *data_buf;
|
|
mp_rf_rsp_tx_cali_t *rsp_hdr;
|
|
iot_ftm_mp_rf_rsp_tx_cali_t* dut_rsp;
|
|
uint32_t timer_start;
|
|
|
|
g_mp_rf_ctxt->phr_mcs = cmd->phr_mcs;
|
|
test_cmd = (iot_ftm_mp_rf_cmd_tx_cali_t*)cmd->data;
|
|
iot_chip_get_mac_addr(buf);
|
|
timer_start = (uint16_t)RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
os_mem_cpy(buf + IOT_MAC_ADDR_LEN, &timer_start, 4);
|
|
dev_id_magic = iot_getcrc16(buf, sizeof(buf), 0);
|
|
|
|
switch (test_cmd->type) {
|
|
case RF_TEST_TX_CALI_REG_IQ_MAG:
|
|
{
|
|
min_code = 0;
|
|
max_code = RF_PHY_IQ_MAG_COMPEN_CODE_MAX;
|
|
step = min(2, test_cmd->step);
|
|
break;
|
|
}
|
|
case RF_TEST_TX_CALI_REG_IQ_PHASE:
|
|
{
|
|
min_code = 0;
|
|
max_code = RF_PHY_IQ_PHASE_COMPEN_CODE_MAX;
|
|
step = min(4, test_cmd->step);
|
|
break;
|
|
}
|
|
default:
|
|
iot_printf("%s parameters error\n", __FUNCTION__);
|
|
ret = ERR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
min_i = min(max_code, max(min_code, test_cmd->i_min));
|
|
max_i = min(max_code, max(min_code, test_cmd->i_max));
|
|
min_q = min(max_code, max(min_code, test_cmd->q_min));
|
|
max_q = min(max_code, max(min_code, test_cmd->q_max));
|
|
|
|
if (!step)
|
|
step = 1;
|
|
iot_printf("%s tx cali type:%d, i:[%d, %d], q:[%d, %d], step:%d, "
|
|
"liner_fit_en:%d, is_nor_pwr:%d, power:%d, phr_mcs:%d, rounds:%d\n",
|
|
__FUNCTION__, test_cmd->type, min_i, max_i, min_q, max_q, step,
|
|
test_cmd->liner_fit_en, test_cmd->is_nor_pwr, cmd->dut_power,
|
|
cmd->phr_mcs, test_cmd->rounds);
|
|
if (max_i < min_i || max_q < min_q || !test_cmd->rounds) {
|
|
ret = ERR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
if (!test_cmd->is_nor_pwr) {
|
|
/* use the cert test mode power configuration */
|
|
mac_rf_set_cert_mode(CERT_TEST_CMD_ENTER_PHY_HPLC2RF_LP);
|
|
if (cmd->phr_mcs == MCS_ID_5 || cmd->phr_mcs == MCS_ID_6 ||
|
|
cmd->pld_mcs == MCS_ID_5 || cmd->pld_mcs == MCS_ID_6) {
|
|
/* mcs 5/6 need special config */
|
|
mac_rf_set_cert_16qam_flag(1);
|
|
} else {
|
|
mac_rf_set_cert_16qam_flag(0);
|
|
}
|
|
} else {
|
|
/* use the power configuration specified by the test script. */
|
|
mac_rf_set_target_tx_power(cmd->dut_power);
|
|
}
|
|
|
|
os_mem_set(g_mp_rf_ctxt->snr_samp_bitmap, 0, MP_RF_TX_CALI_SNR_BM_SIZE);
|
|
if (test_cmd->iq_delta_en) {
|
|
for (code = max_i - 1; code > -max_q; code -= step) {
|
|
if (code > 0) {
|
|
j = MP_RF_IQ_CODE_TO_MAGIC(max_code, code, 0);
|
|
} else {
|
|
j = MP_RF_IQ_CODE_TO_MAGIC(max_code, 0, -code);
|
|
}
|
|
iot_bitmap_set(g_mp_rf_ctxt->snr_samp_bitmap,
|
|
MP_RF_TX_CALI_SNR_BM_SIZE, j + 1);
|
|
}
|
|
} else {
|
|
iot_printf("%s i_sweep_list[", __FUNCTION__);
|
|
for (i = min_i; i < max_i; i += step) {
|
|
i_sweep_list[i_cnt] = i;
|
|
iot_printf("%d, ", i_sweep_list[i_cnt]);
|
|
i_cnt++;
|
|
}
|
|
if (i_sweep_list[i_cnt - 1] < max_i - 1) {
|
|
i_sweep_list[i_cnt] = max_i - 1;
|
|
iot_printf("%d", i_sweep_list[i_cnt]);
|
|
i_cnt++;
|
|
}
|
|
iot_printf("], q_sweep_list[");
|
|
for (q = min_q; q < max_q; q += step) {
|
|
q_sweep_list[q_cnt] = q;
|
|
iot_printf("%d, ", q_sweep_list[q_cnt]);
|
|
q_cnt++;
|
|
}
|
|
if (q_sweep_list[q_cnt - 1] < max_q - 1) {
|
|
q_sweep_list[q_cnt] = max_q - 1;
|
|
iot_printf("%d", q_sweep_list[q_cnt]);
|
|
q_cnt++;
|
|
}
|
|
iot_printf("]\n");
|
|
|
|
if (q_cnt * i_cnt > MP_RF_TX_CALI_SNR_REAL_DATA_GROUP_SIZE) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
for (i = 0; i < i_cnt; i++) {
|
|
for (q = 0; q < q_cnt; q++) {
|
|
j = MP_RF_IQ_CODE_TO_MAGIC(max_code, i_sweep_list[i],
|
|
q_sweep_list[q]);
|
|
iot_bitmap_set(g_mp_rf_ctxt->snr_samp_bitmap,
|
|
MP_RF_TX_CALI_SNR_BM_SIZE, j + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < test_cmd->rounds; i++) {
|
|
ret = mp_rf_dut_test_case_tx_cali_exec(test_cmd, &data_buf,
|
|
dev_id_magic);
|
|
if (ret == ERR_OK) {
|
|
rsp_hdr = (mp_rf_rsp_tx_cali_t *)data_buf;
|
|
for (j = 0; j < MP_RF_TX_CALI_SNR_BM_SIZE; j++) {
|
|
g_mp_rf_ctxt->snr_samp_bitmap[j] &= ~rsp_hdr->bm[j];
|
|
}
|
|
if (iot_bitmap_cbs(g_mp_rf_ctxt->snr_samp_bitmap,
|
|
MP_RF_TX_CALI_SNR_BM_SIZE) == 0) {
|
|
iot_printf("%s bitmap all clear, retry=%d\n", __FUNCTION__, i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ret == ERR_OK) {
|
|
*len = sizeof(iot_ftm_mp_rf_rsp_tx_cali_t);
|
|
dut_rsp = (iot_ftm_mp_rf_rsp_tx_cali_t *)rsp;
|
|
dut_rsp->cnt = min(rsp_hdr->cnt, MP_RF_TX_CALI_SNR_BEST_RESULT_MAX);
|
|
*len += sizeof(iot_ftm_mp_rf_tx_cali_comen_result_t) * dut_rsp->cnt;
|
|
iot_printf("%s best_result:", __FUNCTION__);
|
|
for (i = 0; i < dut_rsp->cnt; i++) {
|
|
dut_rsp->result[i].i = rsp_hdr->result[i].i;
|
|
dut_rsp->result[i].q = rsp_hdr->result[i].q;
|
|
dut_rsp->result[i].snr = rsp_hdr->result[i].snr;
|
|
iot_printf("[%f, %d, %d], ", __FUNCTION__, dut_rsp->result[i].snr,
|
|
dut_rsp->result[i].i, dut_rsp->result[i].q);
|
|
}
|
|
iot_printf("\n");
|
|
}
|
|
|
|
if (!test_cmd->is_nor_pwr) {
|
|
/* after sending the evm samples, restore the power configuration.
|
|
* for some DUT, the success rate of query results can be improved.
|
|
*/
|
|
mac_rf_set_cert_mode(0);
|
|
mac_rf_set_cert_16qam_flag(0);
|
|
mac_rf_set_target_tx_power(cmd->dut_power);
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t mp_rf_dut_test_case_chg_phy(iot_ftm_mp_rf_cmd_hdr_t *cmd,
|
|
void *rsp)
|
|
{
|
|
rf_rx_pb_end *pb_end;
|
|
rf_rx_buf_hdr_t *rx_buf;
|
|
rf_rx_mpdu_start *rx_mpdu;
|
|
mp_rf_test_cmd_hdr_t *hdr;
|
|
mp_rf_test_rsp_t* golden_rsp;
|
|
iot_pkt_t *iot_pkt_array[1] = { 0 };
|
|
iot_ftm_mp_rf_cmd_chg_phy_t *target_para;
|
|
mp_rf_test_cmd_chg_phy_t *phy_para;
|
|
uint32_t timer_start, time_span, timeout, count = 0, done = 0;
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
/* get rx fc message */
|
|
rx_fc_msg_t rx_fc_msg = {0};
|
|
uint8_t ret = ERR_TIMEOVER, rx_done_tmp = 0;
|
|
|
|
/* cfg DUT tx power */
|
|
mac_rf_set_target_tx_power(cmd->dut_power);
|
|
|
|
hdr = (mp_rf_test_cmd_hdr_t *)g_mp_rf_ctxt->rf_pb_buf;
|
|
hdr->pld_blkz = 0;
|
|
hdr->phr_mcs = 0;
|
|
hdr->pld_mcs = 0;
|
|
hdr->power = cmd->golden_power;
|
|
hdr->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
hdr->msg_id = MP_RF_MSG_ID_CHG_PHY;
|
|
target_para = (iot_ftm_mp_rf_cmd_chg_phy_t *)cmd->data;
|
|
phy_para = (mp_rf_test_cmd_chg_phy_t *)hdr->data;
|
|
phy_para->option = target_para->option;
|
|
phy_para->channel = target_para->channel;
|
|
|
|
iot_printf("%s start -- current phy para[option:%d channel:%d], "
|
|
"target phy para[option:%d channel:%d]\n",
|
|
__FUNCTION__, cmd->option, cmd->channel, target_para->option,
|
|
target_para->channel);
|
|
|
|
if (target_para->option == g_mp_rf_ctxt->option &&
|
|
target_para->channel == g_mp_rf_ctxt->channel) {
|
|
iot_printf("%s no need change phy parameters\n", __FUNCTION__);
|
|
ret = ERR_OK;
|
|
goto out;
|
|
}
|
|
|
|
/* step1: notify golden to switch option and channel */
|
|
mp_rf_recover_def_rate();
|
|
mp_rf_tx_packet(0);
|
|
|
|
timeout = MP_RF_TEST_CASE_CHG_PHY_TIMEOUT_DEF;
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
do {
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
timer_start);
|
|
time_span = MAC_NTB_TO_MS(time_span);
|
|
if (!done && time_span >= MP_RF_CMD_RETRY_INTERVAL &&
|
|
count < MP_RF_CMD_RETRY_COUNT) {
|
|
count++;
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
timeout -= MP_RF_CMD_RETRY_INTERVAL;
|
|
mp_rf_tx_packet(0);
|
|
}
|
|
if (!rx_done_tmp) {
|
|
rx_done_tmp = mp_rf_check_rf_rx_done();
|
|
if (!rx_done_tmp) {
|
|
continue;
|
|
}
|
|
}
|
|
if (0 == rf_pop_buf_from_ring(&g_mp_rf_ctxt->rx_ring, 1,
|
|
iot_pkt_array)) {
|
|
rx_done_tmp = 0;
|
|
continue;
|
|
}
|
|
/* after receiving the correct reply, discard all packets received
|
|
* during the waiting period. If the correct response is not received,
|
|
* discard the received exception packet.
|
|
*/
|
|
if (mp_rf_check_rx_packet(iot_pkt_array[0]))
|
|
goto free_packet;
|
|
mp_rf_rx_show_message_info(iot_pkt_array[0]);
|
|
if (done)
|
|
goto free_packet;
|
|
|
|
rx_buf = (rf_rx_buf_hdr_t *)iot_pkt_data(iot_pkt_array[0]);
|
|
golden_rsp = (mp_rf_test_rsp_t *)((uint8_t *)rx_buf +
|
|
PB_PAYLOAD_OFFSET);
|
|
pb_end = &rx_buf->pb_ed;
|
|
rx_mpdu = &rx_buf->mpdu_st;
|
|
mac_rf_get_rx_frm_msg_from_fc(proto,
|
|
mac_rf_rx_mpdu_st_get_phr_addr(rx_mpdu), &rx_fc_msg);
|
|
|
|
if ((rx_fc_msg.delimiter == FC_DELIM_SOF) && (!pb_end->rx_pb_crc_err) &&
|
|
(rx_fc_msg.nid == glb_cfg.nid) &&
|
|
(golden_rsp->magic == MP_RF_TEST_MSG_MAGIC_NUMBER) &&
|
|
(golden_rsp->msg_id == MP_RF_MSG_ID_CHG_PHY)) {
|
|
iot_printf("%s golden response successfully\n", __FUNCTION__);
|
|
ret = ERR_OK;
|
|
done = 1;
|
|
timeout = MP_RF_TEST_CASE_CHG_PHY_TIMEOUT_DEF;
|
|
timer_start = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
}
|
|
free_packet:
|
|
iot_pkt_free(iot_pkt_array[0]);
|
|
} while (time_span < timeout);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint8_t mp_rf_dut_cal_cfg(iot_ftm_mp_rf_cal_meas_cfg_t *cfg)
|
|
{
|
|
uint8_t *tx_pb_buf, *rx_pb_buf, i;
|
|
uint8_t *data, result;
|
|
mp_rf_cal_msg_hdr_t *req_hdr, *rsp_hdr;
|
|
mp_rf_cal_meas_cfg_t *meas_cfg;
|
|
mp_rf_cal_plc_comm_init(MP_RF_PLC_INIT_BAND);
|
|
tx_pb_buf = (uint8_t *)phy_get_pb_buf_ptr_from_mpdu(mpdu_start);
|
|
data = tx_pb_buf;
|
|
|
|
req_hdr = (mp_rf_cal_msg_hdr_t *)data;
|
|
req_hdr->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
req_hdr->msg_id = MP_RF_CAL_MSG_ID_MEAS_CFG;
|
|
req_hdr->sn = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
iot_chip_get_mac_addr(req_hdr->dut_addr);
|
|
|
|
/* update DUT communication power and tmi */
|
|
phy_pwr_adjust_set(cfg->comm_pwr);
|
|
glb_cfg.tmi = MP_RF_PLC_NORMAL_PACKET_TMI;
|
|
data += sizeof(*req_hdr);
|
|
meas_cfg = (mp_rf_cal_meas_cfg_t *)data;
|
|
meas_cfg->meas_en = cfg->meas_en;
|
|
meas_cfg->option = cfg->option;
|
|
meas_cfg->ch = cfg->ch;
|
|
|
|
meas_cfg->comm_pwr = cfg->comm_pwr;
|
|
meas_cfg->comm_tmi = MP_RF_PLC_NORMAL_PACKET_TMI;
|
|
|
|
iot_printf("%s en:%lu,option:%lu,ch:%lu,comm_pwr:%lu,comm_tmi:%lu\n",
|
|
__FUNCTION__, cfg->meas_en, cfg->option, cfg->ch, cfg->comm_pwr,
|
|
cfg->comm_tmi);
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
tx_send_packet_interval(10);
|
|
result = mp_rf_cal_rsp_poll(req_hdr->msg_id, &rx_pb_buf, 50, req_hdr);
|
|
if (result == ERR_OK) {
|
|
rsp_hdr = (mp_rf_cal_msg_hdr_t *)rx_pb_buf;
|
|
result = rsp_hdr->option;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= 5) {
|
|
result = ERR_TIMEOVER;
|
|
}
|
|
iot_printf("%s result:%lu\n", __FUNCTION__, result);
|
|
return result;
|
|
}
|
|
|
|
void mp_rf_dut_cal_reg_update(iot_ftm_mp_rf_tx_cal_update_t *cal_update)
|
|
{
|
|
#define TX_CAL_UPDATE_TIMEOUT 5000000
|
|
uint32_t start_ntb, time_span;
|
|
|
|
if (cal_update->tx_iq_mag_update) {
|
|
mac_rf_set_tx_iqm_cali(cal_update->tx_i_mag, cal_update->tx_q_mag);
|
|
iot_printf("%s, iq_mag[%d %d]\n", __FUNCTION__,
|
|
cal_update->tx_i_mag, cal_update->tx_q_mag);
|
|
}
|
|
if (cal_update->tx_iq_phase_update) {
|
|
mac_rf_set_tx_iqp_cali(cal_update->tx_i_phase, cal_update->tx_q_phase);
|
|
iot_printf("%s, iq_phase[%d %d]\n", __FUNCTION__,
|
|
cal_update->tx_i_phase, cal_update->tx_q_phase);
|
|
}
|
|
if (cal_update->tx_iq_dc_update) {
|
|
mac_rf_set_tx_dc_cali(cal_update->tx_i_dc, cal_update->tx_q_dc);
|
|
iot_printf("%s, iq_dc[%d %d]\n ", __FUNCTION__,
|
|
cal_update->tx_i_dc, cal_update->tx_q_dc);
|
|
}
|
|
if (cal_update->filter_update) {
|
|
mac_rf_set_tx_filter_cali(cal_update->filter_option, 1,
|
|
cal_update->filter_bw_sel);
|
|
iot_printf("%s, option:%lu, filter:%lu\n", __FUNCTION__,
|
|
cal_update->filter_option, cal_update->filter_bw_sel);
|
|
}
|
|
|
|
mac_rf_set_tx_cal_update_status(0);
|
|
mac_rf_set_sw_irq_to_bbcpu(RF_MAC_SW_ISR_TX_CAL_UPDATE);
|
|
/* wait bbcpu update RF calibration register */
|
|
start_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
while (!mac_rf_get_tx_cal_update_status()) {
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
start_ntb);
|
|
if (time_span > TX_CAL_UPDATE_TIMEOUT) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void mp_rf_dut_cal_meas_pwr(iot_ftm_mp_rf_cal_meas_req_t *req,
|
|
iot_ftm_mp_rf_cal_meas_rsp_t *rsp)
|
|
{
|
|
uint8_t *tx_pb_buf, *rx_pb_buf, i;
|
|
uint8_t *data, ret = ERR_OK;
|
|
mp_rf_cal_msg_hdr_t *req_hdr, *rsp_hdr;
|
|
mp_rf_cal_meas_req_t *meas_req;
|
|
mp_rf_cal_meas_rsp_t *meas_rsp;
|
|
uint32_t start_ntb, time_span;
|
|
uint32_t timeout;
|
|
/* initialize HPLC phy */
|
|
mp_rf_cal_plc_comm_init(MP_RF_PLC_INIT_BAND);
|
|
start_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
|
|
tx_pb_buf = (uint8_t *)phy_get_pb_buf_ptr_from_mpdu(mpdu_start);
|
|
data = tx_pb_buf;
|
|
req_hdr = (mp_rf_cal_msg_hdr_t *)data;
|
|
req_hdr->magic = MP_RF_TEST_MSG_MAGIC_NUMBER;
|
|
req_hdr->msg_id = MP_RF_CAL_MSG_ID_MEAS_REQ;
|
|
req_hdr->sn = start_ntb;
|
|
iot_chip_get_mac_addr(req_hdr->dut_addr);
|
|
|
|
/* step1: update the specified tx calibration register before measuring
|
|
* power.
|
|
*/
|
|
mp_rf_dut_cal_reg_update(&req->tx_cal);
|
|
|
|
data += sizeof(*req_hdr);
|
|
meas_req = (mp_rf_cal_meas_req_t *)data;
|
|
meas_req->lo_freq = req->lo_freq;
|
|
meas_req->tone_idx = req->tone_idx;
|
|
meas_req->dc_idx = req->dc_idx;
|
|
meas_req->img_idx = req->img_idx;
|
|
meas_req->avg_cnt = req->avg_cnt;
|
|
os_mem_set(meas_req->rsvd, 0, sizeof(meas_req->rsvd));
|
|
/* TODO: it is necessary to adjust the optimal retry policy to balance the
|
|
* communication reliability and efficiency.
|
|
*/
|
|
timeout = req->timeout;
|
|
for (i = 0; i < req->try_cnt; i++) {
|
|
tx_send_packet_interval(10);
|
|
ret = mp_rf_cal_rsp_poll(req_hdr->msg_id, &rx_pb_buf, timeout, req_hdr);
|
|
if (ret) {
|
|
continue;
|
|
}
|
|
rsp_hdr = (mp_rf_cal_msg_hdr_t *)rx_pb_buf;
|
|
ret = rsp_hdr->option;
|
|
if (ret) {
|
|
rsp->err_no = ret;
|
|
break;
|
|
}
|
|
ret = ERR_OK;
|
|
meas_rsp = (mp_rf_cal_meas_rsp_t *)rsp_hdr->data;
|
|
rsp->gain = meas_rsp->gain_x100;
|
|
rsp->tone_pwr = meas_rsp->tone_pwr;
|
|
rsp->dc_pwr = meas_rsp->dc_pwr;
|
|
rsp->img_pwr = meas_rsp->img_pwr;
|
|
os_mem_set(rsp->rsvd, 0x0, sizeof(rsp->rsvd));
|
|
break;
|
|
}
|
|
rsp->err_no = ret;
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
start_ntb);
|
|
iot_printf("%s result:%lu, cons:%lums, lo_freq:%luHz, idx:[%d, %d, %d], "
|
|
"power[%d, %d, %d], gain %lu\n", __FUNCTION__, ret,
|
|
MAC_NTB_TO_MS(time_span), req->lo_freq, req->tone_idx, req->dc_idx,
|
|
req->img_idx, rsp->tone_pwr, rsp->dc_pwr, rsp->img_pwr,
|
|
rsp->gain);
|
|
|
|
}
|
|
|
|
static void mp_rf_common_timer_func(uint32_t id, void *arg)
|
|
{
|
|
(void)id;
|
|
(void)arg;
|
|
os_set_task_event_with_v(_init_handle, 1 << MP_RF_EVT_ID_TIMEROUT);
|
|
}
|
|
|
|
void mp_rf_ctxt_init(uint8_t is_golden, uint8_t option, uint8_t channel)
|
|
{
|
|
if (!g_mp_rf_ctxt) {
|
|
g_mp_rf_ctxt = (mp_rf_ctxt_t*)os_mem_malloc(IOT_FTM_MID,
|
|
sizeof(mp_rf_ctxt_t));
|
|
if (!g_mp_rf_ctxt)
|
|
IOT_ASSERT(0);
|
|
}
|
|
if (is_golden) {
|
|
rf_phy_power_meas_init();
|
|
g_mp_rf_ctxt->is_golden = 1;
|
|
g_mp_rf_ctxt->target_option = option;
|
|
g_mp_rf_ctxt->target_channel = channel;
|
|
g_mp_rf_ctxt->common_timer = os_create_timer(IOT_FTM_MID, true,
|
|
mp_rf_common_timer_func, NULL);
|
|
mp_rf_cal_plc_comm_init(MP_RF_PLC_INIT_BAND);
|
|
g_mp_rf_ctxt->led_gpio = iot_board_get_led(IOT_PLC_RX_LED);
|
|
iot_gpio_open_as_output(g_mp_rf_ctxt->led_gpio);
|
|
os_start_timer(g_mp_rf_ctxt->common_timer,
|
|
MP_RF_GOLDEN_COMMON_TIMER_PERIOD);
|
|
}
|
|
}
|
|
|
|
uint32_t mp_rf_dut_test_phy_cfg(uint8_t option, uint8_t channel)
|
|
{
|
|
if (!g_mp_rf_ctxt) {
|
|
mp_rf_ctxt_init(0, 0, 0);
|
|
}
|
|
mp_rf_common_init(option, channel);
|
|
return ERR_OK;
|
|
}
|
|
|
|
void mp_rf_dut_test_case_handle(iot_ftm_mp_rf_cmd_hdr_t *cmd,
|
|
iot_ftm_mp_rf_rsp_hdr_t *rsp_hdr, uint8_t *len)
|
|
{
|
|
uint8_t ret, tmp = 0;
|
|
*len = sizeof(*rsp_hdr);
|
|
|
|
mp_rf_dut_test_phy_cfg(cmd->option, cmd->channel);
|
|
mp_rf_cal_plc_comm_init(MP_RF_PLC_INIT_BAND);
|
|
|
|
switch (cmd->id) {
|
|
case IOT_FTM_MP_RF_CASE_ID_CSR:
|
|
{
|
|
ret = mp_rf_dut_test_case_csr(cmd, rsp_hdr->data);
|
|
tmp = sizeof(iot_ftm_mp_rf_rsp_csr_t);
|
|
break;
|
|
}
|
|
case IOT_FTM_MP_RF_CASE_ID_CSI:
|
|
{
|
|
ret = mp_rf_dut_test_case_csi(cmd, rsp_hdr->data);
|
|
tmp = sizeof(iot_ftm_mp_rf_rsp_csi_t);
|
|
break;
|
|
}
|
|
case IOT_FTM_MP_RF_CASE_ID_TX_EVM:
|
|
{
|
|
ret = mp_rf_dut_test_case_tx_evm(cmd, rsp_hdr->data);
|
|
tmp = sizeof(iot_ftm_mp_rf_rsp_tx_evm_t);
|
|
break;
|
|
}
|
|
case IOT_FTM_MP_RF_CASE_ID_CHG_PHY:
|
|
{
|
|
ret = mp_rf_dut_test_case_chg_phy(cmd, rsp_hdr->data);
|
|
break;
|
|
}
|
|
case IOT_FTM_MP_RF_CASE_ID_TX_CALI_BY_SNR:
|
|
{
|
|
ret = mp_rf_dut_test_case_tx_cali(cmd, rsp_hdr->data, &tmp);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ret = ERR_NOSUPP;
|
|
break;
|
|
}
|
|
}
|
|
rsp_hdr->id = cmd->id;
|
|
rsp_hdr->result = ret;
|
|
if (ret == ERR_OK) {
|
|
*len += tmp;
|
|
}
|
|
if (g_mp_rf_ctxt->rf_phy_inited) {
|
|
mac_rf_rx_ring_enable(&g_mp_rf_ctxt->rx_ring, 0);
|
|
}
|
|
}
|
|
|
|
static uint8_t mp_rf_common_timer_handle()
|
|
{
|
|
uint8_t toggle_flag = 0;
|
|
uint32_t time_span;
|
|
|
|
if (g_mp_rf_ctxt->rf_phy_changing) {
|
|
time_span = mp_rf_ntb_span_calc(RGF_MAC_READ_REG(CFG_RD_NTB_ADDR),
|
|
g_mp_rf_ctxt->rf_phy_chg_ts);
|
|
time_span = MAC_NTB_TO_MS(time_span);
|
|
if (time_span >= MP_RF_TEST_CASE_CHG_PHY_EXEC_DELAY) {
|
|
g_mp_rf_ctxt->rf_phy_changing = 0;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
g_mp_rf_ctxt->timeout_count++;
|
|
/* blinking cycle 100ms */
|
|
if (g_mp_rf_ctxt->is_cal_mode) {
|
|
toggle_flag = 1;
|
|
} else {
|
|
/* blinking cycle 500ms */
|
|
if (g_mp_rf_ctxt->timeout_count % 5 == 1) {
|
|
toggle_flag = 1;
|
|
}
|
|
}
|
|
|
|
if (toggle_flag) {
|
|
iot_gpio_value_set(g_mp_rf_ctxt->led_gpio, (int)g_mp_rf_ctxt->led_status);
|
|
g_mp_rf_ctxt->led_status = !g_mp_rf_ctxt->led_status;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mp_rf_golden_unit_main(uint32_t option, uint32_t channel)
|
|
{
|
|
uint8_t reinit_req;
|
|
uint32_t events;
|
|
|
|
mp_rf_ctxt_init(1, option, channel);
|
|
/* set nid by gpio status */
|
|
glb_cfg.nid = mp_pt_golden_nid_config();
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
if (glb_cfg.nid > PLC_NID_MAX_SPG)
|
|
glb_cfg.nid = PLC_NID_MAX_SPG;
|
|
#endif
|
|
if (iot_board_is_overseas_rf_band()) {
|
|
phy_rf_band_info_init(PHY_RF_BAND_OVERSEAS);
|
|
} else {
|
|
phy_rf_band_info_init(PHY_RF_BAND_NSG);
|
|
}
|
|
iot_printf("Global nid has been set to %d.\n", glb_cfg.nid);
|
|
|
|
reinit:
|
|
mp_rf_common_init(g_mp_rf_ctxt->target_option,
|
|
g_mp_rf_ctxt->target_channel);
|
|
for (; ;) {
|
|
events = os_wait_task_event_with_v(MAX_TIME);
|
|
if (events & (1 << MP_RF_EVT_ID_PLC_RX)) {
|
|
reinit_req = mp_rf_golden_plc_rx();
|
|
if (reinit_req) {
|
|
goto reinit;
|
|
}
|
|
}
|
|
if (events & (1 << MP_RF_EVT_ID_RF_RX)) {
|
|
mp_rf_golden_rf_rx();
|
|
}
|
|
if (events & (1 << MP_RF_EVT_ID_TIMEROUT)) {
|
|
reinit_req = mp_rf_common_timer_handle();
|
|
if (reinit_req) {
|
|
goto reinit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#else /* IOT_MP_SUPPORT == 1 && HPLC_RF_DEV_SUPPORT */
|
|
|
|
uint32_t mp_rf_dut_test_phy_cfg(uint8_t option, uint8_t channel)
|
|
{
|
|
(void)option;
|
|
(void)channel;
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
void mp_rf_dut_test_case_handle(iot_ftm_mp_rf_cmd_hdr_t *cmd,
|
|
iot_ftm_mp_rf_rsp_hdr_t *rsp_hdr, uint8_t *len)
|
|
{
|
|
(void)cmd;
|
|
*len = sizeof(*rsp_hdr);
|
|
rsp_hdr->result = ERR_NOSUPP;
|
|
rsp_hdr->id = cmd->id;
|
|
}
|
|
|
|
void mp_rf_golden_unit_main(uint32_t option, uint32_t channel)
|
|
{
|
|
(void)option;
|
|
(void)channel;
|
|
}
|
|
|
|
uint8_t mp_rf_dut_cal_cfg(iot_ftm_mp_rf_cal_meas_cfg_t *cfg)
|
|
{
|
|
(void)cfg;
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
void mp_rf_dut_cal_reg_update(iot_ftm_mp_rf_tx_cal_update_t *cal_update)
|
|
{
|
|
(void)cal_update;
|
|
}
|
|
|
|
void mp_rf_dut_cal_meas_pwr(iot_ftm_mp_rf_cal_meas_req_t *req,
|
|
iot_ftm_mp_rf_cal_meas_rsp_t *rsp)
|
|
{
|
|
(void)req;
|
|
(void)rsp;
|
|
}
|
|
|
|
void mp_rf_clear_rf_common()
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|