Files
kunlun/plc/halphy/phy_bbai_calu_2.c
2024-09-28 14:24:04 +08:00

801 lines
28 KiB
C
Executable File

/****************************************************************************
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 "iot_config.h"
#include "phy_bbai_calu.h"
#include "phy_dump.h"
#include "phy_bb.h"
#include "os_types.h"
#include "hw_reg_api.h"
#include "iot_io.h"
#include "mac_sys_reg.h"
#include "iot_errno_api.h"
#include "hw_tonemask.h"
#include "phy_ana.h"
#include "phy_bb.h"
#include "phy_dfe_reg.h"
#include "phy_data.h"
#include "hw_phy_api.h"
#include "phy_phase.h"
#include "math.h"
#include "phy_ana.h"
#include "math_log10.h"
#include "hw_phy_api.h"
#include "phy_dump_hw.h"
#include "phy_tools.h"
#include "phy_perf.h"
#include "phy_math_tb.h"
#if PHY_BBAI_ALGORITHM == PHY_BBAI_SLIDE_WINDOWS
#define PHY_CHN_EST_AI_SPUR_LEN (684)
/* 0: not care;
* 1: closer to the left;
* 2: closer to the right;
*/
typedef enum{
POSITION_NOT_CARE = 0,
POSITION_CLOSER_LEFT = 1,
POSITION_CLOSER_RIGHT = 2,
}POSITION_INFO;
/* spur array */
typedef struct _iot_phy_spur{
/* notch filter enable */
uint8_t notch_filter_en_cnt;
/* PHY_BBAI_FIX_WINDOWS :color
* PHY_BBAI_SLIDE_WINDOWS: is max spur
*/
uint8_t color;
/* tone number */
uint16_t tone_id;
/* center/sidelobe */
uint32_t spur_ratio;
/* spur occur cnt */
uint16_t spur_cnt;
uint8_t position_left_cnt;
uint8_t position_right_cnt;
} iot_phy_spur_t;
static uint32_t phy_spur_arry_peak_handler(
iot_phy_spur_t *spur_buf, uint32_t buf_len, uint32_t est_rty_cnt)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
#define MAX_PLUSE_LEN 400
uint32_t spur_total_len = 0;
uint32_t max_ratio = 0, sec_ratio = 0;
uint16_t max_spur_id = 0, notch_alpha = 0, sec_spur_id = 0;
/* max spur left or right. secend spur left right */
uint8_t max_spur_lr = POSITION_NOT_CARE, sec_spur_lr = POSITION_NOT_CARE;
uint16_t max_spur_lr_id = 0, sec_spur_lr_id = 0;
uint16_t inband_tone_mask_curr = 0, inband_tone_mask_total = 0;
uint32_t cmp_thd_cnt = est_rty_cnt >> 1;
uint32_t band_id = phy_band_id_get();
uint32_t pluse_idx = 0, pluse_max_idx = 0, pluse_max_vle = 0;
uint32_t spur_vld_cnt = 0, last_tone = 0;
iot_pkt_t *pluse_pkt = NULL;
uint16_t *pluse_buf = NULL;
if (g_phy_cpu_share_ctxt.pt_mode_entry == 1) {
return ERR_NOSUPP;
}
/* get mem from iot_pkt to save pluse data */
IOT_PKT_GET(pluse_pkt, MAX_PLUSE_LEN, 0, PLC_PHY_COMMON_MID);
if (!pluse_pkt) {
iot_printf("phy peak hdl, get pluse pkt fail\n");
return ERR_FAIL;
}
pluse_buf = (uint16_t *)iot_pkt_put(pluse_pkt, MAX_PLUSE_LEN);
/* valid check */
IOT_ASSERT(spur_buf != NULL && buf_len > 0);
/* first fft pwr full for band narrow */
if (band_id == IOT_SUPPORT_TONE_32_120 ||
band_id == IOT_SUPPORT_TONE_MULTI_BAND021) {
cmp_thd_cnt = (cmp_thd_cnt > 0) ? (cmp_thd_cnt - 1) : 0;
}
/* cal total spur len */
spur_total_len = buf_len/sizeof(iot_phy_spur_t);
/* cal max mask tone number */
/* multiband special config */
if (band_id == IOT_SUPPORT_TONE_MULTI_BAND021) {
inband_tone_mask_total = 5;
} else {
inband_tone_mask_total = all_mask_band_table_r0_full.valid_tone_number/3;
}
/* scan all spur */
for (uint32_t i = 0; i < spur_total_len; i++) {
if (spur_buf[i].tone_id != 0) {
iot_printf("[BB_AI] spur: %u, cnt: %u, ismax:%d, lcnt:%d, rcnt:%d\n",
spur_buf[i].tone_id, spur_buf[i].spur_cnt, spur_buf[i].color,
spur_buf[i].position_left_cnt,
spur_buf[i].position_right_cnt);
/* check spike */
if (spur_buf[i].spur_cnt > cmp_thd_cnt) {
/* just check max */
if (spur_buf[i].color == 1) {
spur_vld_cnt++;
if (spur_vld_cnt == 1) {
last_tone = spur_buf[i].tone_id;
} else {
if (spur_buf[i].tone_id > last_tone) {
pluse_idx = spur_buf[i].tone_id - last_tone;
} else {
pluse_idx = last_tone - spur_buf[i].tone_id;
}
last_tone = spur_buf[i].tone_id;
/* only care about the peak length of MAX_PLUSE_LEN */
if (pluse_idx < (MAX_PLUSE_LEN >> 1)) {
pluse_buf[pluse_idx]++;
if (spur_vld_cnt == 2) {
pluse_max_idx = pluse_idx;
pluse_max_vle = pluse_buf[pluse_idx];
} else {
if (pluse_buf[pluse_idx] > pluse_max_vle) {
pluse_max_vle = pluse_buf[pluse_idx];
pluse_max_idx = pluse_idx;
}
}
}
}
}
/* check inband max masked number */
if ((spur_buf[i].tone_id >= all_mask_band_table_r0_full.start_tone &&
spur_buf[i].tone_id <= all_mask_band_table_r0_full.end_tone) ||
(spur_buf[i].tone_id >= all_mask_band_table_r1_full.start_tone &&
spur_buf[i].tone_id <= all_mask_band_table_r1_full.end_tone)) {
if (inband_tone_mask_curr < inband_tone_mask_total) {
inband_tone_mask_curr++;
/* mask spur */
phy_spur_mask_set(spur_buf[i].tone_id, 0);
iot_printf("[BB_AI] spur tone: %u mask done!\n",
spur_buf[i].tone_id);
} else {
/* do nothing for other inband tone */
continue;
}
} else {
/* mask spur */
phy_spur_mask_set(spur_buf[i].tone_id, 0);
iot_printf("[BB_AI] spur tone: %u mask done!\n",
spur_buf[i].tone_id);
}
/* notch filter set */
if (spur_buf[i].notch_filter_en_cnt > cmp_thd_cnt) {
/* find max spur */
if (!g_phy_ctxt.indep.notch_filter_en) {
g_phy_ctxt.indep.notch_filter_en = true;
max_ratio = spur_buf[i].spur_ratio;
max_spur_id = spur_buf[i].tone_id;
if (spur_buf[i].position_left_cnt >
spur_buf[i].position_right_cnt) {
max_spur_lr = POSITION_CLOSER_LEFT;
} else if (spur_buf[i].position_right_cnt >
spur_buf[i].position_left_cnt) {
max_spur_lr = POSITION_CLOSER_RIGHT;
}
sec_ratio = 0;
sec_spur_id = 0;
} else if (max_ratio < spur_buf[i].spur_ratio &&
spur_buf[i].tone_id < 512 &&
spur_buf[i].color) {
/* record second largest */
if (sec_spur_id != max_spur_id &&
spur_buf[i].color) {
sec_ratio = max_ratio;
sec_spur_id = max_spur_id;
sec_spur_lr = max_spur_lr;
}
/* record max */
max_ratio = spur_buf[i].spur_ratio;
max_spur_id = spur_buf[i].tone_id;
if (spur_buf[i].position_left_cnt >
spur_buf[i].position_right_cnt) {
max_spur_lr = POSITION_CLOSER_LEFT;
} else if (spur_buf[i].position_right_cnt >
spur_buf[i].position_left_cnt) {
max_spur_lr = POSITION_CLOSER_RIGHT;
}
} else if (sec_ratio < spur_buf[i].spur_ratio &&
spur_buf[i].tone_id < 512 && spur_buf[i].color) {
/* record second largest */
if (sec_spur_id != spur_buf[i].tone_id &&
spur_buf[i].color) {
sec_ratio = spur_buf[i].spur_ratio;
sec_spur_id = spur_buf[i].tone_id;
if (spur_buf[i].position_left_cnt >
spur_buf[i].position_right_cnt) {
sec_spur_lr = POSITION_CLOSER_LEFT;
} else if (spur_buf[i].position_right_cnt >
spur_buf[i].position_left_cnt) {
sec_spur_lr = POSITION_CLOSER_RIGHT;
}
}
}
}
}
}
}
/* multiband special config */
if (band_id == IOT_SUPPORT_TONE_MULTI_BAND021) {
if ((max_spur_id >= all_mask_band_table_r0_full.start_tone &&
max_spur_id <= all_mask_band_table_r0_full.end_tone) ||
(sec_spur_id >= all_mask_band_table_r0_full.start_tone &&
sec_spur_id <= all_mask_band_table_r0_full.end_tone)) {
iot_printf("clear inband tonemask on multiband\n");
/* clear to avoid mask over for time-varying spur */
phy_tone_mask_amp_phase_tab_load(&all_mask_amp_phase_table,
phy_mask_id_get(), PHY_PROTO_TYPE_GET());
if (max_spur_id >= all_mask_band_table_r0_full.start_tone &&
max_spur_id <= all_mask_band_table_r0_full.end_tone) {
phy_spur_mask_set(max_spur_id, 2);
iot_printf("[BB_AI] spur tone: %u mask done!\n",
max_spur_id);
} else {
phy_spur_mask_set(sec_spur_id, 2);
iot_printf("[BB_AI] spur tone: %u mask done!\n",
sec_spur_id);
}
}
}
/* sw calcualte pluse */
if (spur_vld_cnt > 10) {
uint32_t pluse_cnt = pluse_buf[pluse_max_idx] +
pluse_buf[pluse_max_idx - 1] + pluse_buf[pluse_max_idx + 1];
/* more than 1/2 the pulse is considered present */
if (pluse_cnt > spur_vld_cnt * 0.5) {
g_phy_cpu_share_ctxt.spike_exist = 1;
g_phy_cpu_share_ctxt.spike_value = pluse_max_idx;
}
}
iot_printf("pluse exist:%d, pluse tone %d, vldcnt:%lu cnt-1:%lu, "
"cnt:%lu, cnt+1:%lu, maxspur:%d, lr:%d, secspur:%d, lr:%d\n",
g_phy_cpu_share_ctxt.spike_exist, pluse_max_idx, spur_vld_cnt,
pluse_buf[pluse_max_idx - 1], pluse_buf[pluse_max_idx],
pluse_buf[pluse_max_idx + 1], max_spur_id, max_spur_lr,
sec_spur_id, sec_spur_lr);
/* notch filter config */
if (max_ratio) {
g_phy_cpu_share_ctxt.spur_exist = 1;
notch_alpha = phy_alpha_cal(max_spur_id);
phy_anf_option_set(PHY_ANF_MODE_FIX, 1, 1, notch_alpha);
if (max_spur_lr == POSITION_CLOSER_LEFT) {
if (max_spur_id) {
max_spur_lr_id = max_spur_id - 1;
}
notch_alpha = phy_alpha_cal(max_spur_lr_id);
} else if (max_spur_lr == POSITION_CLOSER_RIGHT) {
max_spur_lr_id = max_spur_id + 1;
notch_alpha = phy_alpha_cal(max_spur_lr_id);
}
phy_fnf_option_set(PHY_FNF_MODE_FIX, 1, notch_alpha);
notch_alpha = phy_alpha_cal(sec_spur_id);
phy_anf_option_set(PHY_ANF_MODE_FIX, 1, 2, notch_alpha);
if (sec_spur_lr == POSITION_CLOSER_LEFT) {
if (sec_spur_id) {
sec_spur_lr_id = sec_spur_id - 1;
}
notch_alpha = phy_alpha_cal(sec_spur_lr_id);
} else if (sec_spur_lr == POSITION_CLOSER_RIGHT) {
sec_spur_lr_id = sec_spur_id + 1;
notch_alpha = phy_alpha_cal(sec_spur_lr_id);
}
phy_fnf_option_set(PHY_FNF_MODE_FIX, 2, notch_alpha);
/* for jilin spur cert test */
extern void mac_cert_test_tt_special(uint32_t tone_id);
mac_cert_test_tt_special(max_spur_id);
phy_check_spur_cert_handle(notch_alpha);
iot_printf("[BB_AI] notch filter max:%d - %d, sec: %d - %d enable!\n",
max_spur_id, max_spur_lr_id, sec_spur_id, sec_spur_lr_id);
}
iot_pkt_free(pluse_pkt);
#else
(void *)spur_buf;
(void)buf_len;
(void)est_rty_cnt;
#endif
return ERR_OK;
}
static uint32_t phy_spur_arry_append(iot_phy_spur_t *spur_buf,
uint32_t buf_len, uint16_t tone_id, uint8_t pwr_ratio,
bool_t notch_en, uint32_t is_max, uint8_t left_right)
{
uint32_t ret = ERR_OK;
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t i = 0;
bool_t tone_find_en = false;
uint32_t spur_buf_size = buf_len/sizeof(iot_phy_spur_t);
/* valid check */
IOT_ASSERT(spur_buf != NULL && buf_len > 0);
/*
* spur mask valid for inband only, notch filter for all.
*/
if (spur_buf[spur_buf_size - 1].tone_id != 0) {
/* check same tone_id */
for(i = 0; i < spur_buf_size; i++)
{
/* tone exist */
if (spur_buf[i].tone_id == tone_id) {
spur_buf[i].spur_cnt++;
spur_buf[i].spur_ratio = (spur_buf[i].spur_ratio > pwr_ratio) ?
spur_buf[i].spur_ratio :
pwr_ratio;
spur_buf[i].notch_filter_en_cnt += notch_en;
spur_buf[i].color = is_max;
if (left_right == POSITION_CLOSER_LEFT) {
spur_buf[i].position_left_cnt++;
} else if (left_right == POSITION_CLOSER_RIGHT) {
spur_buf[i].position_right_cnt++;
}
tone_find_en = true;
break;
}
}
/* if not exist */
if (tone_find_en != true) {
/* find the minimal spur */
uint32_t min_spur_idx = 0;
uint32_t min_spur_ratio = spur_buf[0].spur_ratio;
for (i = 0; i < spur_buf_size; i++) {
if (min_spur_ratio > spur_buf[i].spur_ratio) {
min_spur_ratio = spur_buf[i].spur_ratio;
min_spur_idx = i;
}
}
/* fill */
spur_buf[min_spur_idx].tone_id = tone_id;
spur_buf[min_spur_idx].spur_cnt = 1;
spur_buf[min_spur_idx].spur_ratio = pwr_ratio;
spur_buf[min_spur_idx].notch_filter_en_cnt = notch_en;
spur_buf[min_spur_idx].color = is_max;
if (left_right == POSITION_CLOSER_LEFT) {
spur_buf[min_spur_idx].position_left_cnt = 1;
spur_buf[min_spur_idx].position_right_cnt = 0;
} else if (left_right == POSITION_CLOSER_RIGHT) {
spur_buf[min_spur_idx].position_left_cnt = 0;
spur_buf[min_spur_idx].position_right_cnt = 1;
} else {
spur_buf[min_spur_idx].position_left_cnt = 0;
spur_buf[min_spur_idx].position_right_cnt = 0;
}
}
} else {
for(i = 0; i < spur_buf_size; i++)
{
/* tone exist */
if (spur_buf[i].tone_id == tone_id) {
spur_buf[i].spur_cnt++;
spur_buf[i].spur_ratio = (spur_buf[i].spur_ratio > pwr_ratio) ?
spur_buf[i].spur_ratio :
pwr_ratio;
spur_buf[i].notch_filter_en_cnt += notch_en;
spur_buf[i].color = is_max;
if (left_right == POSITION_CLOSER_LEFT) {
spur_buf[i].position_left_cnt++;
} else if (left_right == POSITION_CLOSER_RIGHT) {
spur_buf[i].position_right_cnt++;
}
break;
} else if (spur_buf[i].tone_id == 0) {
/* add new */
spur_buf[i].tone_id = tone_id;
spur_buf[i].spur_cnt++;
spur_buf[i].spur_ratio = pwr_ratio;
spur_buf[i].notch_filter_en_cnt += notch_en;
spur_buf[i].color = is_max;
if (left_right == POSITION_CLOSER_LEFT) {
spur_buf[i].position_left_cnt++;
} else if (left_right == POSITION_CLOSER_RIGHT) {
spur_buf[i].position_right_cnt++;
}
break;
}
}
}
#else
(void *)spur_buf;
(void)buf_len;
(void)tone_id;
(void)pwr_ratio;
(void)notch_en;
#endif
return ret;
}
static uint32_t phy_chn_est_dmpd_process(uint8_t *pwr_buf, uint32_t *csi_buf,
uint16_t *detect_buf, iot_phy_spur_t *spur_buf, int8_t *current_gain,
uint8_t pkt_idx)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t i = 0, j = 0, zone;
int16_t csi_i = 0, csi_q = 0;
uint32_t dump_valid_cnt = 0;
uint64_t inband_pwr = 0;
uint64_t outband_pwr = 0;
uint32_t tone_idx = 0;
uint32_t max_idx = 0;
int32_t max_value = 0;
int32_t row_sum = 0;
uint32_t window_length;
bool_t full_flag = false;
uint32_t pwr_value = 0;
uint32_t bbai_nf = phy_get_nf_of_bbai();
uint8_t left_right = POSITION_NOT_CARE;
/* range of calculation */
zone = IOT_PHY_CSI_BUF_LEN >> 2;
/* cal csi for every tone for debug*/
for (tone_idx = 0; tone_idx < zone; tone_idx++) {
/* tone 0 is abnormal, set to 20 */
if (pkt_idx == 0 && tone_idx == 0) {
*(pwr_buf + tone_idx) = 20;
continue;
}
csi_i = (int16_t)(*(csi_buf + tone_idx) & 0xFFFF);
csi_q = (int16_t)(*(csi_buf + tone_idx) >> 16);
pwr_value =
(uint32_t)(10 * mlog10(csi_i * csi_i + csi_q * csi_q + 1));
#if PHY_DEBUG_EN
iot_printf("tone:%u, csi_i:%d, csi_q:%d, dB:%u\n",
tone_idx + pkt_idx * 512, csi_i, csi_q, pwr_value);
#endif
/* check full */
if ((csi_i > PHY_CHN_EST_AI_FULL_PWR ||
csi_i < -PHY_CHN_EST_AI_FULL_PWR) ||
(csi_q > PHY_CHN_EST_AI_FULL_PWR ||
csi_q < -PHY_CHN_EST_AI_FULL_PWR) ||
pwr_value > PHY_CHN_EST_PWR_LIMIT) {
/* if current gain is not least gain,
* decrease gain and discard this data.
* else use this data.
*/
if (*current_gain != -PHY_AGC_GAIN_ENTRY_OFFSET) {
full_flag = true;
break;
}
}
*(pwr_buf + tone_idx) = (uint8_t)pwr_value;
}
if (full_flag) {
/* reint full flag */
full_flag = false;
uint8_t gain_step = ((bbai_nf > PHY_CHN_EST_AI_SPUR_NF_THD) ?
(PHY_CHN_EST_AI_GAIN_STEP << 1) : (PHY_CHN_EST_AI_GAIN_STEP));
/* decrease gain */
if ((*current_gain - gain_step + PHY_AGC_GAIN_ENTRY_OFFSET) > 0) {
*current_gain -= (int8_t)gain_step;
} else {
*current_gain = -PHY_AGC_GAIN_ENTRY_OFFSET;
}
iot_printf("[BB_AI] pwr full, decrease gain to:%d\n", *current_gain);
return ERR_FAIL;
}
if (pkt_idx == 0) {
/* cal outband total pwr */
outband_pwr = 0;
for (j = 1; j < PHY_CHN_VALID_TONE_NUM + 1; j++) {
outband_pwr += *(pwr_buf +
g_plc_band_tbl_r0[HW_FULL_BAND]->start_tone - j);
}
/* cal outband average pwr */
outband_pwr = outband_pwr/PHY_CHN_VALID_TONE_NUM;
/* check outband pwr */
if (!outband_pwr) {
return ERR_FAIL;
}
/* cal inband pwr */
for (j = 0; j < PHY_CHN_VALID_TONE_NUM; j++) {
inband_pwr = *(pwr_buf +
g_plc_band_tbl_r0[HW_FULL_BAND]->start_tone + j);
/* pkt feature: inband > outband 10dB */
if (inband_pwr <= outband_pwr ||
((inband_pwr - outband_pwr) < PHY_FD_PKT_CHECK_THD)) {
dump_valid_cnt += 1;
}
}
/* check valid dump */
if (dump_valid_cnt < (PHY_CHN_VALID_TONE_NUM >> 1)) {
iot_printf("[BB_AI] find pkt, valid cnt:%u\n", dump_valid_cnt);
return ERR_FAIL;
}
}
/* the maximum value is found at a certain interval */
for (j = 1; j < ((zone >> 1) + 1); j++) {
row_sum = 0;
for (i = j; i < zone - j; i++) {
if (*(pwr_buf + i) >= *(pwr_buf + i - j) &&
*(pwr_buf + i) >= *(pwr_buf + i + j)) {
row_sum++;
}
/* row_sum can't exceed the max_value, we can stop early */
if ((max_value - row_sum) > (int32_t)(zone - j - i)) {
break;
}
}
/* find max row */
if (row_sum > max_value) {
max_idx = j;
max_value = row_sum;
}
}
window_length = max_idx;
for (j = 1; j < (window_length + 1); j++) {
for (i = j; i < zone - j; i++) {
if (*(pwr_buf + i) > *(pwr_buf + i - j) &&
*(pwr_buf + i) > *(pwr_buf + i + j)) {
detect_buf[i]++;
} else if (j == 1 && i + 2 < zone &&
*(pwr_buf + i) == *(pwr_buf + i + j)) {
if (*(pwr_buf + i) > *(pwr_buf + i - j) &&
*(pwr_buf + i) > *(pwr_buf + i + j + 1)) {
detect_buf[i]++;
}
}
}
}
float window_thd = window_length * 0.75;
if (window_length > 2 && window_length * 0.15 < 1) {
window_thd = window_length - 2;
}
for (i = 0; i < zone; i++) {
if (detect_buf[i] > (uint32_t)window_thd) {
if (pwr_buf[i] > 45) {
if (i && (i < zone -1) && detect_buf[i] == window_length) {
if (pwr_buf[i + 1] > pwr_buf[i - 1]) {
left_right = POSITION_CLOSER_RIGHT;
} else {
left_right = POSITION_CLOSER_LEFT;
}
}
phy_spur_arry_append(spur_buf, PHY_CHN_EST_AI_SPUR_LEN,
i + pkt_idx * (IOT_PHY_CSI_BUF_LEN >> 2), pwr_buf[i], true,
(detect_buf[i] == window_length), left_right);
}
}
}
#else
(void)csi_buf;
(void)spur_buf;
(void)current_gain;
(void)pkt_idx;
#endif
return ERR_OK;
}
uint32_t phy_chn_est_ai(int8_t current_gain, uint32_t est_rty_cnt,
uint32_t timeout_ms)
{
uint32_t success_cnt = 0;
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t i = 0;
uint32_t ret = ERR_OK;
uint32_t start_time = 0, end_time = 0;
int64_t time_span = 0;
iot_pkt_t *csi_pkt = NULL;
uint32_t *csi_buf = NULL;
iot_pkt_t *pwr_pkt = NULL;
uint8_t *pwr_buf = NULL;
iot_pkt_t *detect_pkt = NULL;
uint16_t *detect_buf = NULL;
iot_pkt_t *spur_pkt = NULL;
iot_phy_spur_t *spur_buf = NULL;
uint8_t pkt_idx = 0;
/* check dump busy flag */
if (phy_busy_get(&g_phy_ctxt, PHY_BUSY_DUMP)) {
iot_printf("phy dump busy!\n");
goto err1;
} else {
phy_dump_busy_set(true);
}
/* get start time */
start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
/* get mem from iot_pkt to save csi data */
IOT_PKT_GET(csi_pkt, IOT_PHY_CSI_BUF_LEN, 0, PLC_PHY_COMMON_MID);
if (!csi_pkt) {
iot_printf("phy chn est error, get csi pkt fail\n");
goto err2;
}
csi_buf = (uint32_t *)iot_pkt_put(csi_pkt, IOT_PHY_CSI_BUF_LEN);
/* get mem from iot_pkt to save power data */
IOT_PKT_GET(pwr_pkt, IOT_PHY_PWR_BUF_LEN, 0, PLC_PHY_COMMON_MID);
if (!pwr_pkt) {
iot_printf("phy chn est error, get power pkt fail\n");
goto err3;
}
pwr_buf = (uint8_t *)iot_pkt_put(pwr_pkt, IOT_PHY_PWR_BUF_LEN);
/* get mem from iot_pkt to save detect data */
IOT_PKT_GET(detect_pkt, IOT_PHY_DETECT_BUF_LEN, 0, PLC_PHY_COMMON_MID);
if (!detect_pkt) {
iot_printf("phy chn est error, get detect pkt fail\n");
goto err4;
}
detect_buf = (uint16_t *)iot_pkt_put(detect_pkt, IOT_PHY_DETECT_BUF_LEN);
/* get mem from iot_pkt to save spur data */
IOT_PKT_GET(spur_pkt, PHY_CHN_EST_AI_SPUR_LEN, 0, PLC_PHY_COMMON_MID);
if (!spur_pkt) {
iot_printf("phy chn est error, get spur pkt fail\n");
goto err5;
}
spur_buf = (iot_phy_spur_t *)iot_pkt_put(spur_pkt, PHY_CHN_EST_AI_SPUR_LEN);
/* get average gain */
current_gain = phy_gain_get_from_agc();
if (current_gain > PHY_BBAI_GAIN_MAX) {
current_gain = PHY_BBAI_GAIN_MAX;
}
/* check csi buf pointer valid and flag */
if (csi_buf != NULL) {
/* rst to trig enable */
phy_reset(PHY_RST_REASON_WARM);
/* get valid fft dump */
for (i = 0; i < est_rty_cnt; i++) {
os_mem_set(detect_buf, 0, IOT_PHY_DETECT_BUF_LEN);
for (pkt_idx = 0; pkt_idx < FFT_DUMP_PKT_MAX; pkt_idx++) {
/* trig fft to dump */
ret = phy_rx_fft_dump(csi_buf, current_gain, pkt_idx,
FFT_DUMP_PKT_MAX);
if (ret != ERR_OK) {
/* clr dump and close current dump */
phy_rx_fft_dump(csi_buf, current_gain,
FFT_DUMP_PKT_MAX - 1, FFT_DUMP_PKT_MAX);
break;
}
/* don't care more than 25M */
if (FFT_DUMP_PKT_MAX - 1 == pkt_idx) {
break;
}
ret = phy_chn_est_dmpd_process(pwr_buf,
csi_buf, detect_buf, spur_buf, &current_gain, pkt_idx);
if (ret != ERR_OK) {
/* clr dump and close current dump */
phy_rx_fft_dump(csi_buf, current_gain,
FFT_DUMP_PKT_MAX - 1, FFT_DUMP_PKT_MAX);
break;
}
}
/* record successful dump cnt */
if (ret == ERR_OK) {
success_cnt++;
}
/* check timeout */
end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
/* cal span time */
time_span = end_time - start_time;
if (time_span < 0) { // wrap around
time_span = (0x100000000LL) - start_time + end_time;
}
/* break if timeout */
if (time_span >= timeout_ms * NTB_TICKS_PER_MS) {
break;
}
}
#if PHY_DEBUG_EN
uint32_t spur_buf_size1 = PHY_CHN_EST_AI_SPUR_LEN/sizeof(iot_phy_spur_t);
for (i = 0; i < spur_buf_size1; i++) {
iot_printf("B tone:%d, spur_cnt:%d, ratio:%d, notch_cnt:%d, "
"is_max:%d\n", spur_buf[i].tone_id, spur_buf[i].spur_cnt,
spur_buf[i].spur_ratio, spur_buf[i].notch_filter_en_cnt,
spur_buf[i].color);
}
#endif
/* get peak point */
phy_spur_arry_peak_handler(spur_buf, PHY_CHN_EST_AI_SPUR_LEN, success_cnt);
} else {
iot_printf("csi buf pointer get fail from iot_pkt!\n");
}
/* get end time */
end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
/* cal span time */
time_span = end_time - start_time;
if (time_span < 0) { // wrap around
time_span = (0x100000000LL) - start_time + end_time;
}
/* for kl3 */
phy_increase_tgt_pwr(g_phy_cpu_share_ctxt.spur_exist);
iot_printf("start_time:%u, end time:%u, bbai success cnt:%d\n",
start_time, end_time, success_cnt);
/* free spur pkt */
iot_pkt_free(spur_pkt);
err5:
/* free detect pkt */
iot_pkt_free(detect_pkt);
err4:
/* free pwr pkt */
iot_pkt_free(pwr_pkt);
err3:
/* free csi pkt */
iot_pkt_free(csi_pkt);
err2:
phy_dump_busy_set(false);
err1:
#else
(void)est_rty_cnt;
(void)timeout_ms;
#endif
return success_cnt;
}
#endif /* PHY_BBAI_ALGORITHM == PHY_BBAI_SLIDE_WINDOWS */