diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index e05045d3ed..34ea60f02c 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -535,6 +535,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { RC.gNB[Mod_id]->configured = 1; init_symbol_rotation(fp); + init_timeshift_rotation(fp); LOG_I(PHY,"gNB %d configured\n",Mod_id); } diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index e32f6bf575..efa18db2a3 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -745,6 +745,75 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { } } +void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) +{ + const double fd = 15e3*(float)(1<numerology_index); + const double Tc=(1/480e3/4096); + const double Nu=2048*64*(1/(float)(1<numerology_index)); + const double Ncp0=16*64 + (144*64*(1/(float)(1<numerology_index))); + const double Ncp1=(144*64*(1/(float)(1<numerology_index))); + double t0; + double poff; + double exp_re; + double exp_im; + double f; + int16_t *timeshift_symbol_rotation; + int i; + + for (i = 0; i < fp->ofdm_symbol_size/2; i++) { + timeshift_symbol_rotation = fp->timeshift_symbol_rotation[0]; + f = fd * i; + t0 = Ncp0 / 8; + poff = 2 * M_PI * -t0 * Tc * f; + exp_re = cos(poff); + exp_im = sin(-poff); + timeshift_symbol_rotation[i*2] = (int16_t)floor(exp_re * 32767); + timeshift_symbol_rotation[i*2+1] = (int16_t)floor(exp_im * 32767); + + timeshift_symbol_rotation = fp->timeshift_symbol_rotation[1]; + t0 = Ncp1 / 8; + poff = 2 * M_PI * -t0 * Tc * f; + exp_re = cos(poff); + exp_im = sin(-poff); + timeshift_symbol_rotation[i*2] = (int16_t)floor(exp_re * 32767); + timeshift_symbol_rotation[i*2+1] = (int16_t)floor(exp_im * 32767); + + if (i < 10) + LOG_I(PHY,"Timeshift symbol rotation %d => (%d,%d) %f\n",i, + fp->timeshift_symbol_rotation[1][i*2], + fp->timeshift_symbol_rotation[1][i*2+1], + poff); + + } + + i = 1; + for (int j = fp->ofdm_symbol_size-1; j > fp->ofdm_symbol_size/2-1; j--) { + timeshift_symbol_rotation = fp->timeshift_symbol_rotation[0]; + f = -fd * i; + t0 = Ncp0 / 8; + poff = 2 * M_PI * -t0 * Tc * f; + exp_re = cos(poff); + exp_im = sin(-poff); + timeshift_symbol_rotation[j*2] = (int16_t)floor(exp_re * 32767); + timeshift_symbol_rotation[j*2+1] = (int16_t)floor(exp_im * 32767); + + timeshift_symbol_rotation = fp->timeshift_symbol_rotation[1]; + t0 = Ncp1 / 8; + poff = 2 * M_PI * -t0 * Tc * f; + exp_re = cos(poff); + exp_im = sin(-poff); + timeshift_symbol_rotation[j*2] = (int16_t)floor(exp_re * 32767); + timeshift_symbol_rotation[j*2+1] = (int16_t)floor(exp_im * 32767); + + if (j > fp->ofdm_symbol_size-10-1) + LOG_I(PHY,"Timeshift symbol rotation %d => (%d,%d) %f\n",-i, + fp->timeshift_symbol_rotation[1][j*2], + fp->timeshift_symbol_rotation[1][j*2+1], + poff); + i++; + } +} + int nr_layer_precoder(int16_t **datatx_F_precoding, char *prec_matrix, uint8_t n_layers, int32_t re_offset) { int32_t precodatatx_F = 0; diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index bcd20e06f3..9c77fd765d 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -346,7 +346,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - for (int symbol=0;symbolsymbol_rotation[1])[symbol + symb_offset]; ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; @@ -356,5 +356,18 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, (int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], length, 15); + + int16_t *shift_rot; + if (symb_offset+symbol == (7 * (1 << frame_parms->numerology_index))) + shift_rot = frame_parms->timeshift_symbol_rotation[0]; + else + shift_rot = frame_parms->timeshift_symbol_rotation[1]; + + multadd_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], + shift_rot, + (int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], + 1, + length, + 15); } } diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 398252c37b..bd62bd3937 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -329,6 +329,9 @@ struct NR_DL_FRAME_PARMS { /// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211 /// First dimension is for the direction of the link (0 DL, 1 UL) int16_t symbol_rotation[2][224*2]; + /// sequence used to compensate the phase rotation due to timeshifted OFDM symbols + /// First dimenstion is for different CP lengths + int16_t timeshift_symbol_rotation[2][4096*2] __attribute__ ((aligned (16))); /// shift of pilot position in one RB uint8_t nushift; /// SRS configuration from TS 38.331 RRC