744 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			744 lines
		
	
	
		
			23 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 "hw_reg_api.h"
 | |
| #include "chip_reg_base.h"
 | |
| #include "ada_reg.h"
 | |
| #include "iot_config.h"
 | |
| #include "phy_dfe_reg.h"
 | |
| #include "phy_rx_fd_reg.h"
 | |
| #include "phy_rxtd_reg.h"
 | |
| #include "phy_cal.h"
 | |
| #include "phy_ana.h"
 | |
| #include "ahb.h"
 | |
| #include "ahb_hw.h"
 | |
| #include "phy_reg.h"
 | |
| #include "clk.h"
 | |
| #include "mac_sys_reg.h"
 | |
| #include "math_log10.h"
 | |
| #include "hw_tonemask.h"
 | |
| #include "phy_isr.h"
 | |
| #include "os_types.h"
 | |
| #include "iot_errno_api.h"
 | |
| #include "plc_protocol.h"
 | |
| #include "granite_reg.h"
 | |
| #include "phy_cfg.h"
 | |
| #include "phy_perf.h"
 | |
| #include "hw_phy_init.h"
 | |
| #include "phy_dump.h"
 | |
| #if HW_PLATFORM > HW_PLATFORM_SIMU
 | |
| #include "dbg_io.h"
 | |
| #endif
 | |
| #include "iot_io.h"
 | |
| #include "phy_data.h"
 | |
| #include "os_mem.h"
 | |
| #include "hw_phy_api.h"
 | |
| #include "phy_tools.h"
 | |
| #include "mpdu_header.h"
 | |
| 
 | |
| /* ada common init */
 | |
| void ada_common_init(uint16_t tone_id, uint32_t b_size, uint32_t s_size)
 | |
| {
 | |
|     /* dac init */
 | |
|     phy_ada_dump_dac_init(tone_id);
 | |
| 
 | |
|     phy_dac_en_cfg(false);
 | |
| 
 | |
|     /* delay */
 | |
|     phy_busy_wait(ADA_DUMP_INIT_DLY_CNT);
 | |
| 
 | |
|     /* adc init */
 | |
|     phy_ada_dump_adc_init(tone_id, b_size, s_size);
 | |
| 
 | |
|     /* gen tone if tone id > 0 for ada loopback */
 | |
|     if (tone_id > 0) {
 | |
|         /* att */
 | |
|         phy_dfe_tone_att_cfg(0, ADA_DUMP_R_SHIFT_NUM, 0);
 | |
|         /* config tone id */
 | |
|         phy_dfe_tone_cfg(1, tone_id, 0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void adc_trigger()
 | |
| {
 | |
|     /* trigger ADC */
 | |
|     phy_adc_trig_en_cfg(false);
 | |
|     phy_adc_trig_en_cfg(true);
 | |
| }
 | |
| 
 | |
| void dumpMem(uint8_t *mem_buf, int32_t st_offset, uint32_t b_size)
 | |
| {
 | |
|     int16_t *p_addr = NULL;
 | |
|     int16_t check_bits = 0;
 | |
| #if ADC_DUMP_DATA_SEL == ADC_DUMP_SEL_GAIN_RAW
 | |
|     uint8_t gain_entry = 0;
 | |
|     int16_t gain = 0;
 | |
| #endif
 | |
| 
 | |
|     p_addr = (int16_t *)(mem_buf + st_offset*4);
 | |
|     /* print the pre-trig buf to the end */
 | |
|     iot_printf("[dump]\n");
 | |
|     while(p_addr <= (int16_t *)(mem_buf + b_size*4))
 | |
|     {
 | |
| #if ADC_DUMP_DATA_SEL == ADC_DUMP_SEL_GAIN_RAW
 | |
|         /* gain entry */
 | |
|         if((*p_addr)&0x4000){
 | |
|             gain_entry = ((*p_addr)&0x3c00)>>6;
 | |
|             gain_entry |= (*(p_addr+1)&0x3c00)>>10;
 | |
|         }
 | |
|         else{
 | |
|             gain_entry = ((*p_addr)&0x3c00)>>10;
 | |
|             gain_entry |= (*(p_addr+1)&0x3c00)>>6;
 | |
|         }
 | |
|         gain = phy_gain_val_get(all_mask_gain_table[gain_entry] & 0xff, \
 | |
|                                 (all_mask_gain_table[gain_entry] >> 8) & 0xff);
 | |
| 
 | |
|         if((*p_addr)&0x200)
 | |
|             iot_printf("%hd,%02d,%6d\n",((*p_addr)&0x8000)>>15, \
 | |
|                     gain,((*p_addr)&0x3ff)-1024);
 | |
|         else
 | |
|             iot_printf("%hd,%02d,%6d\n",((*p_addr)&0x8000)>>15, \
 | |
|                     gain,(*p_addr)&0x3ff);
 | |
|         if(*(p_addr+1)&0x200)
 | |
|             iot_printf("%hd,%02d,%6d\n",(*(p_addr+1)&0x8000)>>15, \
 | |
|                     gain,(*(p_addr+1)&0x3ff)-1024);
 | |
|         else
 | |
|             iot_printf("%hd,%02d,%6d\n",(*(p_addr+1)&0x8000)>>15, \
 | |
|                     gain,*(p_addr+1)&0x3ff);
 | |
| #else
 | |
| #if DATA_INV_EN
 | |
|         iot_printf("%06d\n",*(p_addr+1));
 | |
|         iot_printf("%06d\n",*p_addr);
 | |
| #else
 | |
|         iot_printf("%06d\n",*p_addr);
 | |
|         iot_printf("%06d\n",*(p_addr+1));
 | |
| #endif
 | |
| #endif
 | |
|         check_bits = *p_addr ^ check_bits;
 | |
|         check_bits = *(p_addr+1) ^ check_bits;
 | |
|         p_addr += 2;
 | |
|     }
 | |
| 
 | |
|     /* print the begin to start offset */
 | |
|     p_addr = (int16_t *)(mem_buf);
 | |
|     while(p_addr < (int16_t *)(mem_buf + st_offset*4))
 | |
|     {
 | |
| #if ADC_DUMP_DATA_SEL == ADC_DUMP_SEL_GAIN_RAW
 | |
|         /* gain entry */
 | |
|         if((*p_addr)&0x4000){
 | |
|             gain_entry = ((*p_addr)&0x3c00)>>6;
 | |
|             gain_entry |= (*(p_addr+1)&0x3c00)>>10;
 | |
|         }
 | |
|         else{
 | |
|             gain_entry = ((*p_addr)&0x3c00)>>10;
 | |
|             gain_entry |= (*(p_addr+1)&0x3c00)>>6;
 | |
|         }
 | |
|         gain = phy_gain_val_get(all_mask_gain_table[gain_entry] & 0xff, \
 | |
|                                 (all_mask_gain_table[gain_entry] >> 8) & 0xff);
 | |
| 
 | |
|         if((*p_addr)&0x200)
 | |
|             iot_printf("%hd,%02d,%6d\n",((*p_addr)&0x8000)>>15, \
 | |
|                     gain,((*p_addr)&0x3ff)-1024);
 | |
|         else
 | |
|             iot_printf("%hd,%02d,%6d\n",((*p_addr)&0x8000)>>15, \
 | |
|                     gain,(*p_addr)&0x3ff);
 | |
|         if(*(p_addr+1)&0x200)
 | |
|             iot_printf("%hd,%02d,%6d\n",(*(p_addr+1)&0x8000)>>15, \
 | |
|                     gain,(*(p_addr+1)&0x3ff)-1024);
 | |
|         else
 | |
|             iot_printf("%hd,%02d,%6d\n",(*(p_addr+1)&0x8000)>>15, \
 | |
|                     gain,*(p_addr+1)&0x3ff);
 | |
| #else
 | |
| #if DATA_INV_EN
 | |
|         iot_printf("%06d\n",*(p_addr+1));
 | |
|         iot_printf("%06d\n",*p_addr);
 | |
| #else
 | |
|         iot_printf("%06d\n",*p_addr);
 | |
|         iot_printf("%06d\n",*(p_addr+1));
 | |
| #endif
 | |
| #endif
 | |
|         check_bits = *p_addr ^ check_bits;
 | |
|         check_bits = *(p_addr+1) ^ check_bits;
 | |
|         p_addr += 2;
 | |
|     }
 | |
|     iot_printf("[end]\r\ncheck:%x\r\n the last:%x\r\n", \
 | |
|                 check_bits,*(int16_t *)(mem_buf + b_size*4));
 | |
| }
 | |
| 
 | |
| uint32_t ada_dump_with_csi()
 | |
| {
 | |
|     uint32_t tmp = 0;
 | |
|     uint32_t tone_idx = 0;
 | |
|     uint32_t fft_loop = 1;
 | |
|     int16_t csi_i = 0, csi_q = 0;
 | |
|     uint32_t *csi_buf = (uint32_t *)BB_CSI_BASEADDR;
 | |
| 
 | |
|     /* config det tone */
 | |
|     phy_rxfd_rate0_det(0, 1535);
 | |
|     phy_rxfd_rate1_det(0, 1535);
 | |
| 
 | |
|     /* tx att -6dB  */
 | |
|     phy_tx_gain_factor_set(26);
 | |
|     /* enable ana loopback */
 | |
|     phy_txrx_loop_back_begin(0,TXRX_LOOP_BACK_GRANITE);
 | |
| 
 | |
| #if ADA_DUMP_NF_WITH_CSI_BUF_DUMP == 1
 | |
|     /* gain max and disable loopback */
 | |
|     phy_ana_i2c_write(CFG_ANA_RX_REG_0_ADDR, \
 | |
|         24 << RX_SELC_OFFSET, \
 | |
|         RX_SELC_MASK);/* 12M */
 | |
|     /* en adc and rx, disable dac and tx */
 | |
|     phy_ana_i2c_write(CFG_ANA_TOP_REG_ADDR, \
 | |
|         (1 << TOP_EN_ADC_OFFSET) | \
 | |
|         (1 << TOP_ENLIC_OFFSET) | \
 | |
|         (1 << TOP_EN_RX_OFFSET), \
 | |
|         TOP_EN_DAC_MASK | \
 | |
|         TOP_EN_ADC_MASK | \
 | |
|         TOP_ENLIC_MASK | \
 | |
|         TOP_EN_TX_MASK | \
 | |
|         TOP_EN_RX_MASK);
 | |
|     /* fix geode rx */
 | |
|     phy_txrx_ovr_set(1,1);
 | |
|     phy_phase_ovr_set(PHY_PHASE_OVR_B,true,PHY_TXRX_OVR_RX);
 | |
| #endif
 | |
| 
 | |
|     /* 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);
 | |
| 
 | |
|     /* wait fft done */
 | |
|     do{
 | |
|         tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR);
 | |
|     }while(!REG_FIELD_GET(LOOP_FFT_DONE, tmp));
 | |
| 
 | |
|     /* enable sw csi buf access */
 | |
|     enable_sw_access_csi_buf(1);
 | |
| 
 | |
|     /* recover to the state set in ana loopback */
 | |
|     phy_txrx_loop_back_end();
 | |
| 
 | |
|     iot_printf("[dump]\r\n");
 | |
|     /* cal csi for every tone */
 | |
|     for(tone_idx = 0; tone_idx < 1536; tone_idx++)
 | |
|     {
 | |
|         csi_i = (int16_t)(*csi_buf & 0xFFFF);
 | |
|         csi_q = (int16_t)(*csi_buf >> 16);
 | |
|         iot_printf("%d,%d,%d\r\n", tone_idx, csi_i, csi_q);
 | |
|         csi_buf++;
 | |
|     }
 | |
| 
 | |
|     iot_printf("[end]\r\n");
 | |
|     /* enable sw csi buf access */
 | |
|     enable_sw_access_csi_buf(0);
 | |
| 
 | |
|     /* update the precise det range */
 | |
|     phy_rxfd_rate0_det(all_mask_band_table_r0_full.start_tone, \
 | |
|         all_mask_band_table_r0_full.end_tone);
 | |
|     phy_rxfd_rate1_det(all_mask_band_table_r1_full.start_tone, \
 | |
|         all_mask_band_table_r1_full.end_tone);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| /* ADA adc data dump */
 | |
| int phy_dump_from_ada( \
 | |
|     uint32_t b_size, \
 | |
|     uint32_t s_size, \
 | |
|     uint16_t tone_id, \
 | |
|     ADC_DUMP_MODE mode, \
 | |
|     PHY_PHASE_OVR_ID phase, \
 | |
|     uint32_t *trig_offset, \
 | |
|     uint8_t *adc_buf, \
 | |
|     uint32_t speed, \
 | |
|     phy_trig_dump_cond *trig_cond)
 | |
| 
 | |
| {
 | |
|     uint32_t ret = ERR_OK;
 | |
|     uint32_t *ram_ptr = NULL;
 | |
| 
 | |
|     /* ada soft reset */
 | |
|     warm_rst_ada();
 | |
| 
 | |
|     /* adc and dac init */
 | |
|     ada_common_init(tone_id, b_size, s_size);
 | |
| 
 | |
|     /* TODO: dtei stei and nid for kl2  */
 | |
|     if (trig_cond != NULL) {
 | |
|         if (trig_cond->thd != 0) {
 | |
|             /* ADC threshhold conf */
 | |
|             phy_adc_thrd_cfg(trig_cond->thd);
 | |
|         } else {
 | |
|             /* stei, dtei and nid */
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* force inte rx state */
 | |
|     phy_txrx_ovr_set(1,1);
 | |
| 
 | |
|     /* force rx phase */
 | |
|     phy_rx_phase_force_set(true, phase);
 | |
| 
 | |
| #if ADA_DUMP_WITH_CSI_BUF_DUMP == 1
 | |
|     ada_dump_with_csi();
 | |
| #endif
 | |
| 
 | |
|     /* not reset when drop */
 | |
|     phy_agc_drop_restart_dis_set(true);
 | |
| 
 | |
|     /* not reset when up */
 | |
|     phy_agc_ramup_restart_dis_set(true);
 | |
| 
 | |
|     /* full */
 | |
|     phy_agc_sat_rst_dis_set(1);
 | |
| 
 | |
|     /* jusge counter */
 | |
|     phy_agc_sat_jug_cnt_set(32);
 | |
| 
 | |
| #if EDA_SIMU_SUPPORT == 1
 | |
|     phy_busy_wait(ADC_DUMP_EDA_DLY_CYCLE);
 | |
|     (void)ram_ptr;
 | |
| #else
 | |
|     ram_ptr = (uint32_t *)adc_buf;
 | |
|     /* init default val */
 | |
|     uint32_t cnt = b_size;
 | |
|     do {
 | |
|         *ram_ptr++ = 0xffffffff;
 | |
|     } while(cnt--);
 | |
| #endif
 | |
| 
 | |
|     /* must flush ddr before dump */
 | |
|     if ((uint32_t)adc_buf == \
 | |
|         (ADC_DUMP_DDR_OFFSET + ADC_DUMP_DST_ADDR)) {
 | |
|         ahb_dmc_cache_rst_clear();
 | |
|         ahb_dmc_cache_clear();
 | |
|     }
 | |
| 
 | |
|     /* ada dump with max dly */
 | |
|     if (trig_cond != NULL) {
 | |
|         ret = phy_ada_dump_start(b_size, s_size, \
 | |
|            mode, ~0, trig_offset, trig_cond->trig_id, speed);
 | |
|     } else {
 | |
|         ret = phy_ada_dump_start(b_size, s_size, \
 | |
|             mode, ~0, trig_offset, 0, speed);
 | |
|     }
 | |
|     /* disable force phase */
 | |
|     phy_rx_phase_force_set(false, PLC_PHASE_ALL);
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /*
 | |
| *   csi dump to cal SNR/NF
 | |
| */
 | |
| float mac_rx_csi_dump(mac_csi_back_t *info, \
 | |
|         csi_est_dump_cond *cond, \
 | |
|         uint16_t p_num)
 | |
| {
 | |
|     uint8_t cur_nid = 0;
 | |
|     int16_t csi_i = 0, csi_q = 0;
 | |
|     uint16_t total_packets_num = 0, first_flag = 0;
 | |
|     uint16_t array_index = 0, cur_gain_entry = 0;
 | |
|     uint16_t array_index_i = 0, array_index_q = 0;
 | |
|     volatile bool_t trig_flag = false;
 | |
|     uint32_t tmp = 0, tmp_i = 0, data_interval = 10;
 | |
|     uint32_t start_time = 0, end_time = 0;
 | |
|     uint32_t start_pos = 0, end_pos = 0;
 | |
|     uint32_t pkt_rssi = 0, pkt_adc_pwr = 0, pkt_gain = 0;
 | |
|     uint32_t *csi_buf = (uint32_t *)BB_CSI_BASEADDR;
 | |
|     float amp_value = 0, amp_avg = 0, amp_vari = 0;
 | |
|     float pre_amp_avg = 0, post_amp_avg = 0;
 | |
|     uint64_t time_span = 0;
 | |
| 
 | |
|     /* clear shift */
 | |
|     phy_gain_shift_set(0,0,0,0);
 | |
| 
 | |
|     /* notch filter clear */
 | |
|     phy_anf_option_set(PHY_ANF_MODE_BYPASS,0,0,0);
 | |
| 
 | |
|     /* 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());
 | |
| 
 | |
|     /* disable intr */
 | |
|     PHY_WRITE_REG(CFG_BB_INT_CLR_0_ADDR, (PHY_RECV_FD_FC_OK | PHY_RECV_FD_FC_FAIL));
 | |
| 
 | |
|     total_packets_num = ((all_mask_band_table_r0_full.end_tone - \
 | |
|         all_mask_band_table_r0_full.start_tone + 1) << 2) \
 | |
|         / MAC_CSI_BACK_MAX_LEN;
 | |
|     if(total_packets_num) {
 | |
|         first_flag = 1;
 | |
|     }
 | |
| 
 | |
|     /* step1: polling rx_fd_fc_ok/fail
 | |
|        todo: add to interrupt handler */
 | |
|     if(p_num == first_flag) {
 | |
|         if((cond->trig_id & PHY_CSI_DUMP_TRIG_FC_OK) || \
 | |
|                 (cond->trig_id & PHY_CSI_DUMP_TRIG_FC_FAIL))
 | |
|         {
 | |
|             /*polling rx_fd_fc_ok*/
 | |
|             start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
 | |
|             while(!trig_flag)
 | |
|             {
 | |
|                 /* read reg */
 | |
|                 tmp = PHY_READ_REG(CFG_BB_INT_RAW_0_ADDR);
 | |
|                 if(cond->trig_id & PHY_CSI_DUMP_TRIG_FC_OK) {
 | |
|                     if(0 != (tmp & PHY_RECV_FD_FC_OK)) {
 | |
|                         uint32_t bb_fc[4];
 | |
|                         bb_fc[0] = PHY_READ_REG(CFG_BB_RX_FC_RAW_0_ADDR);
 | |
|                         bb_fc[1] = PHY_READ_REG(CFG_BB_RX_FC_RAW_1_ADDR);
 | |
|                         bb_fc[2] = PHY_READ_REG(CFG_BB_RX_FC_RAW_2_ADDR);
 | |
|                         bb_fc[3] = PHY_READ_REG(CFG_BB_RX_FC_RAW_3_ADDR);
 | |
|                         cur_nid = mac_get_nid_from_fc(PHY_PROTO_TYPE_GET(), bb_fc);
 | |
|                         iot_printf("Trigger done. glb_nid: %d, cur_nid: %d.\n", \
 | |
|                             cond->nid, cur_nid);
 | |
| 
 | |
|                         tmp_i = PHY_RXTD_READ_REG(CFG_BB_PACKET_INF_0_ADDR);
 | |
|                         pkt_adc_pwr = REG_FIELD_GET(FREE_RSSI, tmp_i);
 | |
|                         pkt_gain = REG_FIELD_GET(GAIN_TABLE_ENTRY, tmp_i);
 | |
|                         pkt_rssi = PHY_RSSI_FROM_RMI_GAIN(pkt_adc_pwr, pkt_gain);
 | |
|                         iot_printf("Trigger done. adc_pwr: %d, gain: %d, rssi: %d.\n", \
 | |
|                             pkt_adc_pwr, pkt_gain, pkt_rssi);
 | |
|                         if((cond->nid == cur_nid) \
 | |
|                            && (PHY_DUMP_PKT_RSSI_THD < pkt_rssi)) {
 | |
|                             trig_flag = 1;
 | |
|                         } else {
 | |
|                             trig_flag = 0;
 | |
|                         }
 | |
|                     }
 | |
|                 } else if(cond->trig_id & PHY_CSI_DUMP_TRIG_FC_FAIL) {
 | |
|                     trig_flag |= ((tmp & PHY_RECV_FD_FC_FAIL) != 0)?1:0;
 | |
|                 }
 | |
| 
 | |
|                 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;
 | |
|                 }
 | |
| 
 | |
|                 /* wait 1s */
 | |
|                 if((uint64_t)time_span > 1000 * TICKS_UNIT_MS){
 | |
|                     iot_printf("trig fail: wait more than 1s, check rx line!\n");
 | |
|                     return ERR_FAIL;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     tmp = PHY_RXTD_READ_REG(CFG_BB_PACKET_INF_0_ADDR);
 | |
|     cur_gain_entry = REG_FIELD_GET(GAIN_TABLE_ENTRY, tmp);
 | |
|     iot_printf("Current Gain Entry: %d\n", cur_gain_entry);
 | |
| 
 | |
|     /* enable csi buf dump */
 | |
|     enable_sw_access_csi_buf(true);
 | |
|     enable_sw_access_loopback(true);
 | |
| 
 | |
|     /* read data, to do with tone mask */
 | |
|     if(0 == p_num && 0 == total_packets_num) {
 | |
|         start_pos = all_mask_band_table_r0_full.start_tone;
 | |
|         end_pos = all_mask_band_table_r0_full.end_tone;
 | |
|     } else if(0 == p_num && 0 < total_packets_num) {
 | |
|         start_pos = all_mask_band_table_r0_full.start_tone + \
 | |
|             total_packets_num * (MAC_CSI_BACK_MAX_LEN >> 2);
 | |
|         end_pos = all_mask_band_table_r0_full.end_tone;
 | |
|     } else {
 | |
|         start_pos = all_mask_band_table_r0_full.start_tone + \
 | |
|             (p_num - 1) * (MAC_CSI_BACK_MAX_LEN >> 2);
 | |
|         end_pos = start_pos + (MAC_CSI_BACK_MAX_LEN >> 2) - 1;
 | |
|     }
 | |
| 
 | |
|     for(uint32_t i = start_pos; i <= end_pos; i++)
 | |
|     {
 | |
|         csi_i = (int16_t)(*(csi_buf + i) & 0xFFFF);
 | |
|         csi_q = (int16_t)(*(csi_buf + i) >> 16);
 | |
|         //iot_printf("%u,%d,%d\r\n", i, csi_i, csi_q);
 | |
| 
 | |
|         array_index_i = array_index << 1;
 | |
|         array_index_q = array_index_i + 1;
 | |
|         info->info_arry[array_index_i] = csi_i;
 | |
|         info->info_arry[array_index_q] = csi_q;
 | |
|         array_index += 1;
 | |
|     }
 | |
| 
 | |
|     if(end_pos == all_mask_band_table_r0_full.end_tone) {
 | |
|         /* get average */
 | |
|         for(uint32_t i = all_mask_band_table_r0_full.start_tone; \
 | |
|             i <= all_mask_band_table_r0_full.end_tone; i++)
 | |
|         {
 | |
|             csi_i = (int16_t)(*(csi_buf + i) & 0xFFFF);
 | |
|             csi_q = (int16_t)(*(csi_buf + i) >> 16);
 | |
|             amp_value = 10*mlog10(csi_i * csi_i + csi_q * csi_q + 1);
 | |
|             amp_avg += amp_value;
 | |
| 
 | |
|             if(0 == (i - all_mask_band_table_r0_full.start_tone) % data_interval) {
 | |
|                 iot_printf("data interval: %d, %u\r\n", i, (uint32_t)amp_value);
 | |
|             }
 | |
| 
 | |
|             if(i < all_mask_band_table_r0_full.start_tone + data_interval) {
 | |
|                 pre_amp_avg += amp_value;
 | |
|             }
 | |
| 
 | |
|             if(i > all_mask_band_table_r0_full.end_tone - data_interval) {
 | |
|                 post_amp_avg += amp_value;
 | |
|             }
 | |
|         }
 | |
|         amp_avg = amp_avg/all_mask_band_table_r0_full.valid_tone_number;
 | |
|         pre_amp_avg = pre_amp_avg/data_interval;
 | |
|         post_amp_avg = post_amp_avg/data_interval;
 | |
|         iot_printf("data interval %d, pre amp avg: %u, post amp avg: %u\r\n", \
 | |
|             data_interval, (uint32_t)pre_amp_avg, (uint32_t)post_amp_avg);
 | |
| 
 | |
|         info->info_arry[array_index_q + 1] = \
 | |
|             (int16_t)(all_mask_band_table_r0_full.start_tone);
 | |
|         info->info_arry[array_index_q + 2] = \
 | |
|             (int16_t)(all_mask_band_table_r0_full.end_tone);
 | |
|         info->info_arry[array_index_q + 3] = (uint16_t)cur_gain_entry;
 | |
| 
 | |
|         /* differentiate 700K and 2M spectrogram for band 32-120 */
 | |
|         info->info_arry[array_index_q + 4] = (int16_t)(post_amp_avg - pre_amp_avg);
 | |
| 
 | |
|         /* cal variance */
 | |
|         for(uint32_t i = all_mask_band_table_r0_full.start_tone; \
 | |
|             i <= all_mask_band_table_r0_full.end_tone; i++)
 | |
|         {
 | |
|             csi_i = (int16_t)(*(csi_buf + i) & 0xFFFF);
 | |
|             csi_q = (int16_t)(*(csi_buf + i) >> 16);
 | |
|             amp_vari += (10*mlog10(csi_i * csi_i + csi_q * csi_q + 1)-amp_avg) * \
 | |
|                 (10*mlog10(csi_i * csi_i + csi_q * csi_q + 1)-amp_avg);
 | |
|         }
 | |
| 
 | |
|         /* get average */
 | |
|         amp_vari = amp_vari/all_mask_band_table_r0_full.valid_tone_number;
 | |
|         iot_printf("average:%u,variance^2:%u\r\n", (uint32_t)amp_avg, (uint32_t)amp_vari);
 | |
| 
 | |
|     } else {
 | |
|         info->info_arry[array_index_q + 1] = 0;
 | |
|         info->info_arry[array_index_q + 2] = 0;
 | |
|         info->info_arry[array_index_q + 3] = (uint16_t)cur_gain_entry;
 | |
|         info->info_arry[array_index_q + 4] = p_num;
 | |
|     }
 | |
| 
 | |
|     info->len = (array_index << 2) + 8;
 | |
| 
 | |
|     /* default last packet number and single one packet number is 0 */
 | |
|     if(0 == p_num) {
 | |
|         /* disable csi buf dump */
 | |
|         enable_sw_access_csi_buf(false);
 | |
|         enable_sw_access_loopback(false);
 | |
|     }
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t phy_fft_flash_dump(uint32_t *buf_ptr)
 | |
| {
 | |
|     uint32_t ret = ERR_OK;
 | |
| #if HW_PLATFORM >= HW_PLATFORM_FPGA
 | |
|     uint32_t tmp = 0;
 | |
|     int8_t gain = 0;
 | |
|     uint32_t *csi_buf = (uint32_t *)BB_CSI_BASEADDR;
 | |
| 
 | |
|     /* get current gain */
 | |
|     gain = phy_gain_get_from_agc();
 | |
|     iot_printf("current gain: %u\n", gain);
 | |
|     *(buf_ptr + 1) = gain;
 | |
| 
 | |
|     /* fix gain and disable agc */
 | |
|     phy_agc_gain_lvl_set(1,gain,-24,0);
 | |
| 
 | |
|     /* enable phase A rx */
 | |
|     phy_rx_phase_force_set(true, PLC_PHASE_A);
 | |
| 
 | |
|     /* rst to trig enable after tone change */
 | |
|     phy_reset(PHY_RST_REASON_WARM);
 | |
| 
 | |
|     /* fft prepare */
 | |
|     phy_fft_dump_prepare();
 | |
| 
 | |
|     /* wait fft done */
 | |
|     do{
 | |
|         tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR);
 | |
|     }while(!REG_FIELD_GET(LOOP_FFT_DONE, tmp));
 | |
| 
 | |
|     /* enable sw csi buf access */
 | |
|     enable_sw_access_csi_buf(1);
 | |
| 
 | |
|     /* memcpy data from csi buf to buf */
 | |
|     for(uint32_t tone_idx = 2; tone_idx < TOTAL_TONE_MASK_NUM; tone_idx++)
 | |
|     {
 | |
|         *(buf_ptr + tone_idx) = *(csi_buf + tone_idx);
 | |
|     }
 | |
| 
 | |
|     /* enable sw csi buf access */
 | |
|     enable_sw_access_csi_buf(0);
 | |
| 
 | |
|     /* fft revert */
 | |
|     phy_fft_dump_recover();
 | |
| 
 | |
|     /* disable force phase */
 | |
|     phy_rx_phase_force_set(false, PLC_PHASE_ALL);
 | |
| #else
 | |
|     (void)buf_ptr;
 | |
| #endif
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| uint32_t phy_rx_scan_fft_dump(uint32_t *buf_ptr, int8_t rx_gain,\
 | |
|         uint16_t cur_pnum, uint16_t total_pnum)
 | |
| {
 | |
|     uint32_t ret = ERR_OK;
 | |
| #if HW_PLATFORM >= HW_PLATFORM_FPGA
 | |
|     uint32_t tmp = 0;
 | |
|     uint32_t *csi_buf = (uint32_t *)BB_CSI_BASEADDR;
 | |
| 
 | |
|     /* enable phase A rx */
 | |
|     phy_rx_phase_force_set(true, PLC_PHASE_A);
 | |
| 
 | |
|     /* rst to trig enable after tone change */
 | |
|     phy_reset(PHY_RST_REASON_WARM);
 | |
| 
 | |
|     /* enable first packet */
 | |
|     if(cur_pnum < 2) {
 | |
|         /* fix gain and disable agc */
 | |
|         if(rx_gain >= -24 && rx_gain <= 60) {
 | |
|             phy_agc_gain_lvl_set(1,rx_gain,-24,0);
 | |
|         } else {
 | |
|             iot_printf("rx_gain out of range, it should be at [-24, +60]!\n");
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
|         /* fft dump prepare */
 | |
|         phy_fft_dump_prepare();
 | |
| 
 | |
|         /* wait fft done */
 | |
|         do{
 | |
|             tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR);
 | |
|         }while(!REG_FIELD_GET(LOOP_FFT_DONE, tmp));
 | |
| 
 | |
|         /* enable sw csi buf access */
 | |
|         enable_sw_access_csi_buf(1);
 | |
|     }
 | |
| 
 | |
|     csi_buf += (cur_pnum - 1) * IOT_PHY_FFT_BUF_LEN / 4;
 | |
|     /* memcpy data from csi buf to buf */
 | |
|     os_mem_cpy(buf_ptr, csi_buf, IOT_PHY_FFT_BUF_LEN);
 | |
| 
 | |
|     if(cur_pnum == total_pnum) {
 | |
|         /* enable sw csi buf access */
 | |
|         enable_sw_access_csi_buf(0);
 | |
| 
 | |
|         /* fft dump revert */
 | |
|         phy_fft_dump_recover();
 | |
|     }
 | |
| 
 | |
|     /* disable force */
 | |
|     phy_rx_phase_force_set(false, PLC_PHASE_ALL);
 | |
| #else
 | |
|     (void)buf_ptr;
 | |
|     (void)rx_gain;
 | |
|     (void)cur_pnum;
 | |
|     (void)total_pnum;
 | |
| #endif
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| void phy_auto_tone_tx(timer_id_t timer_id, void *arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     phy_ctxt_t *phy_ctxt_ptr = arg;
 | |
| 
 | |
|     if (phy_ctxt_ptr->indep.tx_tone.curent_tone < \
 | |
|         phy_ctxt_ptr->indep.tx_tone.end_tone) {
 | |
|         /* config tone */
 | |
|         phy_dfe_tone_cfg(1, \
 | |
|             phy_ctxt_ptr->indep.tx_tone.curent_tone, 0);
 | |
|         phy_ctxt_ptr->indep.tx_tone.curent_tone++;
 | |
|         iot_printf("%s tone_id %d\r\n",__FUNCTION__,\
 | |
|             phy_ctxt_ptr->indep.tx_tone.curent_tone);
 | |
|     } else {
 | |
|         phy_ctxt_ptr->indep.tx_tone.curent_tone = \
 | |
|             phy_ctxt_ptr->indep.tx_tone.start_tone;
 | |
|         /* disable tone tx */
 | |
|         phy_dfe_tone_cfg(0, 0, 0);
 | |
| 
 | |
|         os_stop_timer(phy_ctxt_ptr->indep.tx_tone.auto_tone_timer);
 | |
|         /*after finish tone tx,rest 10000ms */
 | |
|         os_start_timer(phy_ctxt_ptr->indep.tx_tone.rest_tone_timer,PHY_TX_TONE_REST_TIME);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void phy_star_tone_tx_timer(timer_id_t timer_id, void *arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     phy_ctxt_t *phy_ctxt_ptr = arg;
 | |
| 
 | |
|     os_stop_timer(phy_ctxt_ptr->indep.tx_tone.rest_tone_timer);
 | |
|     /* start timer */
 | |
|     os_start_timer(phy_ctxt_ptr->indep.tx_tone.auto_tone_timer, \
 | |
|         phy_ctxt_ptr->indep.tx_tone.tx_intval_time_ms);
 | |
| }
 | |
| 
 | |
| void phy_auto_tone_tx_start(iot_phy_tone_param_ctxt_t *tx_tone_ptr)
 | |
| {
 | |
| #if HW_PLATFORM >= HW_PLATFORM_FPGA
 | |
|     uint16_t start_tone = 0,end_tone = 0,tx_inval_time = 0;
 | |
| 
 | |
|     phy_load_ada_scan_cfg(&start_tone, &end_tone, &tx_inval_time);
 | |
|     if((0 == start_tone) || (0 == end_tone) || (0 == tx_inval_time)){
 | |
|          start_tone = 32;
 | |
|          end_tone = 120;
 | |
|          tx_inval_time = 400;
 | |
|     }
 | |
|     iot_printf("%s,start %d,end %d ,inter %d\r\n",__FUNCTION__,\
 | |
|         start_tone,end_tone,tx_inval_time);
 | |
| 
 | |
|     /* update tone id */
 | |
|     tx_tone_ptr->start_tone = start_tone / 3;
 | |
|     tx_tone_ptr->end_tone = end_tone / 3;
 | |
|     tx_tone_ptr->curent_tone = start_tone / 3;
 | |
|     tx_tone_ptr->rty_cnt = 1;
 | |
|     tx_tone_ptr->tx_intval_time_ms = tx_inval_time;
 | |
|     tx_tone_ptr->auto_tone_timer = \
 | |
|     os_create_timer( \
 | |
|         PLC_PHY_COMMON_MID, true, phy_auto_tone_tx, &g_phy_ctxt);
 | |
|     if(tx_tone_ptr->auto_tone_timer == 0){
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     tx_tone_ptr->rest_tone_timer = \
 | |
|     os_create_timer( \
 | |
|         PLC_PHY_COMMON_MID, true, phy_star_tone_tx_timer, &g_phy_ctxt);
 | |
|     if(tx_tone_ptr->rest_tone_timer == 0){
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* force phy in tx state */
 | |
|     phy_txrx_ovr_set(true, 2);
 | |
| 
 | |
|     /* en analog tx */
 | |
|     phy_ana_tx_en(true);
 | |
|     phy_ana_rx_en(false);
 | |
|     phy_ana_enlic_en(PHY_ENLIC_TXRX_TX);
 | |
| 
 | |
|     /* att */
 | |
|     phy_dfe_tone_att_cfg(0, 3, 0);
 | |
| 
 | |
|     os_start_timer(tx_tone_ptr->auto_tone_timer, \
 | |
|         tx_tone_ptr->tx_intval_time_ms);
 | |
| #endif
 | |
| }
 |