/**************************************************************************** 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++; } }