801 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			801 lines
		
	
	
		
			28 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 "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, ¤t_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 */
							 |