diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 48e67e0662..7a270e5e96 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1355,6 +1355,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c + ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ue_measurements.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c new file mode 100644 index 0000000000..c74a794735 --- /dev/null +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -0,0 +1,140 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "PHY/types.h" +#include "PHY/defs_nr_UE.h" +#include "PHY/NR_UE_ESTIMATION/nr_estimation.h" +#include "PHY/impl_defs_top.h" +//#include "openair2/LAYER2/MAC/mac_proto.h" + +#include "common/utils/LOG/vcd_signal_dumper.h" + +#define DEBUG_PHY + +// Adjust location synchronization point to account for drift +// The adjustment is performed once per frame based on the +// last channel estimate of the receiver + +void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, + PHY_VARS_NR_UE *ue, + module_id_t eNB_id, + uint8_t subframe, + unsigned char clear, + short coef) +{ + + static int max_pos_fil = 0; + static int count_max_pos_ok = 0; + static int first_time = 1; + int temp = 0, i, aa, max_val = 0, max_pos = 0; + int diff; + short Re,Im,ncoef; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); + + ncoef = 32767 - coef; + +//#ifdef DEBUG_PHY + LOG_D(PHY,"AbsSubframe %d.%d: rx_offset (before) = %d\n",ue->proc.proc_rxtx[0].frame_rx%1024,subframe,ue->rx_offset); +//#endif //DEBUG_PHY + + + // we only use channel estimates from tx antenna 0 here + for (i = 0; i < frame_parms->nb_prefix_samples; i++) { + temp = 0; + + for (aa=0; aanb_antennas_rx; aa++) { + Re = ((int16_t*)ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id][aa])[(i<<1)]; + Im = ((int16_t*)ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id][aa])[1+(i<<1)]; + temp += (Re*Re/2) + (Im*Im/2); + } + + if (temp > max_val) { + max_pos = i; + max_val = temp; + } + } + + // filter position to reduce jitter + if (clear == 1) + max_pos_fil = max_pos; + else + max_pos_fil = ((max_pos_fil * coef) + (max_pos * ncoef)) >> 15; + + // do not filter to have proactive timing adjustment + max_pos_fil = max_pos; + + if(subframe == 1) + { + diff = max_pos_fil - (frame_parms->nb_prefix_samples>>3); + + if ( abs(diff) < SYNCH_HYST ) + ue->rx_offset = 0; + else + ue->rx_offset = diff; + + if(abs(diff)<5) + count_max_pos_ok ++; + else + count_max_pos_ok = 0; + + printf("adjust sync count_max_pos_ok = %d\n",count_max_pos_ok); + + if(count_max_pos_ok > 10 && first_time == 1) + { + first_time = 0; + ue->time_sync_cell = 1; + if (ue->mac_enabled==1) { + LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); + //mac_resynch(); + //dl_phy_sync_success(ue->Mod_id,ue->proc.proc_rxtx[0].frame_rx,0,1);//ue->common_vars.eNb_id); + ue->UE_mode[0] = PRACH; + } + else { + ue->UE_mode[0] = PUSCH; + } + } + + if ( ue->rx_offset < 0 ) + ue->rx_offset += FRAME_LENGTH_COMPLEX_SAMPLES; + + if ( ue->rx_offset >= FRAME_LENGTH_COMPLEX_SAMPLES ) + ue->rx_offset -= FRAME_LENGTH_COMPLEX_SAMPLES; + + + + #ifdef DEBUG_PHY + LOG_I(PHY,"AbsSubframe %d.%d: ThreadId %d diff =%i rx_offset (final) = %i : clear %d,max_pos = %d,max_pos_fil = %d (peak %d) max_val %d target_pos %d \n", + ue->proc.proc_rxtx[ue->current_thread_id[subframe]].frame_rx, + subframe, + ue->current_thread_id[subframe], + diff, + ue->rx_offset, + clear, + max_pos, + max_pos_fil, + temp,max_val, + (frame_parms->nb_prefix_samples>>3)); + #endif //DEBUG_PHY + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); + } +} diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index ac60cef628..7629f0e4f6 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -262,7 +262,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short nb_rb_coreset) { int pilot[200] __attribute__((aligned(16))); - unsigned char aarx; + unsigned char aarx,p; unsigned short k; unsigned int pilot_cnt; int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*fr; @@ -424,6 +424,52 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, } } + + void (*idft)(int16_t *,int16_t *, int); + + switch (ue->frame_parms.ofdm_symbol_size) { + case 128: + idft = idft128; + break; + + case 256: + idft = idft256; + break; + + case 512: + idft = idft512; + break; + + case 1024: + idft = idft1024; + break; + + case 1536: + idft = idft1536; + break; + + case 2048: + idft = idft2048; + break; + + default: + idft = idft512; + break; + } + + if( ((Ns%2) == 0) && (l == 0)) + { + // do ifft of channel estimate + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) + for (p=0; pframe_parms.nb_antenna_ports_eNB; p++) { + if (ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates[eNB_offset][(p<<1)+aarx]) + { + //LOG_I(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d \n", Ns, ue->current_thread_id[Ns>>1], l); + idft((int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates[eNB_offset][(p<<1)+aarx][0], + (int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1); + } + } + } return(0); } @@ -465,7 +511,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, int re_offset = k; //#ifdef DEBUG_CH - printf("PDSCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns>>1], eNB_offset,ch_offset,symbol_offset,ue->frame_parms.ofdm_symbol_size, + printf("PDSCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,symbol_offset,ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp,l,Ns,k, symbol); //#endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index aaaf63e753..ae4295a99b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -67,4 +67,12 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned char symbol, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch); + +void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, + PHY_VARS_NR_UE *ue, + module_id_t eNB_id, + uint8_t subframe, + unsigned char clear, + short coef); + #endif diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 7f443cdb17..75eff8b907 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -46,6 +46,7 @@ #include "SCHED_NR/extern.h" //#include //#include "targets/RT/USER/nr-softmodem.h" +#include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #ifdef EMOS #include "SCHED/phy_procedures_emos.h" @@ -2643,19 +2644,25 @@ void phy_procedures_UE_S_TX(PHY_VARS_NR_UE *ue,uint8_t eNB_id,uint8_t abstractio } } -void ue_measurement_procedures( +#endif + +void nr_ue_measurement_procedures( uint16_t l, // symbol index of each slot [0..6] - PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc, uint8_t eNB_id, + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint8_t eNB_id, uint16_t slot, // slot index of each radio frame [0..19] - uint8_t abstraction_flag,runmode_t mode) + uint8_t abstraction_flag, + runmode_t mode) { - //LOG_I(PHY,"ue_measurement_procedures l %d Ncp %d\n",l,ue->frame_parms.Ncp); + LOG_I(PHY,"ue_measurement_procedures l %u Ncp %d\n",l,ue->frame_parms.Ncp); NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int nr_tti_rx = proc->nr_tti_rx; +#if 0 VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN); if (l==0) { @@ -2705,12 +2712,12 @@ void ue_measurement_procedures( ue->sinr_eff = sinr_eff_cqi_calc(ue, 0, nr_tti_rx); } - +#endif // accumulate and filter timing offset estimation every nr_tti_rx (instead of every frame) if (( (slot%2) == 0) && (l==(4-frame_parms->Ncp))) { // AGC - +/* VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_IN); #ifndef OAI_USRP @@ -2724,12 +2731,14 @@ void ue_measurement_procedures( #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); - +*/ eNB_id = 0; if (abstraction_flag == 0) { + + printf("start adjust sync l = %d slot = %d no timing %d\n",l, slot, ue->no_timing_correction); if (ue->no_timing_correction==0) - lte_adjust_synch(&ue->frame_parms, + nr_adjust_synch_ue(&ue->frame_parms, ue, eNB_id, nr_tti_rx, @@ -2742,6 +2751,7 @@ void ue_measurement_procedures( VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT); } + #ifdef EMOS void phy_procedures_emos_UE_RX(PHY_VARS_NR_UE *ue,uint8_t last_slot,uint8_t eNB_id) { @@ -2830,7 +2840,7 @@ void phy_procedures_emos_UE_RX(PHY_VARS_NR_UE *ue,uint8_t last_slot,uint8_t eNB_ } #endif - +#if 0 void restart_phy(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t abstraction_flag) { @@ -5475,6 +5485,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN int nr_tti_rx = proc->nr_tti_rx; proc->decoder_switch = 0; //int counter_decoder = 0; + + LOG_I(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); @@ -5557,8 +5569,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN #endif //nr_gold_pdcch(ue,0, 2); - if (nr_tti_rx==2) - for (int l=0; l<2; l++) { + if (nr_tti_rx==1){ + for (uint16_t l=0; l<2; l++) { if (abstraction_flag == 0) { #if UE_TIMING_TRACE start_meas(&ue->ofdm_demod_stats); @@ -5567,7 +5579,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); nr_slot_fep(ue, l, - nr_tti_rx, + nr_tti_rx<<1, 0, 0, 1, @@ -5576,8 +5588,12 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN #if UE_TIMING_TRACE stop_meas(&ue->ofdm_demod_stats); #endif + printf("phy procedure pdcch start measurement l =%d\n",l); + nr_ue_measurement_procedures(l,ue,proc,eNB_id,(nr_tti_rx<<1),abstraction_flag,mode); } + } + } //write_output("rxdataF.m","rxF",ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx>>1]].rxdataF[0],ue->frame_parms.ofdm_symbol_size*2,1,1); @@ -5654,18 +5670,23 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN //#if 0 LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - if (nr_tti_rx==2){ + if (nr_tti_rx==1){ //to update from pdsch config nr_gold_pdsch(ue,2,0, 1); - for (int m=2;m<6 ; m++) + for (uint16_t m=2;m<6 ; m++){ nr_slot_fep(ue, m, //to be updated from higher layer - nr_tti_rx, + nr_tti_rx<<1, 0, 0, 1, NR_PDSCH_EST); + + printf("phy procedure pdsch start measurement\n"); + nr_ue_measurement_procedures(m,ue,proc,eNB_id,(nr_tti_rx<<1),abstraction_flag,mode); + + } //set active for testing, to be removed ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 1; } diff --git a/targets/RT/USER/nr-ru.c b/targets/RT/USER/nr-ru.c index 31698232b4..1147420988 100644 --- a/targets/RT/USER/nr-ru.c +++ b/targets/RT/USER/nr-ru.c @@ -2443,9 +2443,11 @@ void RCconfig_RU(void) { RC.ru[j]->num_gNB = 0; for (i=0;inum_gNB;i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0]; +#ifndef OAI_ADRV9371_ZC706 if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); } +#endif if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) {