315 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			315 lines
		
	
	
		
			10 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 "os_types.h"
 | |
| #include "chip_reg_base.h"
 | |
| #include "hw_reg_api.h"
 | |
| #include "phy_rxtd_reg.h"
 | |
| #include "mac_sys_reg.h"
 | |
| #include "phy_dfe_reg.h"
 | |
| #include "cpu1_fix.h"
 | |
| #include "phy_bb.h"
 | |
| #include "iot_system.h"
 | |
| #include "iot_config.h"
 | |
| #include "phy_chn.h"
 | |
| 
 | |
| /* AGC FSM */
 | |
| typedef enum{
 | |
|     RSSI_L        = 0,
 | |
|     RSSI_H      = 1,
 | |
|     PACKET      = 2,
 | |
|     LOCK        = 3,
 | |
| }AGC_STATE;
 | |
| 
 | |
| /* RX TD FSM */
 | |
| typedef enum{
 | |
|     RX_TD_IDLE              = 0,
 | |
|     RX_TD_WAIT_AGC          = 1,
 | |
|     RX_TD_WAIT_SELF_CORR    = 2,
 | |
|     RX_TD_AGC_LOCK          = 3,
 | |
| }RX_TD_FSM;
 | |
| 
 | |
| extern cpu_state g_cpu1_state;
 | |
| 
 | |
| /* 0.040us units for each tick */
 | |
| void delay_td_point(uint32_t point)
 | |
| {
 | |
|     uint64_t time_span = 0;
 | |
|     uint32_t start_time = 0, end_time = 0;
 | |
|     uint64_t dly_us = point/3;/* us=point/75*25 */
 | |
| 
 | |
|     start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
 | |
|     do{
 | |
|         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;
 | |
|         }
 | |
|     }while(time_span < dly_us);
 | |
| }
 | |
| 
 | |
| void set_next_gain(uint8_t exp_gain_entry)
 | |
| {
 | |
|     uint32_t tmp = 0;
 | |
|     int8_t exp_gain_int = 0;
 | |
| 
 | |
|     exp_gain_int = (int8_t)exp_gain_entry - 24;
 | |
|     /* force the exp_gain */
 | |
|     tmp = PHY_RXTD_READ_REG(CFG_BB_AGC_GAIN_LEVEL_ADDR);
 | |
|     REG_FIELD_SET(SW_MAX_GAIN, tmp, exp_gain_int );
 | |
|     REG_FIELD_SET(SW_FIX_GAIN_EN, tmp, 1 );
 | |
|     PHY_RXTD_WRITE_REG(CFG_BB_AGC_GAIN_LEVEL_ADDR, tmp);
 | |
| 
 | |
|     /* force rx_abort to reset phy */
 | |
|     tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_0_ADDR);
 | |
|     REG_FIELD_SET(CFG_PHY_RX_ABORT_FORCE_EN, tmp, 1);
 | |
|     REG_FIELD_SET(CFG_PHY_RX_ABORT, tmp, 1);
 | |
|     RGF_MAC_WRITE_REG(CFG_PHY_FORCE_0_ADDR, tmp);
 | |
| 
 | |
|     REG_FIELD_SET(CFG_PHY_RX_ABORT_FORCE_EN, tmp, 0);
 | |
|     REG_FIELD_SET(CFG_PHY_RX_ABORT, tmp, 0);
 | |
|     RGF_MAC_WRITE_REG(CFG_PHY_FORCE_0_ADDR, tmp);
 | |
| 
 | |
|     /* delay 5us to let gain work */
 | |
|     delay_td_point(400);
 | |
| }
 | |
| 
 | |
| uint8_t phy_rxtd_rssi_get()
 | |
| {
 | |
|     uint32_t tmp = PHY_RXTD_READ_REG(CFG_BB_PACKET_INF_0_ADDR);
 | |
|     return REG_FIELD_GET(FREE_RSSI, tmp);
 | |
| }
 | |
| 
 | |
| uint8_t cpu1_get_nf_by_phase()
 | |
| {
 | |
|     uint8_t nf_phase;
 | |
|     if (g_phy_cpu_share_ctxt.cal_3phase_nf_init) {
 | |
|         uint32_t tmp = RGF_MAC_READ_REG(CFG_RD_MACPHY_INTF_0_ADDR);
 | |
|         uint8_t cur_phase = REG_FIELD_GET(PHY_RX_PHASE_SEL, tmp);
 | |
|         nf_phase = g_phy_cpu_share_ctxt.nf_phase[cur_phase];
 | |
|     } else {
 | |
|         nf_phase = g_phy_cpu_share_ctxt.nf_192p;
 | |
|     }
 | |
|     return nf_phase;
 | |
| }
 | |
| 
 | |
| void cpu1_fix()
 | |
| {
 | |
|     uint32_t tmp = 0;
 | |
|     uint8_t cur_adc_pwr = 0, adc_pwr_th1, adc_pwr_th2;
 | |
|     uint8_t cur_gain_entry = 0;
 | |
|     uint8_t exp_gain_entry = 0;
 | |
|     uint8_t cur_rssi = 120;
 | |
|     uint8_t td_fsm = 0;  //0:idle, 1:AGC, 2:CORR, 3:PACKET
 | |
|     uint8_t rssi_high_cnt = 0;
 | |
|     uint8_t rssi_low_cnt = 0;
 | |
|     uint8_t current_nf = 0;
 | |
|     volatile bool_t shift_en = false;
 | |
|     volatile bool_t shift_flag = false;
 | |
|     uint32_t tmp_spare2 = 0;
 | |
| 
 | |
| #if PHY_CHIP_CERT_EN == 0
 | |
|     uint8_t  no_shift_cnt =0 ;
 | |
|     uint8_t  shift1_cnt =0 ;
 | |
|     uint16_t lock_cnt =0 ;
 | |
|     bool_t  shift1_en = 0;
 | |
| #endif
 | |
| 
 | |
| #if PHY_CPU1_DBG_EN
 | |
|     volatile uint32_t *shift_cnt = \
 | |
|         (uint32_t *)(PHY_RXTD_BASEADDR + CFG_BB_RXTD_SPARE3_ADDR);
 | |
|     volatile uint32_t *dbg_sts = \
 | |
|         (uint32_t *)(PHY_RXTD_BASEADDR + CFG_BB_RXTD_SPARE1_ADDR);
 | |
| #endif
 | |
| 
 | |
|     while(1)
 | |
|     {
 | |
|         tmp_spare2 = PHY_RXTD_READ_REG(CFG_BB_RXTD_SPARE2_ADDR);
 | |
|         /* check magic number */
 | |
|         if (tmp_spare2 != 0x5A5A5A5A) {
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         if (g_phy_cpu_share_ctxt.high_perf_en) {
 | |
|             delay_td_point(150);
 | |
|         } else {
 | |
|             delay_td_point(1500);
 | |
|         }
 | |
|         /* get td fsm value */
 | |
|         tmp = PHY_RXTD_READ_REG(CFG_RX_TD_FSM_DBG_BUS_ADDR);
 | |
|         td_fsm = (uint8_t)(tmp & 0xf);
 | |
| 
 | |
|         if (g_phy_cpu_share_ctxt.high_perf_en) {
 | |
|             if(td_fsm == RX_TD_WAIT_SELF_CORR) { //if not find packet
 | |
|                 /* get current nf (updated per 1s) */
 | |
|                 current_nf = cpu1_get_nf_by_phase();
 | |
|                 /*target power is 110*/
 | |
|                 if (g_phy_cpu_share_ctxt.spur_exist) {
 | |
|                     exp_gain_entry = 114 + 24 - current_nf;
 | |
|                 } else {
 | |
|                     exp_gain_entry = 110 + 24 - current_nf;
 | |
|                 }
 | |
| 
 | |
|                 if (exp_gain_entry > 84) {
 | |
|                     exp_gain_entry = 84;
 | |
|                 }
 | |
| 
 | |
| #if PHY_CPU1_DBG_EN
 | |
|                 *shift_cnt = (*shift_cnt & 0xFFFFFF00) + \
 | |
|                     (uint32_t)exp_gain_entry + 0x100;
 | |
| #endif
 | |
| 
 | |
|                 /*
 | |
|                  *  Maybe changed by reg write but nf always the same.
 | |
|                  *  need read the current reg value.
 | |
|                  */
 | |
|                 tmp = PHY_RXTD_READ_REG(CFG_BB_AGC_GAIN_LEVEL_ADDR);
 | |
|                 cur_gain_entry = REG_FIELD_GET(SW_MAX_GAIN, tmp) + 24;
 | |
| 
 | |
|                 /*adjust gain*/
 | |
|                 if (cur_gain_entry != exp_gain_entry) {
 | |
|                     set_next_gain(exp_gain_entry);
 | |
| 
 | |
| #if PHY_CHIP_CERT_EN == 0
 | |
|                     no_shift_cnt = 0;
 | |
|                     shift1_cnt = 0;
 | |
|                     shift1_en = 0;
 | |
|                     lock_cnt = 0;
 | |
| #endif
 | |
|                 }
 | |
| #if PHY_CHIP_CERT_EN == 0
 | |
|                 /*if no big spur, do shift*/
 | |
|                 if (!g_phy_cpu_share_ctxt.spur_exist) {
 | |
|                     /*push the cur_adc_pwr in*/
 | |
|                     cur_adc_pwr = phy_rxtd_rssi_get();
 | |
|                     /* if adc power > 100, can not shift */
 | |
|                     adc_pwr_th1 = 100;
 | |
|                     adc_pwr_th2 = 92;
 | |
| 
 | |
|                     /* decide shift */
 | |
|                     if (cur_adc_pwr > adc_pwr_th1) {
 | |
|                         no_shift_cnt = (no_shift_cnt == 8) ? 8 : no_shift_cnt + 1;
 | |
|                         //shift1_cnt = 0 ;
 | |
|                     } else if(cur_adc_pwr > adc_pwr_th2) {
 | |
|                         shift1_cnt = (shift1_cnt == 8) ? 8 : shift1_cnt + 1;
 | |
|                         no_shift_cnt = 0;
 | |
|                     } else {
 | |
|                         no_shift_cnt = 0;
 | |
|                         shift1_cnt   = 0;
 | |
|                     }
 | |
| 
 | |
|                     if (shift1_en == 1 && no_shift_cnt == 8) {
 | |
|                         lock_cnt = 0;
 | |
|                     }
 | |
| 
 | |
|                     if (lock_cnt == 0) {
 | |
|                         if (no_shift_cnt == 8) {
 | |
|                             phy_gain_shift_set(0,0,0,0);
 | |
|                             lock_cnt++;
 | |
|                             shift1_en = 0;
 | |
|                         } else if (shift1_cnt == 8) {
 | |
|                             phy_gain_shift_set(0,0,
 | |
|                                 g_phy_cpu_share_ctxt.shift_low > 0,
 | |
|                                 g_phy_cpu_share_ctxt.shift_low);
 | |
|                             lock_cnt++;
 | |
|                             shift1_en = 1;
 | |
|                         } else if (no_shift_cnt == 0 && shift1_cnt == 0) {
 | |
|                             phy_gain_shift_set(0,0,
 | |
|                                 g_phy_cpu_share_ctxt.shift_high > 0,
 | |
|                                 g_phy_cpu_share_ctxt.shift_high);
 | |
|                             shift1_en = 0;
 | |
|                         }
 | |
|                     } else if (lock_cnt >= 1000) {   //>2ms for preamble dectection
 | |
|                         lock_cnt = 0;
 | |
|                     } else {
 | |
|                         lock_cnt++ ;
 | |
|                     }
 | |
|                 } else {
 | |
|                     phy_gain_shift_set(0,0,0,0);
 | |
|                 }
 | |
| #else
 | |
|                 phy_gain_shift_set(0,0,0,0);
 | |
| #endif
 | |
|             }
 | |
| #if PHY_CHIP_CERT_EN == 0
 | |
|             else {
 | |
|                 no_shift_cnt = 0;
 | |
|                 shift1_cnt = 0 ;
 | |
|                 lock_cnt = 0;
 | |
|                 shift1_en = 0;
 | |
|             }
 | |
| #endif
 | |
|         }
 | |
|         /* if not high_perf_en*/
 | |
|         /* check if not idle */
 | |
|         else if (td_fsm != 0) {
 | |
|             /* get current gain and adc power */
 | |
|             tmp = PHY_RXTD_READ_REG(CFG_BB_PACKET_INF_0_ADDR);
 | |
|             cur_adc_pwr = REG_FIELD_GET(FREE_RSSI, tmp);
 | |
|             cur_gain_entry = REG_FIELD_GET(GAIN_TABLE_ENTRY, tmp);
 | |
| 
 | |
|             if (td_fsm == RX_TD_WAIT_SELF_CORR && cur_adc_pwr != 0) {
 | |
|                 cur_rssi = PHY_RSSI_FROM_RMI_GAIN(cur_adc_pwr, cur_gain_entry);
 | |
| 
 | |
|                 /* high/low rssi dection */
 | |
|                 if (cur_rssi <= (current_nf + PHY_SPIKE_RSSI_NF_THD)) {
 | |
|                     rssi_high_cnt = 0;
 | |
|                     if (rssi_low_cnt < PHY_SPIKE_RSSI_LOW_CNT) {
 | |
|                         rssi_low_cnt++;
 | |
|                     }
 | |
|                 } else if (rssi_high_cnt < PHY_SPIKE_RSSI_HIGH_CNT) {
 | |
|                     rssi_high_cnt++;
 | |
|                     if (rssi_low_cnt > 0) {
 | |
|                         rssi_low_cnt--;
 | |
|                     }
 | |
|                 } else if (rssi_low_cnt > 0) {
 | |
|                     rssi_low_cnt--;
 | |
|                 }
 | |
| 
 | |
| #if PHY_CPU1_DBG_EN
 | |
|                 /* rssi low cnt*/
 | |
|                 *dbg_sts = rssi_low_cnt | \
 | |
|                     (cur_rssi << 8) | \
 | |
|                     (g_phy_cpu_share_ctxt.nf_192p << 16) | \
 | |
|                     (g_phy_cpu_share_ctxt.nf_384p << 24);
 | |
| 
 | |
|                 *shift_cnt = g_phy_cpu_share_ctxt.nf_768p | \
 | |
|                     (g_phy_cpu_share_ctxt.nf_1536p << 8) | \
 | |
|                     (g_phy_cpu_share_ctxt.nf_3072p << 16) | \
 | |
|                     (g_phy_cpu_share_ctxt.nf_6144p << 24);
 | |
| #endif
 | |
| 
 | |
|                 /* spike find */
 | |
|                 if (rssi_high_cnt == PHY_SPIKE_RSSI_HIGH_CNT || \
 | |
|                     cur_adc_pwr > PHY_PWR_SHIFT_FULL_LVL) {
 | |
|                     shift_en = false;
 | |
|                 } else if (rssi_low_cnt > 0) {
 | |
|                     /* rssi low */
 | |
|                     shift_en = true;
 | |
|                 }
 | |
| 
 | |
|                 /* check if shift */
 | |
|                 if (shift_en && !shift_flag) {
 | |
|                     phy_gain_shift_set(0,0,1,2);
 | |
|                     shift_flag = true;
 | |
|                 } else if (!shift_en && shift_flag) {
 | |
|                     phy_gain_shift_set(0,0,0,0);
 | |
|                     shift_flag = false;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         g_cpu1_state.count++;
 | |
|     }
 | |
| }
 |