/**************************************************************************** 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_dump.h" #include "phy_bb.h" #include "os_types.h" #include "hw_reg_api.h" #include "iot_io.h" #include "phy_reg.h" #include "phy_rxtd_reg.h" #include "phy_rx_fd_reg.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" uint32_t g_nf_buf[TONE_MAX_NUM] = {0}; void phy_snr_dump_mode_set(phy_snr_dump_mode_t mode) { #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; /* select dump mode */ tmp = PHY_RX_FD_READ_REG(CFG_BB_SNR_ADDR); REG_FIELD_SET(SW_SNR_DUMP_MODE,tmp, mode); //REG_FIELD_SET(SW_DUMP_DATA_SHIFT,tmp, 3); PHY_RX_FD_WRITE_REG(CFG_BB_SNR_ADDR,tmp); #else (void)mode; #endif } void phy_snr_dump_en(bool_t en) { #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; /* dump en */ tmp = PHY_RX_FD_READ_REG(CFG_BB_SNR_ADDR); REG_FIELD_SET(SW_SNR_DUMP_EN, tmp, en); PHY_RX_FD_WRITE_REG(CFG_BB_SNR_ADDR,tmp); #else (void)en; #endif } bool_t phy_snr_dump_wait_done() { #if HW_PLATFORM >= HW_PLATFORM_FPGA int32_t tmp = 0; tmp = PHY_RX_FD_READ_REG(CFG_BB_SNR_ADDR); return REG_FIELD_GET(SW_SNR_DUMP_DONE,tmp); #endif } void phy_spur_dump_en(bool_t en) { #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; /* dump start */ tmp = PHY_RX_FD_READ_REG(CFG_BB_SPUR_STAT_ADDR); REG_FIELD_SET(SW_SPUR_STAT_START, tmp, en); PHY_RX_FD_WRITE_REG(CFG_BB_SPUR_STAT_ADDR,tmp); #else (void)en; #endif } bool_t phy_spur_dump_wait_done() { #if HW_PLATFORM >= HW_PLATFORM_FPGA int32_t tmp = 0; tmp = PHY_RX_FD_READ_REG(CFG_BB_SPUR_STAT_ADDR); return REG_FIELD_GET(SW_SPUR_STAT_DONE,tmp); #endif } void phy_sound_dump_cond_set( \ bool_t snid_en, \ uint8_t snid, \ bool_t dtei_en, \ uint8_t dtei) { #if HW_PLATFORM >= HW_PLATFORM_FPGA int32_t tmp = 0; /* dump en */ tmp = PHY_RX_FD_READ_REG(CFG_BB_SOUND_DUMP_ADDR); REG_FIELD_SET(SW_MATCH_DTEI, tmp, dtei); REG_FIELD_SET(SW_MATCH_SNID, tmp, snid); REG_FIELD_SET(SW_MATCH_DTEI_EN, tmp, dtei_en); REG_FIELD_SET(SW_MATCH_SNID_EN, tmp, snid_en); PHY_RX_FD_WRITE_REG(CFG_BB_SOUND_DUMP_ADDR,tmp); #else (void)snid_en; (void)snid; (void)dtei_en; (void)dtei; #endif } /* snr calibrate */ uint32_t phy_rx_snr_get( \ uint32_t start, \ uint32_t end, \ int32_t *buf, \ uint32_t dly_cnt) { #if HW_PLATFORM >= HW_PLATFORM_FPGA int32_t tmp = 0; int32_t snr = 0; uint32_t i = 0; uint32_t tone_idx = 0; /* det start and end tone */ phy_rxfd_rate0_det(start,end); /* select dump mode */ phy_snr_dump_mode_set(PHY_SNR_DUMP_SNR1); phy_snr_dump_en(true); /* wait until dump done */ while(!phy_snr_dump_wait_done()) { if(tmp++ > dly_cnt) { return ERR_FAIL; } } /* cal snr for every tone */ for(tone_idx = start; tone_idx < end; ) { tmp = SOC_READ_REG(BB_SNR_BASEADDR + tone_idx*2); #if PHY_DBG_EN iot_printf( \ "[tone id-%d] signal:%d, noise:%d\n" "[tone id-%d] signal:%d, noise:%d\n", \ tone_idx, (tmp >> 8) & 0xff,(tmp >> 0) & 0xff, \ tone_idx+1, (tmp >> 24) & 0xff,(tmp >> 16) & 0xff); #endif snr = (int32_t)((( \ ((tmp >> 8) & 0xff) - ((tmp >> 0) & 0xff) \ ) * 3) >> 3); buf[i++] = snr; snr = (int32_t)((( \ ((tmp >> 24) & 0xff) - ((tmp >> 16) & 0xff) \ )*3) >> 3); buf[i++] = snr; tone_idx += 2; } #else (void)start; (void)end; (void)buf; #endif return ERR_OK; } /* softbit dump */ uint32_t phy_rx_softbit_get( \ uint32_t start, \ uint32_t end, \ int32_t *buf, \ uint32_t dly_cnt) { #if HW_PLATFORM >= HW_PLATFORM_FPGA int32_t tmp = 0; uint32_t i = 0; uint32_t tone_idx = 0; /* det start and end tone */ phy_rxfd_rate0_det(start,end); /* select dump mode */ PHY_WRITE_REG(CFG_BB_INT_CLR_0_EXT_ADDR, 0xffffffff); phy_snr_dump_mode_set(PHY_SNR_DUMP_SOFTBIT); phy_snr_dump_en(true); /* wait until dump done */ while (!phy_snr_dump_wait_done()) { if (tmp++ > dly_cnt) { return ERR_FAIL; } } /* softbit I/Q for every tone */ for (tone_idx = start; tone_idx < end; ) { tmp = SOC_READ_REG(BB_SNR_BASEADDR + tone_idx*2); #if PHY_DBG_EN int8_t pwr_i = 0, pwr_q = 0; /* tone idx 0 I */ pwr_i = tmp & 0xff; /* tone idx 0 Q */ pwr_q = (tmp >> 8) & 0xff; iot_printf("tone%d softbit:I=%d, Q=%d\n", \ tone_idx, pwr_i, pwr_q); /* tone idx 0 I */ pwr_i = (tmp >> 16) & 0xff; /* tone idx 0 Q */ pwr_q = (tmp >> 24) & 0xff; iot_printf("tone%d softbit:I=%d,Q=%d\n", \ tone_idx + 1, pwr_i, pwr_q); #endif buf[i++] = tmp; tone_idx += 2; } #else (void)start; (void)end; (void)buf; #endif return ERR_OK; } /* csi calibrate */ uint32_t phy_rx_csi_get( \ uint32_t start, \ uint32_t end, \ uint32_t *buf, \ uint32_t dly_cnt) { #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; uint32_t i = 0; uint32_t tone_idx = 0; int16_t pwr_i = 0, pwr_q = 0; #if MAC_RX_TEST_ID == MAC_RX_CSI_SCAN && \ HW_PLATFORM >= HW_PLATFORM_SILICON /* right shift for signal saturation */ phy_gain_shift_set(0,0,0,3); #endif /* det start and end tone */ phy_rxfd_rate0_det(start,end); /* select dump mode */ phy_snr_dump_mode_set(PHY_SNR_DUMP_CSI); phy_snr_dump_en(true); /* wait until dump done */ while(!phy_snr_dump_wait_done()) { if(tmp++ > dly_cnt) { return ERR_FAIL; } } /* cal snr for every tone */ for(tone_idx = start; tone_idx < end; ) { tmp = SOC_READ_REG(BB_SNR_BASEADDR + tone_idx*2); /* tone idx 0 I */ pwr_i = tmp & 0xff; if(pwr_i & 0x80) { pwr_i = pwr_i - 256; } /* tone idx 0 Q */ pwr_q = (tmp >> 8) & 0xff; if(pwr_q & 0x80) { pwr_q = pwr_q - 256; } #if PHY_DBG_EN iot_printf("tone%d csi:I=%d,Q=%d\n", \ tone_idx, pwr_i, pwr_q); #endif buf[i++] = pow(pwr_i, 2) + pow(pwr_q, 2); /* tone idx 1 I */ pwr_i = (tmp >> 16) & 0xff; if(pwr_i & 0x80) { pwr_i = pwr_i - 256; } /* tone idx 1 Q */ pwr_q = (tmp >> 24) & 0xff; if(pwr_q & 0x80) { pwr_q = pwr_q - 256; } #if PHY_DBG_EN iot_printf("tone%d csi:I=%d,Q=%d\n", \ tone_idx + 1, pwr_i, pwr_q); #endif buf[i++] = pow(pwr_i, 2) + pow(pwr_q, 2); tone_idx += 2; } #else (void)start; (void)end; (void)buf; #endif return 0; } /* spur cal */ uint32_t phy_rx_spur_get( \ uint32_t start, \ uint32_t end, \ uint32_t *buf, \ uint32_t dly_cnt) { #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; uint32_t tone_idx = 0; uint32_t i = 0; #if PHY_DBG_EN uint32_t start_time = 0, end_time = 0; int64_t time_span = 0; #endif /* det start and end tone */ phy_rxfd_rate0_det(start,end); /* start spur */ phy_spur_dump_en(true); #if PHY_DBG_EN /* start time after enable */ start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); #endif /* wait until dump done */ while (!phy_spur_dump_wait_done()) { if (tmp++ > dly_cnt) { return ERR_FAIL; } } #if PHY_DBG_EN /* end time after done */ end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end_time - start_time; /* wrap around */ if (time_span < 0) { time_span = (0x100000000LL) - start_time + end_time; } iot_printf("[Spur][Elapsed Time] %lldns\r\n", time_span * 40); #endif /* cal spur for every tone */ for (tone_idx = start; tone_idx < end; ) { tmp = SOC_READ_REG(BB_SNR_BASEADDR + tone_idx * 2); buf[i++] = tmp & 0xFFFF; buf[i++] = (tmp >> 16) & 0xFFFF; tone_idx += 2; } #else (void)start; (void)end; (void)buf; #endif return 0; } /* noise floor cal */ uint32_t phy_rx_noise_floor_get( \ uint32_t start, \ uint32_t end, \ uint32_t *buf, \ uint32_t dly_cnt, \ phy_snr_dump_mode_t mode) { #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; uint32_t tone_idx = 0; uint32_t i = 0; #if PHY_DBG_EN uint32_t start_time = 0, end_time = 0; int64_t time_span = 0; #endif #if HW_PLATFORM == HW_PLATFORM_SILICON /* right shift for signal saturation */ phy_gain_shift_set(0, 0, 0, 3); #endif /* det start and end tone */ phy_rxfd_rate0_det(start,end); /* en noise floor */ phy_snr_dump_mode_set(mode); phy_snr_dump_en(true); #if PHY_DBG_EN /* start time after enable */ start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); #endif /* wait until dump done */ while(!phy_snr_dump_wait_done()) { if(tmp++ > dly_cnt) { return ERR_FAIL; } } #if PHY_DBG_EN /* end time after done */ end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end_time - start_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - start_time + end_time; } iot_printf("[Noise Floor][Elapsed Time] %lldns\r\n", time_span*40); #endif /* cal noise floor for every tone */ for(tone_idx = start; tone_idx < end; ) { tmp = SOC_READ_REG(BB_SNR_BASEADDR+tone_idx*2); buf[i++] = tmp & 0xFFFF; buf[i++] = (tmp >> 16) & 0xFFFF; tone_idx += 2; } #if HW_PLATFORM == HW_PLATFORM_SILICON /* recover right shift */ phy_gain_shift_set(0, 0, 0, 0); #endif #else (void)start; (void)end; (void)buf; #endif return 0; } /* sound dump */ uint32_t phy_rx_sound_snr_get( \ uint32_t start, \ uint32_t end, \ int32_t *buf, \ uint32_t dly_cnt) { #if HW_PLATFORM >= HW_PLATFORM_FPGA int32_t tmp = 0; int32_t snr = 0; uint32_t i = 0; uint32_t tone_idx = 0; /* det start and end tone */ phy_rxfd_rate0_det(start,end); /* select dump mode */ phy_snr_dump_mode_set(PHY_SNR_DUMP_SOUND_EST); phy_snr_dump_en(true); /* wait until dump done */ while(!phy_snr_dump_wait_done()) { if(tmp++ > dly_cnt) { return ERR_FAIL; } } /* cal snr for every tone */ for(tone_idx = start; tone_idx < end; ) { tmp = SOC_READ_REG(BB_SNR_BASEADDR + tone_idx*2); #if PHY_DBG_EN iot_printf( \ "[tone id-%d] signal:%d, noise:%d\n" "[tone id-%d] signal:%d, noise:%d\n", \ tone_idx, (tmp >> 8) & 0xff,(tmp >> 0) & 0xff, \ tone_idx+1, (tmp >> 24) & 0xff,(tmp >> 16) & 0xff); #endif snr = (int32_t)((( \ ((tmp >> 8) & 0xff) - ((tmp >> 0) & 0xff) \ ) * 3) >> 3); buf[i++] = snr; snr = (int32_t)((( \ ((tmp >> 24) & 0xff) - ((tmp >> 16) & 0xff) \ )*3) >> 3); buf[i++] = snr; tone_idx += 2; } #else (void)start; (void)end; (void)buf; #endif return 0; } uint32_t phy_rx_noise_dump( \ uint32_t *buf_ptr, \ int8_t gain, \ uint8_t pkt_idx, \ uint8_t pkt_max) { uint32_t ret = ERR_OK; #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; /* check pkt idx and max valid */ IOT_ASSERT(pkt_idx < pkt_max && pkt_max <= FFT_DUMP_PKT_MAX); /* first dump pkt */ if(pkt_idx == 0) { /* save force value */ tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_0_ADDR); g_phy_ctxt.dep.rx_phase_force_en = \ REG_FIELD_GET(CFG_PHY_RX_PHASE_SEL_FORCE_EN, tmp); g_phy_ctxt.dep.rx_phase_force = \ REG_FIELD_GET(CFG_PHY_RX_PHASE_SEL, tmp); /* fix gain and disable agc */ phy_agc_gain_lvl_set(1,gain,-24,0); /* enable rx all phase */ phy_rx_phase_force_set(true, PLC_PHASE_ALL); ret = phy_rx_noise_floor_get(0, TONE_MAX_NUM, g_nf_buf, PHY_DUMP_DLY_CNT, PHY_SNR_DUMP_NF); /* disable fix gain */ phy_agc_gain_lvl_set(0,60,-24,0); if(ret != ERR_OK) { iot_printf("file=%s,func=%s,line=%d fail!\n", \ __FILE__, __FUNCTION__, __LINE__); return ret; } /* enable sw csi buf access */ enable_sw_access_csi_buf(1); } /* memcpy data from csi buf to buf */ os_mem_cpy(buf_ptr, \ g_nf_buf + pkt_idx * (IOT_PHY_CSI_BUF_LEN >> 2), \ IOT_PHY_CSI_BUF_LEN); /* last dump pkt */ if(pkt_idx == (pkt_max - 1)) { /* enable sw csi buf access */ enable_sw_access_csi_buf(0); /* recover force */ phy_rx_phase_force_set( \ g_phy_ctxt.dep.rx_phase_force_en, \ g_phy_ctxt.dep.rx_phase_force); } #else (void)buf_ptr; (void)gain; (void)pkt_idx; (void)pkt_max; #endif return ret; } void phy_fft_dump_prepare() { #if HW_PLATFORM >= HW_PLATFORM_FPGA uint32_t tmp = 0; uint32_t fft_loop = 1; /* config det tone */ phy_rxfd_rate0_det(0, TOTAL_TONE_MASK_NUM - 4); /* tone disable */ phy_dfe_tone_cfg(0,0,0); /* force inte rx state */ phy_txrx_ovr_set(1,1); /* disable packet detect timeout */ phy_pkt_time_out_disable(true); /* bypass dc blocker */ tmp = PHY_DFE_READ_REG(CFG_BB_DC_BLK_STAGE_DLY_ADDR); REG_FIELD_SET(SW_DC_BLK_BYPASS, tmp, 1); PHY_DFE_WRITE_REG(CFG_BB_DC_BLK_STAGE_DLY_ADDR, tmp); /* disable adj req and sat */ phy_agc_sat_adj_set(1,1); tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR); REG_FIELD_SET(SW_LOOPBACK_EN, tmp, 1); PHY_DFE_WRITE_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR, tmp); /* en adc and rx, disable dac and tx */ phy_ana_tx_en(false); phy_ana_rx_en(true); phy_ana_enlic_en(PHY_ENLIC_TXRX_RX); /* trig fft */ tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR); REG_FIELD_SET(SW_LOOP_FFT_CYCLE, tmp, fft_loop); REG_FIELD_SET(SW_LOOP_FFT_START, tmp, 1); PHY_DFE_WRITE_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR, tmp); #endif } void phy_increase_tgt_pwr(uint32_t spur_exist) { (void)spur_exist; }